Skip to content

fix(web): 130+ UI consistency fixes - #6218

Open
0x00-sys wants to merge 6 commits into
pingdotgg:mainfrom
0x00-sys:fix/web-ui-consistency
Open

fix(web): 130+ UI consistency fixes#6218
0x00-sys wants to merge 6 commits into
pingdotgg:mainfrom
0x00-sys:fix/web-ui-consistency

Conversation

@0x00-sys

@0x00-sys 0x00-sys commented Aug 11, 2026

Copy link
Copy Markdown

Problem

The web app has accumulated small UI drift: raw interactive elements missing the cursor-pointer the primitives opt into (Tailwind v4 preflight leaves buttons at cursor: default), controls with outline-none and no focus ring, seven different disabled opacities (30/40/45/50/55/60/80) against the primitives' opacity-64, popups that animate in but not out (or not at all), single-line text clipping descenders, and sibling components hand-rolling what a shared primitive already provides.

None of these are features — every change aligns an element with what its own siblings or the ui/ primitives already do. When one instance of a defect was found, the identical pattern was grepped for across the tree, so each category below is exhaustive rather than anecdotal. ~130 fixes, 87 files, +249/−283.

Fixes

1. Switch thumb flush against the track edge; unchecked state invisible in dark

The thumb had a 1px inset (p-px on a track sized thumb+2px). The track now grows 2px each way with p-0.5, giving an even 2px inset in both states — the checked translate distance is unchanged (--thumb-size − 4px before and after). Separately, the dark unchecked track was --input = white/8% under a bg-background thumb — structurally invisible. It now gets dark:data-unchecked:bg-foreground/16 plus the hairline inset-ring-white/6 edge treatment dark surfaces use elsewhere. Checked state untouched. Applied to ui/switch.tsx and the inline switch in ui/menu.tsx.

Before After

2. Descender clipping (the letter g cut off)

leading-none combined with truncate/line-clamp gives a 1em line box with overflow: hidden, so g/y/p/q tails clip at the box edge. Three real instances: the sidebar thread tooltip title (Sidebar.tsx), InputGroupText, and a copy-pasted leading-8.5 on the small NumberField (a 34px line box inside a 26px input).

Before After

3. ~60 clickable elements missing cursor-pointer

Raw <button>s and clickable labels across the sidebar, terminal drawer, pull-requests page, changed-files tree, settings, diff panel, and preview cards rendered the arrow cursor. Also fixed at the source: AutocompleteItem shipped cursor-default, which three consumers (command palette, composer command/stash menus) had each patched around locally; the base is now correct. Conditionally-clickable elements set both branches (isClickable ? "cursor-pointer" : "cursor-default").

Each clip shows nightly first, then the fixed build after the window switch:

Add-Action icon presets Sidebar PR badge
Terminal drawer buttons PR page rows + condensed filters

4. Menus and selects don't animate; popovers animate in but not out

ui/popover.tsx had data-starting-style with no data-ending-style, so popovers faded in and popped out. ui/menu.tsx and ui/select.tsx popups carried origin-(--transform-origin) but no transition at all. The combobox and autocomplete popups declared transition-[scale,opacity] with nothing driving it. All five now share the tooltip's bidirectional scale/fade. Frame-level proof: at 120Hz, nightly's menu open/close changes exactly 1 frame; fixed shows a multi-frame ramp both directions.

Before After

5. Snoozed shelf expand judders the list; Settled doesn't

The thread list FLIP-animates every moved row (auto-animate). Settled sits at the list tail, so expanding it moves nothing and looks smooth; Snoozed sits mid-list, so expanding it slides every settled row below while translucent rows cross each other. Shelf toggles now suspend the list animation for that one update (toggleShelfWithoutListAnimation in Sidebar.tsx), making both shelves behave identically. Single-row transitions — settle, wake, pin reorder — keep the animation they were designed for.

Before After

6. Autocomplete popup was the only opaque popup

Every popup surface uses dropdown-glass except the autocomplete popup (composer @-mentions, file pickers), which hand-rolled border bg-popover shadow-lg/5 — and therefore also ignored the Settings → Appearance glass controls.

Before After

7. Theme color picker cancelled its own glass

