diff --git a/client/web/src/repo/RepoRevisionSidebar.module.scss b/client/web/src/repo/RepoRevisionSidebar.module.scss index 2bbfee4d0564..9a679910a9c9 100644 --- a/client/web/src/repo/RepoRevisionSidebar.module.scss +++ b/client/web/src/repo/RepoRevisionSidebar.module.scss @@ -15,8 +15,6 @@ height: 2rem; z-index: 1; isolation: isolate; - border-bottom-left-radius: 0; - border-top-left-radius: 0; color: var(--icon-color); background-color: var(--body-bg); diff --git a/client/web/src/repo/RepoRevisionSidebar.tsx b/client/web/src/repo/RepoRevisionSidebar.tsx index 2bc2bd0c2391..aa73e4f310ed 100644 --- a/client/web/src/repo/RepoRevisionSidebar.tsx +++ b/client/web/src/repo/RepoRevisionSidebar.tsx @@ -1,6 +1,6 @@ import { type FC, useCallback, useState } from 'react' -import { mdiChevronDoubleRight, mdiChevronDoubleLeft } from '@mdi/js' +import { mdiChevronDoubleLeft, mdiPageLayoutSidebarRight } from '@mdi/js' import classNames from 'classnames' import type { Scalars } from '@sourcegraph/shared/src/graphql-operations' @@ -12,7 +12,6 @@ import type { RepoFile } from '@sourcegraph/shared/src/util/url' import { Button, useLocalStorage, - useMatchMedia, Tab, TabList, TabPanel, @@ -23,7 +22,6 @@ import { Tooltip, } from '@sourcegraph/wildcard' -import settingsSchemaJSON from '../../../../schema/settings.schema.json' import type { AuthenticatedUser } from '../auth' import { useFeatureFlag } from '../featureFlags/useFeatureFlag' import { GettingStartedTour } from '../tour/GettingStartedTour' @@ -41,28 +39,22 @@ interface RepoRevisionSidebarProps extends RepoFile, TelemetryProps, SettingsCas className: string authenticatedUser: AuthenticatedUser | null isSourcegraphDotCom: boolean + isVisible: boolean + handleSidebarToggle: (value: boolean) => void } const SIZE_STORAGE_KEY = 'repo-revision-sidebar' const TABS_KEY = 'repo-revision-sidebar-last-tab' -const SIDEBAR_KEY = 'repo-revision-sidebar-toggle' /** * The sidebar for a specific repo revision that shows the list of files and directories. */ export const RepoRevisionSidebar: FC = props => { const [persistedTabIndex, setPersistedTabIndex] = useLocalStorage(TABS_KEY, 0) - const [persistedIsVisible, setPersistedIsVisible] = useLocalStorage( - SIDEBAR_KEY, - settingsSchemaJSON.properties.fileSidebarVisibleByDefault.default - ) const showOnboardingTour = useShowOnboardingTour({ authenticatedUser: props.authenticatedUser, isSourcegraphDotCom: props.isSourcegraphDotCom, }) - const isWideScreen = useMatchMedia('(min-width: 768px)', false) - const [isVisible, setIsVisible] = useState(persistedIsVisible && isWideScreen) - const [initialFilePath, setInitialFilePath] = useState(props.filePath) const [initialFilePathIsDir, setInitialFilePathIsDir] = useState(props.isDir) const onExpandParent = useCallback((parent: string) => { @@ -70,17 +62,6 @@ export const RepoRevisionSidebar: FC = props => { setInitialFilePathIsDir(true) }, []) - const handleSidebarToggle = useCallback( - (value: boolean) => { - props.telemetryService.log('FileTreeViewClicked', { - action: 'click', - label: 'expand / collapse file tree view', - }) - setPersistedIsVisible(value) - setIsVisible(value) - }, - [setPersistedIsVisible, props.telemetryService] - ) const handleSymbolClick = useCallback( () => props.telemetryService.log('SymbolTreeViewClicked'), [props.telemetryService] @@ -94,7 +75,7 @@ export const RepoRevisionSidebar: FC = props => { return ( <> - {isVisible ? ( + {props.isVisible && ( = props => { - )} {enableBlobPageSwitchAreasShortcuts && ( @@ -206,7 +173,7 @@ export const RepoRevisionSidebar: FC = props => { {...keybinding} allowDefault={true} onMatch={() => { - handleSidebarToggle(true) + props.handleSidebarToggle(true) setPersistedTabIndex(0) setFileTreeFocusKey(Date.now().toString()) }} @@ -218,7 +185,7 @@ export const RepoRevisionSidebar: FC = props => { {...keybinding} allowDefault={true} onMatch={() => { - handleSidebarToggle(true) + props.handleSidebarToggle(true) setPersistedTabIndex(1) setSymbolsFocusKey(Date.now().toString()) }} diff --git a/client/web/src/repo/RepositoryFileTreePage.tsx b/client/web/src/repo/RepositoryFileTreePage.tsx index 9a1740fe86da..6e6a0246072e 100644 --- a/client/web/src/repo/RepositoryFileTreePage.tsx +++ b/client/web/src/repo/RepositoryFileTreePage.tsx @@ -1,4 +1,4 @@ -import type { FC } from 'react' +import { FC, useCallback, useState } from 'react' import { Navigate, useLocation } from 'react-router-dom' @@ -6,8 +6,9 @@ import { appendLineRangeQueryParameter } from '@sourcegraph/common' import { TraceSpanProvider } from '@sourcegraph/observability-client' import { getModeFromPath } from '@sourcegraph/shared/src/languages' import { isLegacyFragment, parseQueryAndHash, toRepoURL } from '@sourcegraph/shared/src/util/url' -import { LoadingSpinner } from '@sourcegraph/wildcard' +import { LoadingSpinner, useLocalStorage, useMatchMedia } from '@sourcegraph/wildcard' +import settingsSchemaJSON from '../../../../schema/settings.schema.json' import { ErrorBoundary } from '../components/ErrorBoundary' import type { SourcegraphContext } from '../jscontext' import type { NotebookProps } from '../notebooks' @@ -58,6 +59,27 @@ export const RepositoryFileTreePage: FC = props => return } + const SIDEBAR_KEY = 'repo-revision-sidebar-toggle' + + const [persistedIsVisible, setPersistedIsVisible] = useLocalStorage( + SIDEBAR_KEY, + settingsSchemaJSON.properties.fileSidebarVisibleByDefault.default + ) + const isWideScreen = useMatchMedia('(min-width: 768px)', false) + const [isVisible, setIsVisible] = useState(persistedIsVisible && isWideScreen) + + const handleSidebarToggle = useCallback( + (value: boolean) => { + props.telemetryService.log('FileTreeViewClicked', { + action: 'click', + label: 'expand / collapse file tree view', + }) + setPersistedIsVisible(value) + setIsVisible(value) + }, + [setPersistedIsVisible, props.telemetryService] + ) + // For blob pages with legacy URL fragment hashes like "#L17:19-21:23$foo:bar" // redirect to the modern URL fragment hashes like "#L17:19-21:23&tab=foo:bar" if (!hideRepoRevisionContent && objectType === 'blob' && isLegacyFragment(location.hash)) { @@ -86,6 +108,8 @@ export const RepositoryFileTreePage: FC = props => repoName={repoName} isDir={objectType === 'tree'} defaultBranch={resolvedRevision?.defaultBranch || 'HEAD'} + isVisible={isVisible} + handleSidebarToggle={handleSidebarToggle} /> {!hideRepoRevisionContent && ( <> @@ -108,6 +132,8 @@ export const RepositoryFileTreePage: FC = props => fetchHighlightedFileLineRanges={props.fetchHighlightedFileLineRanges} className={styles.pageContent} context={globalContext} + sidebarOpen={isVisible} + handleSidebarToggle={handleSidebarToggle} /> ) : resolvedRevision ? ( diff --git a/client/web/src/repo/blob/BlobPage.tsx b/client/web/src/repo/blob/BlobPage.tsx index 94e87886ac02..29a3201da131 100644 --- a/client/web/src/repo/blob/BlobPage.tsx +++ b/client/web/src/repo/blob/BlobPage.tsx @@ -111,6 +111,8 @@ interface BlobPageProps repoID?: Scalars['ID'] repoUrl?: string repoServiceType?: string + sidebarOpen: boolean + handleSidebarToggle: (value: boolean) => void fetchHighlightedFileLineRanges: (parameters: FetchFileParameters, force?: boolean) => Observable className?: string @@ -454,6 +456,8 @@ export const BlobPage: React.FunctionComponent = ({ className, co revision={revision} filePath={filePath} enableOwnershipPanel={enableOwnershipPanel} + sidebarOpen={props.sidebarOpen} + handleSidebarToggle={props.handleSidebarToggle} /> )} diff --git a/client/web/src/repo/blob/own/HistoryAndOwnBar.module.scss b/client/web/src/repo/blob/own/HistoryAndOwnBar.module.scss index d5c0bf9a1890..32e6922cf9a5 100644 --- a/client/web/src/repo/blob/own/HistoryAndOwnBar.module.scss +++ b/client/web/src/repo/blob/own/HistoryAndOwnBar.module.scss @@ -12,7 +12,7 @@ .history-panel { padding: 0; display: flex; - align-items: stretch; + align-items: center; vertical-align: middle; font-weight: normal; letter-spacing: normal; @@ -28,11 +28,28 @@ .history { min-width: 0; + justify-content: center; padding: 0; font-size: 0.75rem; flex-shrink: 1000000; // Very high value to shrink this before shrinking the ownership side. } +.toggle { + display: flex; + justify-content: center; + left: 0; + width: 2rem; + height: 2rem; + z-index: 1; + isolation: isolate; + color: var(--icon-color); + background-color: var(--body-bg); + + &:hover { + background-color: var(--color-bg-3); + } +} + .own { padding: 0; display: flex; diff --git a/client/web/src/repo/blob/own/HistoryAndOwnBar.tsx b/client/web/src/repo/blob/own/HistoryAndOwnBar.tsx index a9800bcb9386..63a12ce10292 100644 --- a/client/web/src/repo/blob/own/HistoryAndOwnBar.tsx +++ b/client/web/src/repo/blob/own/HistoryAndOwnBar.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useEffect } from 'react' -import { mdiAccount } from '@mdi/js' +import { mdiAccount, mdiChevronDoubleRight, mdiPageLayoutSidebarLeft } from '@mdi/js' import classNames from 'classnames' import { useNavigate } from 'react-router-dom' @@ -23,7 +23,9 @@ export const HistoryAndOwnBar: React.FunctionComponent<{ revision?: string filePath: string enableOwnershipPanel: boolean -}> = ({ repoID, revision, filePath, enableOwnershipPanel }) => { + sidebarOpen: boolean + handleSidebarToggle: (value: boolean) => void +}> = ({ repoID, revision, filePath, enableOwnershipPanel, sidebarOpen, handleSidebarToggle }) => { const navigate = useNavigate() const openOwnershipPanel = useCallback(() => { @@ -86,17 +88,31 @@ export const HistoryAndOwnBar: React.FunctionComponent<{
{history && (
+ {!sidebarOpen && ( + + + + )} +