Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit 6c985d2

Browse files
web: collapse navbar on smaller screens than before (#42057)
1 parent f7920c2 commit 6c985d2

12 files changed

+153
-434
lines changed

client/web/src/Layout.tsx

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ import { Settings } from '@sourcegraph/shared/src/schema/settings.schema'
1818
import { SettingsCascadeProps } from '@sourcegraph/shared/src/settings/settings'
1919
import { TelemetryProps } from '@sourcegraph/shared/src/telemetry/telemetryService'
2020
import { parseQueryAndHash } from '@sourcegraph/shared/src/util/url'
21-
import { LoadingSpinner, Panel, useObservable } from '@sourcegraph/wildcard'
21+
import { LoadingSpinner, Panel } from '@sourcegraph/wildcard'
2222

23-
import { AuthenticatedUser, authRequired as authRequiredObservable } from './auth'
23+
import { AuthenticatedUser } from './auth'
2424
import { BatchChangesProps } from './batches'
2525
import { CodeIntelligenceProps } from './codeintel'
2626
import { communitySearchContextsRoutes } from './communitySearchContexts/routes'
@@ -122,7 +122,6 @@ const CONTRAST_COMPLIANT_CLASSNAME = 'theme-contrast-compliant-syntax-highlighti
122122
export const Layout: React.FunctionComponent<React.PropsWithChildren<LayoutProps>> = props => {
123123
const routeMatch = props.routes.find(({ path, exact }) => matchPath(props.location.pathname, { path, exact }))?.path
124124
const isSearchRelatedPage = (routeMatch === '/:repoRevAndRest+' || routeMatch?.startsWith('/search')) ?? false
125-
const minimalNavLinks = routeMatch === '/cncf'
126125
const isSearchHomepage = props.location.pathname === '/search' && !parseSearchURLQuery(props.location.search)
127126
const isSearchConsolePage = routeMatch?.startsWith('/search/console')
128127
const isSearchNotebooksPage = routeMatch?.startsWith(PageRoutes.Notebooks)
@@ -154,8 +153,6 @@ export const Layout: React.FunctionComponent<React.PropsWithChildren<LayoutProps
154153
// and preserve autofocus for first textarea at survey page, creation UI etc.
155154
const isSearchAutoFocusRequired = routeMatch === PageRoutes.Survey || routeMatch === EnterprisePageRoutes.Insights
156155

157-
const authRequired = useObservable(authRequiredObservable)
158-
159156
const themeProps = useThemeProps()
160157
const [enableContrastCompliantSyntaxHighlighting] = useFeatureFlag('contrast-compliant-syntax-highlighting')
161158

@@ -218,25 +215,17 @@ export const Layout: React.FunctionComponent<React.PropsWithChildren<LayoutProps
218215
<GlobalNavbar
219216
{...props}
220217
{...themeProps}
221-
authRequired={!!authRequired}
222218
showSearchBox={
223219
isSearchRelatedPage &&
224220
!isSearchHomepage &&
225221
!isCommunitySearchContextPage &&
226222
!isSearchConsolePage &&
227223
!isSearchNotebooksPage
228224
}
229-
variant={
230-
isSearchHomepage
231-
? 'low-profile'
232-
: isCommunitySearchContextPage
233-
? 'low-profile-with-logo'
234-
: 'default'
235-
}
236-
minimalNavLinks={minimalNavLinks}
237225
isSearchAutoFocusRequired={!isSearchAutoFocusRequired}
238226
isRepositoryRelatedPage={isRepositoryRelatedPage}
239227
showKeyboardShortcutsHelp={showKeyboardShortcutsHelp}
228+
enableLegacyExtensions={window.context.enableLegacyExtensions}
240229
/>
241230
)}
242231
{needsSiteInit && !isSiteInit && <Redirect to="/site-admin/init" />}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { action } from '@storybook/addon-actions'
2+
3+
import { Activation } from '@sourcegraph/shared/src/components/activation/Activation'
4+
import { Link } from '@sourcegraph/wildcard'
5+
6+
export const baseActivation = (): Activation => ({
7+
steps: [
8+
{
9+
id: 'ConnectedCodeHost',
10+
title: 'Add repositories',
11+
detail: 'Configure Sourcegraph to talk to your code host and fetch a list of your repositories.',
12+
},
13+
{
14+
id: 'DidSearch',
15+
title: 'Search your code',
16+
detail: (
17+
<span>
18+
Head to the <Link to="/search">homepage</Link> and perform a search query on your code.{' '}
19+
<strong>Example:</strong> type 'lang:' and select a language
20+
</span>
21+
),
22+
},
23+
{
24+
id: 'FoundReferences',
25+
title: 'Find some references',
26+
detail:
27+
'To find references of a token, navigate to a code file in one of your repositories, hover over a token to activate the tooltip, and then click "Find references".',
28+
},
29+
{
30+
id: 'EnabledSharing',
31+
title: 'Configure SSO or share with teammates',
32+
detail: 'Configure a single-sign on (SSO) provider or have at least one other teammate sign up.',
33+
},
34+
],
35+
refetch: action('Refetch'),
36+
update: action('Update'),
37+
completed: undefined,
38+
})