The picker painted bg-popover on a child filling its glass popover, stacked border-border/70 + shadow-2xl on top of the glass border/elevation (utilities beat the @layer components shadow silently), and its dark hex field used a black wash on a dark surface — the only dark overlay in settings that darkens instead of lightens (cf. AddProviderInstanceDialog's dark:bg-white/* pattern).

Before After

8. Two select triggers, two chevrons

ui/select.tsx contains two trigger components. One rendered the picker-standard (matching comboboxes, the diff-panel branch picker, the PR base selector); the other a half-size 50%-opacity ˅. Value pickers now consistently use ; menus and compact ghost selects keep ˅ — the pop-up vs pull-down distinction the app already follows.

Before After

9. Invisible keyboard focus on ~15 controls

outline-none/outline-hidden with no replacement ring: diff-file collapse chevrons, changed-files tree rows (three of five also missing the ring offset their two siblings have), markdown <details> triggers, toast copy/expand buttons, combobox/autocomplete trigger and clear buttons, the ⌘K submenu Back button, the scroll-to-end pill, onboarding step cards. All now use the standard ring (focus-visible:ring-2 focus-visible:ring-ring + offset), or the inset variant where full-bleed rows would clip an offset ring.

The tooltip proves focus is on the collapse button in both shots; only one shows it:

Before After

10. Project settings "Actions" section invented a third heading scale

text-base font-semibold where every settings row title is text-sm font-medium tracking-[-0.005em], a brighter description than the canonical recipe, and py-2 rows against the ITEM_ROW_CLASSNAME standard of py-3.

Before After

11. Preview controller badge didn't match the zoom pill

Same overlay layer, same geometry, different everything else: text-[11px] on bg-background/90 + shadow-sm vs the zoom pill's text-xs on bg-popover/95 + shadow-md/10. Now identical.

Before After

12. Timeline disclosure rows misaligned

The turn-plan row lacked the size-5 chevron centering box its sibling work-group rows use (and used gap-2 vs their gap-1.5), so stacked rows' labels started at different x-offsets; one chevron was also size-3 vs size-3.5.

Unannotated pair
Before After

13. Disabled states dimmed to seven different values

opacity-30/40/45/50/55/60/80 normalized to the primitives' opacity-64 across ~20 sites, including the shared sidebarMenuButtonVariants (disabled: and aria-disabled:). Two disabled rows (search results in flight, saved-backend cards while applying) had no dimming at all and gained it.

Before After

14. Fixes without a useful screenshot

Fix Detail
Dead electron-drag-region class PreviewPanelShell referenced a class that no stylesheet defines — the preview panel's window-drag strip has been inert since it shipped (the bundle defines only .drag-region). Renamed to the real class.
Sheet backdrop ≠ dialog backdrop Sheets used bg-background/60 backdrop-blur-xs (2px); dialogs use .dialog-backdrop (4px + tuned tint). Sheets now use the shared class.
dropdown-glass lacked saturate() The only glass surface without saturate(var(--glass-saturation)); content behind menus read grayer than behind dialogs.
prefers-reduced-motion Only 2 of ~20 looping animations respected it. The reduce block now also covers status/ghost pulses, status ping, the ultrathink loop, and the update-pill countdown.
Ghost-pulse period 2.4s vs status-pulse's 2s; simultaneous pulses on the PR page visibly drifted against each other. Synced to 2s.
Dead CSS Four zero-consumer blocks removed (.ultrathink-pill, .ultrathink-word, .turn-chip-strip, .diff-render-file) plus a duplicate dark model-picker-surface rule that overrode nothing; the split .dialog-glass declaration merged; two near-identical markdown scrollbar styles unified on the --app-scrollbar-width token.
Geometry tokens Hardcoded paddings duplicating --sidebar-*-inset, --floating-content-inset, --command-content-inset, and --fade-size now route through the vars (zero visual delta — these tokens exist, per the comment above them, so these surfaces "cannot quietly drift apart"). sidebarMenuButtonVariants lg/sm had the radius and inset values transposed relative to default.
Hover/transition long tail Bare transition where only colors change, color hovers with no transition, hover-reveals without a keyboard reveal (focus-visible:opacity-100), one-off hover tokens (hover:bg-accent/50 amid /20 siblings), a dead transition-colors with no hover state, hover:cursor-pointer instead of cursor-pointer.

15. Added during review

Two fixes landed after the PR opened, in the same spirit:

Autocomplete and combobox popups now animate their exit (Cursor Bugbot finding, confirmed real). Both put the scale/fade transition on a wrapper span reacting to a child's data-ending-style, but Base UI waits only on the Popup node's own animations before unmounting, so exits popped instantly. The transition now lives on the Popup itself, matching menu, select, popover, and tooltip.

The changed-files header buttons were different sizes. The collapse-all button carried a !size-[22px] override forcing it 2px smaller than the Open-diff button beside it. Removed the override so both render the standard control size; the two tests pinning the old markup now pin its absence.

Before After

Notes

  • Two changes are opinion rather than drift-repair, and are isolated so they can be debated (or reverted) without touching the rest: the switch geometry (2px thumb inset, visible unchecked track in dark mode) and toggling the sidebar shelves without the list animation.
  • Tooltips and toasts keep their heavier glass shadow. It reads as an intentional elevation variant, so it was left alone.
  • One test was updated: the standalone stop button now matches the send button it swaps places with, which removes a 4px layout jump on narrow viewports. The test's intent (the pending variant stays smaller) is preserved.
  • The branch is rebased continuously as main moves. Where newer commits rewrote code this PR had fixed, the same fixes were re-applied to the new code: both the update pill's new footer button and the right panel's new empty-state cards shipped carrying the old off-convention disabled opacities (60 and 40), normalized to the primitives' 64 here. Fixes that the reworks made obsolete were dropped.

Validation

  • vp run --filter @t3tools/web typecheck
  • vp test run --project unit (apps/web) — 2199 tests passed
  • vp lint --report-unused-disable-directives
  • vp fmt --check
  • vp run --filter @t3tools/web build
  • Manually verified against the previous build side by side (all screenshots/videos above are from those sessions); popup animation additionally verified by per-frame analysis.

Model: Claude Fable 5 · Harness: Claude Code in T3 Code

Note

Apply 130+ UI consistency fixes across cursor, opacity, spacing, and focus styles

  • Adds cursor-pointer to dozens of interactive buttons and links across chat, settings, sidebar, pull request, and preview panels that were missing pointer cursor affordance.
  • Standardizes disabled-state opacity from inconsistent values (40%, 45%, 50%, 60%, 80%) to opacity-64 across components.
  • Replaces hardcoded spacing and sizing values with CSS variable-driven equivalents (--control-radius, --sidebar-content-inset, --fade-size) in sidebar and scroll area components.
  • Improves keyboard accessibility by adding focus-visible ring styles to several interactive elements including image anchors, user avatar triggers, and sidebar thread links.
  • Temporarily disables list auto-animation during sidebar shelf expand/collapse to prevent all rows from animating when toggling shelves.
  • Broadens reduced-motion overrides in index.css to suppress animations across more component classes.
  • Refactors AutocompletePopup and ComboboxPopup DOM structure by removing intermediate span wrappers, applying props directly to the primitive popup elements.

Macroscope summarized e156f01.


Note

Low Risk
Mostly Tailwind/className and shared primitive styling with test updates; no auth, data, or API logic. Shelf animation suspend and switch geometry are isolated UX tweaks with limited blast radius.

Overview
Broad UI polish pass (~87 files) that aligns interactive surfaces with shared ui/ primitives instead of one-off class strings.

Interaction & a11y: Adds cursor-pointer on raw buttons/links across sidebar, chat, settings, PR/diff/preview flows; fixes AutocompleteItem at the source. Adds focus-visible rings (and ring offsets where rows would clip) on controls that only had outline-none. Checkbox/Radio gain pointer cursors; disabled states standardize on opacity-64 (replacing mixed 30–80 values).

Overlays & motion: Menu, select, popover, combobox, and autocomplete popups get matching enter/exit scale+fade (data-ending-style on the Popup node); autocomplete/combobox drop extra wrapper spans and adopt dropdown-glass. Sheet backdrop uses dialog-backdrop; preview shell electron-drag-regiondrag-region.

Sidebar: Snoozed/settled shelf toggles briefly disable auto-animate so mid-list expand doesn’t FLIP every row below; shelf headers get hover/focus styling. Row chrome uses --control-radius / --sidebar-row-content-inset tokens.

Component-specific: Switch track/thumb geometry and dark unchecked track in menu/switch; default select value triggers use chevron; theme color picker stops painting opaque bg-popover over glass; changed-files header drops !size-[22px] so actions match; misc typography/spacing (descenders, timeline chevron box, pending-approval label, stop button size-9 sm:size-8).

Reviewed by Cursor Bugbot for commit e156f01. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ddce0d70-85b8-4ddf-8aeb-cce90ae16858

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 11, 2026
Comment thread apps/web/src/index.css Outdated
@0x00-sys
0x00-sys marked this pull request as ready for review August 11, 2026 20:58
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 11, 2026
@macroscopeapp

macroscopeapp Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved e156f01

This PR contains 130+ CSS styling consistency fixes: adding cursor-pointer to interactive elements, normalizing opacity values, adding focus-visible accessibility styles, and using CSS variables. The only logic change is a minor animation polish fix in the sidebar. All changes are low-risk UI improvements with no material runtime behavior impact.

You can customize Macroscope's approvability policy. Learn more.

@0x00-sys
0x00-sys force-pushed the fix/web-ui-consistency branch from d86f2ed to e21bd74 Compare August 11, 2026 23:46
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@macroscopeapp
macroscopeapp Bot dismissed their stale review August 11, 2026 23:46

Dismissing prior approval to re-evaluate e21bd74

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 11, 2026
@0x00-sys
0x00-sys force-pushed the fix/web-ui-consistency branch from e21bd74 to c4ef3ee Compare August 12, 2026 01:50
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@macroscopeapp
macroscopeapp Bot dismissed their stale review August 12, 2026 01:50

Dismissing prior approval to re-evaluate c4ef3ee

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 12, 2026
@0x00-sys
0x00-sys force-pushed the fix/web-ui-consistency branch from c4ef3ee to 00fe156 Compare August 12, 2026 07:58
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@0x00-sys
0x00-sys force-pushed the fix/web-ui-consistency branch from 00fe156 to 6798e63 Compare August 12, 2026 09:20
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@0x00-sys
0x00-sys force-pushed the fix/web-ui-consistency branch from 6798e63 to 602815c Compare August 12, 2026 10:09
@macroscopeapp
macroscopeapp Bot dismissed their stale review August 12, 2026 10:09

Dismissing prior approval to re-evaluate 602815c

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 12, 2026
@0x00-sys
0x00-sys force-pushed the fix/web-ui-consistency branch from 602815c to 66f4e28 Compare August 12, 2026 10:42
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@macroscopeapp
macroscopeapp Bot dismissed their stale review August 12, 2026 10:42

Dismissing prior approval to re-evaluate 66f4e28

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 66f4e28. Configure here.

Comment thread apps/web/src/components/ui/autocomplete.tsx Outdated
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 12, 2026
@0x00-sys
0x00-sys force-pushed the fix/web-ui-consistency branch from 66f4e28 to 42dc566 Compare August 12, 2026 11:05
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@macroscopeapp
macroscopeapp Bot dismissed their stale review August 12, 2026 11:05

Dismissing prior approval to re-evaluate 42dc566

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 12, 2026
@0x00-sys
0x00-sys force-pushed the fix/web-ui-consistency branch from 42dc566 to 39544e9 Compare August 12, 2026 17:55
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@macroscopeapp
macroscopeapp Bot dismissed their stale review August 12, 2026 17:55

Dismissing prior approval to re-evaluate 39544e9

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 12, 2026
Cursor, focus-ring, disabled-opacity, popup-animation, glass-surface,
padding/typography, and descender-clipping consistency fixes across the
web app, aligning hand-rolled elements with the shared ui/ primitives.

Model: Claude Fable 5 · Harness: Claude Code in T3 Code
…sable

The prefers-reduced-motion block preceded the provider-update pill,
ultrathink frame, and chroma animation declarations; at equal
specificity the later rules won, so those animations kept running.
Moved the block to the end of the stylesheet.
Both put the scale/fade transition on a wrapper span via
has-data-starting-style/has-data-ending-style, but Base UI sets those
attributes on the inner Popup and only waits on that node's own
animations before unmounting, so exit popped instantly. Moved the
transition onto the Popup itself, matching menu/select/popover/tooltip.
The collapse-all button forced itself to 22px with an !important
override, 2px smaller than the adjacent Open-diff button. Removed the
override so both render the standard control size; the two tests
pinning the old markup now pin its absence.
…le button

Takes the upstream profile-page refactor as-is and re-applies the
icon-size normalization in its new home; the sm button already sizes
bare svgs correctly.
@0x00-sys
0x00-sys force-pushed the fix/web-ui-consistency branch from 39544e9 to e156f01 Compare August 12, 2026 20:57
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@macroscopeapp
macroscopeapp Bot dismissed their stale review August 12, 2026 20:59

Dismissing prior approval to re-evaluate e156f01

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL 500-999 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant