ui: align the sidebar with the app's own chrome (rows, buttons, motion)

Explorer rows become the app's tree-row cell — 34px, radius 8, inset by
the scroll padding, 22px indent step, and the session-row mount fade —
and git rows get the same cell plus the proper selected fill
(interactive-bg-active). Icon buttons switch to the app's 28px circle
pattern (ui-workspace), headers settle at the 36px section rhythm, and
keyboard focus gets a visible ring everywhere per the styling policy,
with a prefers-reduced-motion block turning off the slides and fades.
This commit is contained in:
Menghuan1918
2026-08-08 17:30:45 +08:00
parent 7aa24badf0
commit 439adf3967
2 changed files with 74 additions and 17 deletions
+5 -5
View File
@@ -66,11 +66,11 @@ export function ExplorerView(props: {
const renderLevel = (dir: string, depth: number): ReactNode => {
const level = data[dir]
if (level === undefined) {
return <div className={css.explorerRow} style={{ paddingLeft: depth * 14 + 8 }}>{t('loading')}</div>
return <div className={css.explorerRow} style={{ paddingLeft: depth * 22 + 6 }}>{t('loading')}</div>
}
if (level.error !== undefined) {
return (
<div className={clsx(css.explorerRow, css.explorerError)} style={{ paddingLeft: depth * 14 + 8 }}>
<div className={clsx(css.explorerRow, css.explorerError)} style={{ paddingLeft: depth * 22 + 6 }}>
{level.error}
</div>
)
@@ -84,7 +84,7 @@ export function ExplorerView(props: {
<button
type="button"
className={clsx(css.explorerRow, css.explorerDir, entry.hidden && css.explorerHidden)}
style={{ paddingLeft: depth * 14 + 8 }}
style={{ paddingLeft: depth * 22 + 6 }}
onClick={() => { onToggle(entry.path) }}
>
{isOpen ? <IconFolderOpen16 size={14} /> : <IconFolderClose16 size={14} />}
@@ -99,7 +99,7 @@ export function ExplorerView(props: {
key={entry.path}
type="button"
className={clsx(css.explorerRow, entry.hidden && css.explorerHidden)}
style={{ paddingLeft: depth * 14 + 8 }}
style={{ paddingLeft: depth * 22 + 6 }}
title={entry.path}
onClick={() => { onOpenFile(entry.path) }}
>
@@ -133,7 +133,7 @@ export function ExplorerView(props: {
<div className={css.explorerEmpty}>{t('noSession')}</div>
) : (
<>
<div className={css.explorerRow} style={{ paddingLeft: 8 }}>
<div className={css.explorerRow} style={{ paddingLeft: 6 }}>
<IconFolderOpen16 size={14} />
<span className={css.explorerName}>{baseName(root)}</span>
</div>
+69 -12
View File
@@ -100,7 +100,8 @@
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 6px 8px 6px 12px;
height: 36px;
padding: 0 8px 0 12px;
border-bottom: 1px solid var(--dsw-alias-border-l1);
flex: none;
}
@@ -119,17 +120,20 @@
display: flex;
}
/* Icon button: the app's own icon-button pattern (ui-workspace) — a 28px
circle, secondary label, hover fill; no border so the icon alone is the
affordance. */
.iconButton {
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
width: 28px;
height: 28px;
padding: 0;
border: none;
border-radius: 6px;
border-radius: 50%;
background: transparent;
color: var(--dsw-alias-label-tertiary);
color: var(--dsw-alias-label-secondary);
cursor: pointer;
flex: none;
}
@@ -440,7 +444,8 @@
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 6px 8px 6px 12px;
height: 36px;
padding: 0 8px 0 12px;
}
.explorerRoot {
@@ -455,16 +460,20 @@
flex: 1;
min-height: 0;
overflow-y: auto;
padding-bottom: 8px;
padding: 2px 6px 8px;
}
/* One tree row: the app's tree-row cell (34px, radius 8, inset, hover
fill, 22px indent step) with a mount fade so expanding a directory
reveals its children gently (stable keys keep existing rows from
replaying it). */
.explorerRow {
display: flex;
align-items: center;
gap: 6px;
width: 100%;
height: 24px;
padding: 0 8px;
height: 34px;
padding: 0 6px;
border: none;
background: transparent;
font: var(--dsw-font-xxs-12);
@@ -472,6 +481,8 @@
text-align: left;
cursor: pointer;
white-space: nowrap;
border-radius: 8px;
animation: dsh-row-in 150ms var(--ds-ease-in-out);
}
.explorerRow:hover {
@@ -497,6 +508,11 @@
cursor: default;
}
/* Mount fade for tree rows (the app's session-row reveal). */
@keyframes dsh-row-in {
from { opacity: 0; }
}
.explorerEmpty {
padding: 16px;
font: var(--dsw-font-xxs-12);
@@ -740,7 +756,8 @@
display: flex;
align-items: center;
gap: 8px;
padding: 6px 8px 6px 12px;
height: 36px;
padding: 0 8px 0 12px;
}
.gitBranchSelect {
@@ -791,7 +808,11 @@
display: flex;
align-items: center;
gap: 6px;
padding: 2px 8px 2px 12px;
min-height: 34px;
margin: 0 6px;
padding: 0 6px 0 12px;
border-radius: 8px;
animation: dsh-row-in 150ms var(--ds-ease-in-out);
}
.gitRow:hover {
@@ -799,7 +820,7 @@
}
.gitRowSelected {
background: var(--dsw-alias-interactive-bg-hover);
background: var(--dsw-alias-interactive-bg-active);
}
.gitRowMain {
@@ -965,3 +986,39 @@
font: var(--dsw-font-xxs-12);
color: var(--dsw-alias-label-tertiary);
}
/* ── Shared interaction rules ──────────────────────────────────────────── */
/* Keyboard focus stays visible on every interactive control (the styling
policy requires focus visibility; the accent token doubles as the ring). */
.toggleButton:focus-visible,
.iconButton:focus-visible,
.tab:focus-visible,
.tabClose:focus-visible,
.tabBarPlus:focus-visible,
.paneCard:focus-visible,
.explorerRow:focus-visible,
.gitRowMain:focus-visible,
.gitLink:focus-visible,
.gitCommitButton:focus-visible,
.terminalRetry:focus-visible,
.editorModeButton:focus-visible {
outline: 2px solid var(--dsw-alias-interactive-bg-hover-accent);
outline-offset: -1px;
}
/* Reduced motion: no slides, fades or color transitions. */
@media (prefers-reduced-motion: reduce) {
.panel,
.panelHidden,
.toggleButton,
.tab,
.tabBarPlus,
.paneCard,
.explorerRow,
.gitRow,
.divider {
transition: none;
animation: none;
}
}