fix: keep workspace file controls visible while scrolling
Scroll the file list independently so view selection, refresh, creation actions and directory navigation remain visible. Keep the selected Files entry available in projects without Git. Add component coverage and 16 Electron layout scenarios for themes, window sizes and scroll retention. Focused tests, typecheck and lint passed; the full test run timed out after 200 seconds. Release note: Workspace file controls remain visible while scrolling, and projects without Git retain the Files entry.
This commit is contained in:
@@ -211,6 +211,9 @@ describe('WorkspaceFilesPanel', () => {
|
||||
expect(css).toMatch(/\.workspace-git__toolbar > \.segmented-control\s*\{[^}]*width: max-content;[^}]*border: 0/)
|
||||
expect(css).toMatch(/\.workspace-git__branch-trigger\s*\{[^}]*width: auto;[^}]*height: 32px;[^}]*flex: 0 1 auto;[^}]*text-align: left/)
|
||||
expect(css).toMatch(/\.workspace-files__header\s*\{[^}]*justify-content: space-between/)
|
||||
expect(css).toMatch(/\.workspace-files__files-view\s*\{[^}]*flex: 1;[^}]*min-height: 0;[^}]*overflow: auto/)
|
||||
expect(css).toContain('.workspace-files__navigation:has(.workspace-files__list:not([hidden]) .workspace-files__files-view:not([hidden]))')
|
||||
expect(css).toMatch(/\.workspace-files__header,\s*\.workspace-files__actions,\s*\.workspace-files__breadcrumbs,[^{]*\{\s*flex-shrink: 0/)
|
||||
expect(css).toMatch(/\.workspace-git__branches\s*\{[^}]*width: min\(100%, 360px\);[^}]*border-radius: var\(--radius-control\)/)
|
||||
expect(css).toMatch(/\.workspace-git__branches\s*\{[^}]*position: fixed;[^}]*max-height: calc\(100vh - 32px\);[^}]*overflow: auto/)
|
||||
expect(css).toMatch(/\.workspace-git__branch-list\s*\{[^}]*max-height: 240px;[^}]*overflow: auto/)
|
||||
@@ -535,6 +538,7 @@ describe('WorkspaceFilesPanel', () => {
|
||||
)
|
||||
|
||||
await screen.findByText('工作区为空。')
|
||||
expect(screen.getByRole('button', { name: '文件' })).toHaveAttribute('aria-pressed', 'true')
|
||||
expect(onListDirectory).toHaveBeenCalledOnce()
|
||||
await changeUiLocale('en-US')
|
||||
|
||||
@@ -705,6 +709,7 @@ describe('WorkspaceFilesPanel', () => {
|
||||
expect(screen.queryByRole('status')).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('button', { name: 'Git 工作区' })).not.toBeInTheDocument()
|
||||
rerender(<WorkspaceFilesPanel {...props} isRepository={false} />)
|
||||
expect(screen.getByRole('button', { name: '文件' })).toHaveAttribute('aria-pressed', 'true')
|
||||
expect(screen.queryByRole('button', { name: 'Git 工作区' })).not.toBeInTheDocument()
|
||||
rerender(<WorkspaceFilesPanel {...props} isRepository />)
|
||||
fireEvent.click(screen.getByRole('button', { name: 'Git 工作区' }))
|
||||
|
||||
@@ -492,10 +492,10 @@ export function WorkspaceFilesPanel({
|
||||
</section>}
|
||||
<div className="workspace-files__list" hidden={showingDiff}>
|
||||
<div className="workspace-files__header">
|
||||
{showGit && <div className="workspace-files__view-switch"><SegmentedControl ariaLabel={t('files.view')} value={activeView} onChange={setView} options={[
|
||||
<div className="workspace-files__view-switch"><SegmentedControl ariaLabel={t('files.view')} value={activeView} onChange={setView} options={[
|
||||
{ value: 'files', label: t('files.filesView') },
|
||||
{ value: 'changes', label: t('management.gitWorkspace') }
|
||||
]} /></div>}
|
||||
...(showGit ? [{ value: 'changes' as const, label: t('management.gitWorkspace') }] : [])
|
||||
]} /></div>
|
||||
<button ref={refreshRef} className="icon-button" type="button" disabled={refreshing} aria-label={t('sidebar.workspace.refreshAriaLabel')} title={t('sidebar.workspace.refresh')} onClick={() => void refresh()}><RefreshCw size={14} aria-hidden="true" /></button>
|
||||
</div>
|
||||
{activeView === 'files' && root && <div className="workspace-files__toolbar workspace-files__actions">
|
||||
@@ -555,7 +555,7 @@ export function WorkspaceFilesPanel({
|
||||
</div>
|
||||
</WorkspaceGitTools>}
|
||||
</div>
|
||||
<div hidden={activeView !== 'files'}>
|
||||
<div className="workspace-files__files-view" hidden={activeView !== 'files'}>
|
||||
{loadingPaths.has(browsedPath) && !root ? (
|
||||
<p className="assistant-sidebar__empty">
|
||||
{t('files.readingWorkspace')}
|
||||
|
||||
@@ -18639,13 +18639,14 @@ textarea.field-control {
|
||||
.workspace-git__history-dock > [role="separator"] { height: var(--space-2); flex: 0 0 auto; cursor: ns-resize; touch-action: none; }
|
||||
.workspace-git__history-scroll { flex: 1; overflow: auto; min-height: 0; }
|
||||
/* Keep the history header docked even when its content is collapsed. */
|
||||
.workspace-files__navigation:has(.workspace-files__list:not([hidden]) .workspace-files__files-view:not([hidden])),
|
||||
.workspace-files__navigation:has(.workspace-files__list:not([hidden]) .workspace-files__git-view:not([hidden]) .workspace-git__working:not([hidden])) {
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.workspace-files__navigation:has(.workspace-git) .workspace-files,
|
||||
.workspace-files__navigation:has(.workspace-git) .workspace-files__list:not([hidden]),
|
||||
.workspace-files__navigation .workspace-files,
|
||||
.workspace-files__navigation .workspace-files__list:not([hidden]),
|
||||
.workspace-files__git-view:not([hidden]),
|
||||
.workspace-git,
|
||||
.workspace-git__current {
|
||||
@@ -18659,8 +18660,15 @@ textarea.field-control {
|
||||
.workspace-git__current { gap: var(--space-2); overflow: auto; }
|
||||
.workspace-git > [role="status"] { margin: 0; flex-shrink: 0; }
|
||||
.workspace-files__header,
|
||||
.workspace-files__actions,
|
||||
.workspace-files__breadcrumbs,
|
||||
.workspace-git__toolbar,
|
||||
.workspace-git__history-toggle { flex-shrink: 0; }
|
||||
.workspace-files__files-view {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
.workspace-git__changes {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
|
||||
Reference in New Issue
Block a user