client/web/src/components/ActivationDropdown/ActivationDropdown.story.tsx

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,13 @@
1-
import { action } from '@storybook/addon-actions'
21
import { DecoratorFn, Meta, Story } from '@storybook/react'
32
import * as H from 'history'
43

54
import { subtypeOf } from '@sourcegraph/common'
6-
import { Activation } from '@sourcegraph/shared/src/components/activation/Activation'
7-
import { Link } from '@sourcegraph/wildcard'
85

96
import { WebStory } from '../WebStory'
107

118
import { ActivationDropdown, ActivationDropdownProps } from './ActivationDropdown'
9+
import { baseActivation } from './ActivationDropdown.fixtures'
1210

13-
const baseActivation = (): Activation => ({
14-
steps: [
15-
{
16-
id: 'ConnectedCodeHost',
17-
title: 'Add repositories',
18-
detail: 'Configure Sourcegraph to talk to your code host and fetch a list of your repositories.',
19-
},
20-
{
21-
id: 'DidSearch',
22-
title: 'Search your code',
23-
detail: (
24-
<span>
25-
Head to the <Link to="/search">homepage</Link> and perform a search query on your code.{' '}
26-
<strong>Example:</strong> type 'lang:' and select a language
27-
</span>
28-
),
29-
},
30-
{
31-
id: 'FoundReferences',
32-
title: 'Find some references',
33-
detail:
34-
'To find references of a token, navigate to a code file in one of your repositories, hover over a token to activate the tooltip, and then click "Find references".',
35-
},
36-
{
37-
id: 'EnabledSharing',
38-
title: 'Configure SSO or share with teammates',
39-
detail: 'Configure a single-sign on (SSO) provider or have at least one other teammate sign up.',
40-
},
41-
],
42-
refetch: action('Refetch'),
43-
update: action('Update'),
44-
completed: undefined,
45-
})
4611
const history = H.createMemoryHistory({ keyLength: 0 })
4712
const commonProps = subtypeOf<Partial<ActivationDropdownProps>>()({
4813
alwaysShow: true,

client/web/src/components/WebStory.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@ if (!window.context) {
2121
window.context = {} as SourcegraphContext & Mocha.SuiteFunction
2222
}
2323

24+
export type WebStoryChildrenProps = ThemeProps &
25+
BreadcrumbSetters &
26+
BreadcrumbsProps &
27+
TelemetryProps &
28+
RouteComponentProps<any>
29+
2430
export interface WebStoryProps
2531
extends Omit<MemoryRouterProps, 'children'>,
2632
Pick<MockedStoryProviderProps, 'mocks' | 'useStrictMocking'> {
27-
children: React.FunctionComponent<
28-
ThemeProps & BreadcrumbSetters & BreadcrumbsProps & TelemetryProps & RouteComponentProps<any>
29-
>
33+
children: React.FunctionComponent<WebStoryChildrenProps>
3034
}
3135

3236
/**
Lines changed: 63 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import React from 'react'
2-
31
import { DecoratorFn, Meta, Story } from '@storybook/react'
42
import { createMemoryHistory } from 'history'
53

@@ -11,22 +9,19 @@ import {
119
} from '@sourcegraph/shared/src/testing/searchContexts/testHelpers'
1210
import { extensionsController } from '@sourcegraph/shared/src/testing/searchTestHelpers'
1311
import { ThemeProps } from '@sourcegraph/shared/src/theme'
12+
import { Grid, H3 } from '@sourcegraph/wildcard'
1413

1514
import { AuthenticatedUser } from '../auth'
15+
import { baseActivation } from '../components/ActivationDropdown/ActivationDropdown.fixtures'
1616
import { WebStory } from '../components/WebStory'
1717
import { useExperimentalFeatures } from '../stores'
1818
import { ThemePreference } from '../theme'
1919

20-
import { GlobalNavbar } from './GlobalNavbar'
20+
import { GlobalNavbar, GlobalNavbarProps } from './GlobalNavbar'
2121

2222
const history = createMemoryHistory()
2323

24-
const defaultProps = (
25-
props: ThemeProps
26-
): Omit<
27-
React.ComponentProps<typeof GlobalNavbar>,
28-
'authenticatedUser' | 'variant' | 'showSearchBox' | 'authRequired'
29-
> => ({
24+
const getDefaultProps = (props: ThemeProps): GlobalNavbarProps => ({
3025
isSourcegraphDotCom: false,
3126
settingsCascade: {
3227
final: null,
@@ -44,83 +39,82 @@ const defaultProps = (
4439
setSelectedSearchContextSpec: () => undefined,
4540
defaultSearchContextSpec: '',
4641
isLightTheme: props.isLightTheme,
47-
searchContextsEnabled: true,
48-
batchChangesEnabled: true,
49-
batchChangesExecutionEnabled: true,
50-
batchChangesWebhookLogsEnabled: true,
42+
searchContextsEnabled: false,
43+
batchChangesEnabled: false,
44+
batchChangesExecutionEnabled: false,
45+
batchChangesWebhookLogsEnabled: false,
5146
activation: undefined,
5247
routes: [],
5348
fetchAutoDefinedSearchContexts: mockFetchAutoDefinedSearchContexts(),
5449
fetchSearchContexts: mockFetchSearchContexts,
5550
getUserSearchContextNamespaces: mockGetUserSearchContextNamespaces,
5651
showKeyboardShortcutsHelp: () => undefined,
52+
showSearchBox: false,
53+
authenticatedUser: null,
5754
})
5855

56+
const allNavItemsProps: Partial<GlobalNavbarProps> = {
57+
searchContextsEnabled: true,
58+
batchChangesEnabled: true,
59+
batchChangesExecutionEnabled: true,
60+
batchChangesWebhookLogsEnabled: true,
61+
codeInsightsEnabled: true,
62+
enableLegacyExtensions: true,
63+
}
64+
65+
const allAuthenticatedNavItemsProps: Partial<GlobalNavbarProps> = {
66+
activation: { ...baseActivation(), completed: { ConnectedCodeHost: true, DidSearch: false } },
67+
authenticatedUser: {
68+
username: 'alice',
69+
organizations: { nodes: [{ id: 'acme', name: 'acme' }] },
70+
siteAdmin: true,
71+
} as AuthenticatedUser,
72+
}
73+
5974
const decorator: DecoratorFn = Story => {
6075
useExperimentalFeatures.setState({ codeMonitoring: true })
61-
return <Story />
76+
77+
return (
78+
<WebStory>
79+
{props => (
80+
<div className="mt-3">
81+
<Story args={getDefaultProps(props)} />
82+
</div>
83+
)}
84+
</WebStory>
85+
)
6286
}
6387

6488
const config: Meta = {
6589
title: 'web/nav/GlobalNav',
6690
decorators: [decorator],
91+
parameters: {
92+
chromatic: {
93+
disableSnapshot: false,
94+
viewports: [320, 576, 978],
95+
},
96+
},
6797
}
6898

6999
export default config
70100

71-
export const AnonymousViewer: Story = () => (
72-
<WebStory>
73-
{webProps => (
74-
<GlobalNavbar
75-
{...defaultProps(webProps)}
76-
authRequired={false}
77-
authenticatedUser={null}
78-
variant="default"
79-
showSearchBox={false}
80-
/>
81-
)}
82-
</WebStory>
83-
)
84-
85-
AnonymousViewer.storyName = 'Anonymous viewer'
86-
87-
export const AuthRequired: Story = () => (
88-
<WebStory>
89-
{webProps => (
90-
<GlobalNavbar
91-
{...defaultProps(webProps)}
92-
authRequired={true}
93-
authenticatedUser={null}
94-
variant="default"
95-
showSearchBox={false}
96-
/>
97-
)}
98-
</WebStory>
99-
)
100-
101-
AuthRequired.storyName = 'Auth required'
102-
103-
export const AuthenticatedViewer: Story = () => (
104-
<WebStory>
105-
{webProps => (
106-
<GlobalNavbar
107-
{...defaultProps(webProps)}
108-
authRequired={false}
109-
authenticatedUser={
110-
{ username: 'alice', organizations: { nodes: [{ name: 'acme' }] } } as AuthenticatedUser
111-
}
112-
variant="default"
113-
showSearchBox={false}
114-
/>
115-
)}
116-
</WebStory>
101+
export const Default: Story<GlobalNavbarProps> = props => (
102+
<Grid columnCount={1}>
103+
<div>
104+
<H3 className="ml-2">Anonymous viewer</H3>
105+
<GlobalNavbar {...props} />
106+
</div>
107+
<div>
108+
<H3 className="ml-2">Anonymous viewer with all possible nav items</H3>
109+
<GlobalNavbar {...props} {...allNavItemsProps} />
110+
</div>
111+
<div>
112+
<H3 className="ml-2">Authenticated user with all possible nav items</H3>
113+
<GlobalNavbar {...props} {...allNavItemsProps} {...allAuthenticatedNavItemsProps} />
114+
</div>
115+
<div>
116+
<H3 className="ml-2">Authenticated user with all possible nav items and search input</H3>
117+
<GlobalNavbar {...props} {...allNavItemsProps} {...allAuthenticatedNavItemsProps} showSearchBox={true} />
118+
</div>
119+
</Grid>
117120
)
118-
119-
AuthenticatedViewer.storyName = 'Authenticated viewer'
120-
121-
AuthenticatedViewer.parameters = {
122-
design: {
123-
type: 'figma',
124-
url: 'https://www.figma.com/file/SFhXbl23TJ2j5tOF51NDtF/%F0%9F%93%9AWeb?node-id=985%3A1281',
125-
},
126-
}

client/web/src/nav/GlobalNavbar.test.tsx

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ jest.mock('../components/branding/BrandLogo', () => ({ BrandLogo: 'BrandLogo' })
2222
const history = createMemoryHistory()
2323
const PROPS: React.ComponentProps<typeof GlobalNavbar> = {
2424
authenticatedUser: null,
25-
authRequired: false,
2625
extensionsController,
2726
location: createLocation('/'),
2827
history,
@@ -40,7 +39,6 @@ const PROPS: React.ComponentProps<typeof GlobalNavbar> = {
4039
selectedSearchContextSpec: '',
4140
setSelectedSearchContextSpec: () => undefined,
4241
defaultSearchContextSpec: '',
43-
variant: 'default',
4442
globbing: false,
4543
branding: undefined,
4644
routes: [],
@@ -71,13 +69,4 @@ describe('GlobalNavbar', () => {
7169
)
7270
expect(asFragment()).toMatchSnapshot()
7371
})
74-
75-
test('low-profile', () => {
76-
const { asFragment } = renderWithBrandedContext(
77-
<MockedTestProvider>
78-
<GlobalNavbar {...PROPS} variant="low-profile" />
79-
</MockedTestProvider>
80-
)
81-
expect(asFragment()).toMatchSnapshot()
82-
})
8372
})

0 commit comments

Comments
 (0)