style(desktop): sit every pane tab strip on the sidebar surface

The strips painted with `--theme-card-seed` — the raw, unmixed seed rather
than a surface token — so they read as their own band beside the sidebar and
titlebar, which share `--ui-bg-sidebar`.

Fixed at the default in `PaneTab` rather than per strip. The right-rail
preview strip never set the vars at all, so its inactive tabs fell through
to the seed even though its container was already on the sidebar surface;
correcting the fallback fixes that one for free and keeps the next strip
from regressing. With the default right, the two zone strips no longer need
to redeclare the var and paint the token directly.
This commit is contained in:
Brooklyn Nicholson 2026-07-27 18:02:20 -05:00
parent 58c8d86bd5
commit f4e042f466
2 changed files with 13 additions and 11 deletions

View file

@ -353,7 +353,7 @@ export function TreeGroup({
<ZoneMenu {...zoneMenu}>
<div
className={cn(
'flex h-full w-7 shrink-0 cursor-pointer select-none flex-col items-stretch bg-(--pane-tab-strip-bg) [--pane-tab-strip-bg:var(--theme-card-seed)]',
'flex h-full w-7 shrink-0 cursor-pointer select-none flex-col items-stretch bg-(--ui-sidebar-surface-background)',
// Strip line faces the content the zone collapsed away from.
railSide === 'right' ? PANE_TAB_STRIP_LINE_LEFT : PANE_TAB_STRIP_LINE_RIGHT
)}
@ -397,11 +397,11 @@ export function TreeGroup({
{headerVisible && (
<ZoneMenu {...zoneMenu}>
<div
// Active = sidebar surface (merges into body). Strip =
// `--theme-card-seed` (VS Code `tab.inactiveBackground`). No bottom
// rule — the active tab's primary underline is the only seam.
// Strip and active tab both sit on the sidebar surface, so the
// header reads as one piece of chrome with the titlebar above it.
// No bottom rule — the active tab's primary underline is the only seam.
// data-zone-tabstrip: a drop over here STACKS (drag-session reads it).
className="group/pane-header relative flex h-7 shrink-0 select-none bg-(--pane-tab-strip-bg) [-webkit-app-region:no-drag] [--pane-tab-active-bg:var(--ui-sidebar-surface-background)] [--pane-tab-strip-bg:var(--theme-card-seed)]"
className="group/pane-header relative flex h-7 shrink-0 select-none bg-(--ui-sidebar-surface-background) [-webkit-app-region:no-drag] [--pane-tab-active-bg:var(--ui-sidebar-surface-background)]"
data-zone-tabstrip={node.id}
onContextMenu={e => {
setMenuPane(

View file

@ -23,10 +23,12 @@ const TAB_ACTIVE = 'h-full text-foreground [--tab-bg:var(--pane-tab-active-bg,va
// so it costs no layout and can't shift the tab.
const TAB_ACTIVE_UNDERLINE = 'shadow-[inset_0_-2px_0_var(--pane-tab-active-accent,var(--theme-primary))]'
// Inactive = gutter. Hover DARKENS: active is the lighter content surface, so a
// lightening wash made the two nearly indistinguishable.
// Inactive = gutter, defaulting to the shared chrome surface so a strip that
// sets no vars still matches the sidebar/titlebar instead of falling through to
// the raw (unmixed) card seed. Hover DARKENS: surfaces this close in value need
// a darkening wash to register at all.
const TAB_IDLE =
'text-(--ui-text-tertiary) [--tab-bg:var(--pane-tab-strip-bg,var(--theme-card-seed))] hover:shadow-[inset_0_0_0_100vmax_color-mix(in_srgb,#000_var(--ui-tab-hover-darken),transparent)] hover:text-(--ui-text-secondary)'
'text-(--ui-text-tertiary) [--tab-bg:var(--pane-tab-strip-bg,var(--ui-sidebar-surface-background))] hover:shadow-[inset_0_0_0_100vmax_color-mix(in_srgb,#000_var(--ui-tab-hover-darken),transparent)] hover:text-(--ui-text-secondary)'
interface PaneTabProps extends React.ComponentProps<'div'> {
active?: boolean
@ -49,9 +51,9 @@ const isMetaClose = (event: { button: number; metaKey: boolean }) => event.butto
/**
* Editor tab shell preview rail + zone headers + collapsed vertical rails.
*
* Strip sets `--pane-tab-active-bg` (content surface) and `--pane-tab-strip-bg`
* (gutter; prefer `--theme-card-seed` = VS Code `tab.inactiveBackground`).
* Active merges into content; inactive sits flush in the gutter.
* Defaults need no vars: the active tab takes the editor surface, inactive the
* sidebar one. Override `--pane-tab-active-bg` to change what the active tab
* merges into, `--pane-tab-strip-bg` for a gutter unlike the bar around it.
*/
export const PaneTab = React.forwardRef<HTMLDivElement, PaneTabProps>(function PaneTab(
{