Commit Graph

12 Commits

Author SHA1 Message Date
_Kerman
6e303ac0b7 test(web): cover workspace sidebar behavior 2026-08-11 15:25:11 +08:00
Tianyi Cui
25dcd7293c docs: purge chain-of-thought leakage from prose
Delete design-session citations (decision/audit/plan ordinals, stack
positions), change narration, review choreography, and reviewer-addressed
justification from comments, JSDoc, docs, READMEs, Agent Notes, tests, and
generator templates; restate every affected fact as current-state contract
prose. Fix generated docs at their sources and regenerate the catalogs and
cordis-surface regions; re-paste type-equiv blocks; update every bilingual
counterpart and re-record the pairs. Record the citation rule in the
committed-artifact-citations Agent Note.
2026-08-09 21:10:59 +08:00
creatixchu
86514f2921 Merge origin/master into worktree/sidebar-scrollbar-reveal
#1381 landed the bar's horizontal position; this branch decides when it is
drawn. The e2e keeps both scenarios and the golden carries both palettes'
pointer-state readings alongside the new edge-offset lines.
2026-08-04 15:46:53 +08:00
creatixchu
10ce8d8a45 fix(web): decide the sidebar's pointer leave by geometry, and tighten the gate
Review findings from the first round:

- ui-settings renders its full-viewport panel as a fixed-position DESCENDANT
  of the sidebar column, so `pointerleave` never fires when the pointer moves
  onto it and the bars stayed drawn after it closed. Leaving is now decided
  against the column's box from a document-level pointermove that exists only
  while the bars are drawn; the element's own leave stays for the pointer that
  leaves the window.
- The rebind gate judges the rule rather than each declaration, so a pair that
  mixes `transparent` with an l2 hover no longer passes, and the elevation
  half compares whole values instead of token shape.
- Hiding no longer exempts a sheet from the elevated-surface rebind check.
- The e2e polls the reveal before reading a colour for the golden, and pins
  that a pointerless scroll draws no thumb.
2026-08-04 15:42:39 +08:00
creatixchu
a030397aca feat(web): draw the sidebar's scrollbar only under the pointer
The session list overflows after a handful of sessions, and its scrollbar
was drawn permanently in a column that is at rest most of the time.

SidebarRoot now tracks the pointer over the whole column and rebinds
ui-theme's scrollbar indirection pair to `transparent` while it is
outside, keeping the thumb for 2s after the pointer leaves so it does not
blink out on the way past. Rebinding colour leaves the list's
`scrollbar-gutter: stable` reservation in force, so revealing the bar
moves no row.

ui-theme's gate now states the widened contract: a rebind targets an -l2
token pair or `transparent`, and nothing else.
2026-08-04 15:05:32 +08:00
_Kerman
369fad9faf fix(web): inset sidebar scrollbar by 2px 2026-08-04 14:56:30 +08:00
_Kerman
c1ac85c15f fix(web): keep sidebar scrollbar inside inset 2026-08-04 14:11:54 +08:00
imccyu
d9fa79a1e1 test(web): pin browser replay locale 2026-07-30 11:39:11 +08:00
Chinesezjc
4265ac876c fix(client): rebind the scrollbar indirection on three missed elevated surfaces
Review found three scroll containers sitting on surfaces the rebinding
contract covers, none of which rebound: ui-primitives' shared Menu card
on --dsw-specific-menu (the surface PopupSelectView already rebinds for),
and the composer input and question composer cards, both on
--dsw-specific-input-major. Each rendered the l1 thumb, which differs
from l2 only in the dark palette and only on that surface, so a
light-palette screenshot and a code read both look correct.

Adds the mechanical check that would have caught them instead of leaving
it to inspection: a sheet that scrolls somewhere and paints a known
elevated surface somewhere must rebind. The elevated set is derived from
the sheets that already rebind, since a rebinding rule paints the surface
whose elevation it declares, so a new elevated surface joins the set by
rebinding rather than by anyone updating a list. Surface-level rather than
element-level because the card and the descendant that scrolls are
separate rules and CSS text does not say which contains which. Verified by
reverting each of the three fixes in turn: the check names the sheet and
the surface every time.

Also commits snapshots/sidebar-scrollbar/geometry.expected.md, the
resolved scrollbar style and geometry in both palettes. The aria goldens
the other web scenarios commit cannot carry a CSS-only change, since it
alters no DOM and no accessible name and leaves their trees
byte-identical. Absolute coordinates stay out: they track font metrics and
the laid-out sidebar width, so committing them would document the platform
and force a per-platform re-record.
2026-07-28 17:42:57 +08:00
Chinesezjc
17419aa6b9 test(web): assert the timestamp occlusion the sidebar gutter fixes
The e2e measured the reserved band but never the symptom the change is
named for. Headless chromium defaults to an overlay scrollbar, which is
the configuration where a bar can cover row content at all, so the
scenario already ran in the right mode: against clean master the band is
0 and the bar covers 7px of the relative time.

