sidebar: VSCode-style drag-to-edge splitting, collapse instead of close, theme-compliant tokens
- Split panes by dragging a tab to a pane edge (left/right/up/down zones with a drop overlay) or into the center to merge; the toolbar split buttons are gone (split-pane.tsx, state.ts moveTabToEdge/insertLeafAt). - The header close button is now a collapse button; the expand button on the right edge stays visible whenever the panel is collapsed, so the sidebar can always be reopened (Sidebar.tsx, locales collapse/expand). - Styles now follow the DSH web-styling rules exactly: --dsw-alias-* semantic colors (state-error/warn tokens), --dsw-font-* typography roles (size + line-height paired), --dsw-shadow-lv* elevation, no color literals or static palette values (sidebar.module.css). - Tests: +3 for moveTabToEdge (edge split, center merge, self reorder).
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
/**
|
||||
* Sidebar styles: everything rides the DSH theme tokens (--dsw-alias-*,
|
||||
* --dsw-static-*, --ds-transition-*) so the plugin matches the host UI in
|
||||
* both light and dark themes, plus a few absolute z-indexes for the
|
||||
* document-level overlay (below the app's modal layer).
|
||||
* Sidebar styles. Per the DSH web-styling rules every visual value rides the
|
||||
* theme: --dsw-alias-* semantic tokens for colors, --dsw-font-* typography
|
||||
* roles (size paired with line-height), --dsw-shadow-* for elevation, and
|
||||
* --ds-* for motion. No static palette values, no color literals, no theme
|
||||
* selectors — light/dark adaptation is the theme package's job.
|
||||
*/
|
||||
|
||||
/* ── Shell ─────────────────────────────────────────────────────────────── */
|
||||
@@ -21,14 +22,15 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 22px;
|
||||
height: 56px;
|
||||
width: 26px;
|
||||
height: 64px;
|
||||
border: 1px solid var(--dsw-alias-border-l2-darkmode-thin);
|
||||
border-right: none;
|
||||
border-radius: 10px 0 0 10px;
|
||||
background: var(--dsw-alias-button-floating-fill);
|
||||
color: var(--dsw-alias-label-secondary);
|
||||
cursor: pointer;
|
||||
box-shadow: var(--dsw-shadow-lv1);
|
||||
transition:
|
||||
background var(--ds-transition-duration-slow) var(--ds-ease-in-out),
|
||||
color var(--ds-transition-duration-slow) var(--ds-ease-in-out);
|
||||
@@ -54,7 +56,7 @@
|
||||
flex-direction: column;
|
||||
background: var(--dsw-alias-bg-layer-1);
|
||||
border-left: 1px solid var(--dsw-alias-border-l2);
|
||||
box-shadow: -8px 0 24px rgba(0, 0, 0, 0.08);
|
||||
box-shadow: var(--dsw-shadow-lv2);
|
||||
}
|
||||
|
||||
.panelResize {
|
||||
@@ -83,8 +85,7 @@
|
||||
}
|
||||
|
||||
.panelTitle {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
font: var(--dsw-font-xxs-strong-12);
|
||||
color: var(--dsw-alias-label-secondary);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -178,6 +179,7 @@
|
||||
}
|
||||
|
||||
.pane {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
@@ -191,6 +193,53 @@
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
/* VSCode-style drag-to-edge drop zones (25% edges, 50% center). */
|
||||
.dropOverlay {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
pointer-events: none;
|
||||
background: var(--dsw-alias-interactive-bg-hover-accent);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.dropLeft {
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.dropRight {
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.dropUp {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 25%;
|
||||
}
|
||||
|
||||
.dropDown {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 25%;
|
||||
}
|
||||
|
||||
.dropCenter {
|
||||
left: 25%;
|
||||
right: 25%;
|
||||
top: 25%;
|
||||
bottom: 25%;
|
||||
background: transparent;
|
||||
outline: 2px dashed var(--dsw-alias-interactive-bg-hover-accent);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.paneContent {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
@@ -206,7 +255,7 @@
|
||||
justify-content: center;
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
}
|
||||
|
||||
@@ -246,7 +295,7 @@
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 0 4px 0 10px;
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-label-secondary);
|
||||
border-right: 1px solid var(--dsw-alias-border-l1);
|
||||
background: transparent;
|
||||
@@ -338,8 +387,7 @@
|
||||
}
|
||||
|
||||
.explorerRoot {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
font: var(--dsw-font-xxs-strong-12);
|
||||
color: var(--dsw-alias-label-secondary);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -362,7 +410,7 @@
|
||||
padding: 0 8px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-label-primary);
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
@@ -374,7 +422,7 @@
|
||||
}
|
||||
|
||||
.explorerDir {
|
||||
font-weight: 500;
|
||||
font: var(--dsw-font-xxs-strong-12);
|
||||
}
|
||||
|
||||
.explorerHidden {
|
||||
@@ -387,13 +435,14 @@
|
||||
}
|
||||
|
||||
.explorerError {
|
||||
color: var(--dsw-static-red-500, #ef4444);
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-state-error-primary);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.explorerEmpty {
|
||||
padding: 16px;
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
text-align: center;
|
||||
}
|
||||
@@ -419,8 +468,7 @@
|
||||
.editorTitle {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
font: var(--dsw-font-xxs-strong-12);
|
||||
color: var(--dsw-alias-label-secondary);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -428,19 +476,19 @@
|
||||
}
|
||||
|
||||
.editorStatus {
|
||||
font-size: 11px;
|
||||
font: var(--dsw-font-xxxs-11);
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
}
|
||||
|
||||
.editorStatusError {
|
||||
color: var(--dsw-static-red-500, #ef4444);
|
||||
color: var(--dsw-alias-state-error-primary);
|
||||
}
|
||||
|
||||
.dirtyDot {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
background: var(--dsw-static-amber-500, #f59e0b);
|
||||
background: var(--dsw-alias-state-warn-primary);
|
||||
flex: none;
|
||||
}
|
||||
|
||||
@@ -449,7 +497,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
@@ -457,16 +505,16 @@
|
||||
|
||||
.editorError {
|
||||
padding: 12px 16px;
|
||||
font-size: 12px;
|
||||
color: var(--dsw-static-red-500, #ef4444);
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-state-error-primary);
|
||||
}
|
||||
|
||||
.editorBanner {
|
||||
flex: none;
|
||||
padding: 4px 12px;
|
||||
font-size: 11px;
|
||||
color: var(--dsw-static-amber-600, #dd8629);
|
||||
background: var(--dsw-static-amber-100, #fef5e7);
|
||||
font: var(--dsw-font-xxxs-11);
|
||||
color: var(--dsw-alias-state-warn-label);
|
||||
background: var(--dsw-alias-state-warn-tertiary);
|
||||
}
|
||||
|
||||
.editorTextarea {
|
||||
@@ -479,9 +527,7 @@
|
||||
resize: none;
|
||||
background: transparent;
|
||||
color: var(--dsw-alias-label-primary);
|
||||
font-family: var(--dsw-font-mono, 'SF Mono', Menlo, Consolas, monospace);
|
||||
font-size: 12px;
|
||||
line-height: 1.55;
|
||||
font: var(--dsw-font-markdown-code-block-small);
|
||||
tab-size: 2;
|
||||
white-space: pre;
|
||||
}
|
||||
@@ -507,7 +553,7 @@
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
padding: 10px 14px;
|
||||
font-size: 13px;
|
||||
font: var(--dsw-font-xs-13);
|
||||
}
|
||||
|
||||
/* ── Terminal ──────────────────────────────────────────────────────────── */
|
||||
@@ -534,9 +580,9 @@
|
||||
.terminalBanner {
|
||||
flex: none;
|
||||
padding: 3px 10px;
|
||||
font-size: 11px;
|
||||
color: var(--dsw-static-amber-600, #dd8629);
|
||||
background: var(--dsw-static-amber-100, #fef5e7);
|
||||
font: var(--dsw-font-xxxs-11);
|
||||
color: var(--dsw-alias-state-warn-label);
|
||||
background: var(--dsw-alias-state-warn-tertiary);
|
||||
}
|
||||
|
||||
/* ── Git ───────────────────────────────────────────────────────────────── */
|
||||
@@ -566,7 +612,7 @@
|
||||
border-radius: 6px;
|
||||
background: var(--dsw-alias-bg-base);
|
||||
color: var(--dsw-alias-label-primary);
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
}
|
||||
|
||||
.gitSection {
|
||||
@@ -578,8 +624,7 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 6px 12px 4px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
font: var(--dsw-font-xxxs-strong-11);
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
@@ -587,7 +632,7 @@
|
||||
.gitLink {
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 11px;
|
||||
font: var(--dsw-font-xxxs-11);
|
||||
color: var(--dsw-alias-brand-primary);
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
@@ -638,8 +683,7 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
font: var(--dsw-font-xxxs-strong-11);
|
||||
background: var(--dsw-alias-interactive-bg-hover);
|
||||
color: var(--dsw-alias-label-secondary);
|
||||
}
|
||||
@@ -650,27 +694,27 @@
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-label-primary);
|
||||
}
|
||||
|
||||
.gitEmpty {
|
||||
padding: 4px 12px 8px;
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
}
|
||||
|
||||
.gitPlaceholder {
|
||||
padding: 16px;
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.gitError {
|
||||
padding: 8px 12px;
|
||||
font-size: 12px;
|
||||
color: var(--dsw-static-red-500, #ef4444);
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-state-error-primary);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
@@ -699,8 +743,8 @@
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
background: var(--dsw-alias-button-primary-fill);
|
||||
color: var(--dsw-alias-label-primary-inverted, #fff);
|
||||
font-size: 12px;
|
||||
color: var(--dsw-alias-label-primary-inverted);
|
||||
font: var(--dsw-font-xxs-strong-12);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -718,12 +762,12 @@
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
padding: 3px 12px;
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
}
|
||||
|
||||
.gitLogHash {
|
||||
flex: none;
|
||||
font-family: var(--dsw-font-mono, 'SF Mono', Menlo, Consolas, monospace);
|
||||
font: var(--dsw-font-markdown-code-block-small);
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
}
|
||||
|
||||
@@ -747,7 +791,7 @@
|
||||
}
|
||||
|
||||
.producedLabel {
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
}
|
||||
|
||||
@@ -761,7 +805,7 @@
|
||||
border-radius: 999px;
|
||||
background: var(--dsw-alias-bg-layer-2);
|
||||
color: var(--dsw-alias-label-secondary);
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -778,6 +822,6 @@
|
||||
}
|
||||
|
||||
.producedMore {
|
||||
font-size: 12px;
|
||||
font: var(--dsw-font-xxs-12);
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user