Adds timeCoveredBy, the overlap between the relative time's right edge
and the range the bar occupies, taking the bar's width from the sheet
where it applies and from the UA's overlay width otherwise. Assuming 0
there would report no occlusion in precisely the state that has it.

Keeps the band assertion rather than replacing it: the two catch
different regressions. Removing only scrollbar-gutter leaves
timeCoveredBy at 0, because the bar is then 8px and the row's right
padding is also 8px, so it abuts the timestamp without covering it.
Removing the pseudo-element width as well is what produces the overlap.
Each was mutation-checked with the other assertions in its test silenced.

Records in the note that the gutter and the ::-webkit-scrollbar width are
jointly necessary against an overlay bar, measured by deleting each from
the live cascade with the other in force: either alone drops the band
from 8 to 0.
2026-07-28 17:22:09 +08:00
Chinesezjc
c3e9690b2e fix(ui-theme): gate the standard scrollbar properties behind the missing WebKit pseudo-element
A non-`auto` `scrollbar-width` or `scrollbar-color` makes Chromium and Safari
discard every `::-webkit-scrollbar*` rule for that element, including
`::-webkit-scrollbar-thumb:hover`. Declaring both unconditionally left the
hover tokens rendering nowhere: the engines implementing the hover
pseudo-element are exactly the ones the standard properties silence, and
Firefox has no hover pseudo-element to fall back on. Both hover tokens and all
four elevated surfaces' hover rebinds were therefore dead code.

Measured in chromium on probe elements with `scrollbar-gutter: stable`: an 8px
`::-webkit-scrollbar` alone reserved a 30px band, and adding
`scrollbar-width: thin` dropped it to the 10px `thin` reserves.

The standard properties now sit inside `@supports not
selector(::-webkit-scrollbar)`, so Firefox takes them and WebKit-based engines
take the pseudo-elements. The WebKit rules stay ungated: an engine without
those pseudo-elements drops them as unknown selectors, and gating them would
hide them from an engine that implements them without `selector()` — the
pre-16.4 Safari the ungated form serves correctly.

Three unit assertions pin the split by source offset, which the existing
at-rule-flattening parser cannot see. The web e2e now reads the path chromium
actually takes: the `auto` standard properties as the gate's signature, the
pseudo-element sizing and track, the indirection variables resolved per
throwaway probe, and the hover declaration as cascade rule text — chromium
folds the `:hover` rule into `getComputedStyle(el,
'::-webkit-scrollbar-thumb')`, so no computed query separates the states.
2026-07-28 15:02:20 +08:00
Chinesezjc
662089dd76 fix(client): theme the scrollbars and reserve the workspace list gutter
design-platform.css declared four --dsw-alias-scrollbar-* tokens in both
palettes that no rule read, so every scrolling region rendered the user
agent's own scrollbar and the dark theme showed a light native bar against
dark surfaces.

The symptom that surfaced the gap was in the sidebar: the workspace
browser's session list is its only scrolling region, and each row's
trailing content (the relative timestamp, and the hover action buttons
that replace it) is `flex: none` flush against the row's 8px right
padding, so an overlaid scrollbar painted on top of the timestamp.

ui-theme/styles/scrollbar.css becomes the sole consumer of the four
tokens, imported by the web shell's base.css after design-platform.css
because it reads that sheet's tokens. The rules sit on `body`, not
`html`: the alias tokens are declared on `body`, custom properties
inherit only downward, and from `html` they resolve to the
guaranteed-invalid value with scrollbar-color computing to `auto`.
scrollbar-width and scrollbar-color are declared on `body, body *` rather
than inherited, because inheritance would carry the color already
substituted at `body` and an elevated surface could not retint its own
thumb; scrollbar-width does not inherit at all.

Both the standard properties and the ::-webkit-scrollbar pseudo-elements
read one indirection pair bound to the l1 tokens, so an elevated surface
rebinds that pair to the l2 tokens once and retints both renderings. The
command popup, slash menu, model-select panel, and settings panel do so,
which gives the l2 tokens their first consumers.

WorkspaceBrowser's `.list` declares scrollbar-gutter: stable, keeping the
bar beside the rows. `stable` rather than `auto` so the reservation holds
when the list is short enough not to scroll: expanding a workspace group
would otherwise shift every row sideways at the moment it starts
scrolling.
2026-07-28 11:02:11 +08:00