Skip to content

feat(ui): fill user message bubble (#601 area A)#616

Merged
Astro-Han merged 5 commits into
devfrom
claude/i601-bubble-fill
May 14, 2026
Merged

feat(ui): fill user message bubble (#601 area A)#616
Astro-Han merged 5 commits into
devfrom
claude/i601-bubble-fill

Conversation

@Astro-Han
Copy link
Copy Markdown
Owner

@Astro-Han Astro-Han commented May 14, 2026

Summary

First visual slice of issue #601 area A (message flow). Fills the user bubble and recalibrates the dark --surface-raised tier so raised surfaces actually read as a layer above base.

  • Light bubble fills with --surface-interactive-base (#fdf6f0). Hairline border removed, radius 14px, padding 12/16.
  • Dark bubble fills with --surface-raised.
  • Dark --surface-raised recalibrated #2a2622#3a3431 (1.13:1 → 1.46:1 against --bg-base). Lifts every other raised-tier surface too (dialogs, command palette, menus, toasts, keycaps).
  • Max width flattened from min(82%, 64ch) to 75% for attachments and message body.

Why

The shipped build used a white-bubble + hairline-border treatment, but DESIGN.md L455-461 specifies a filled cream tier with no border. The two had drifted apart. On top of that, the dark --surface-raised token (#2a2622) was only 1.13:1 against --bg-base (#1a1714) — visually inseparable, so a fill-only approach in dark mode would have produced an invisible bubble. The fix is to align the implementation with the design spec and lift the dark raised tier so the fill actually reads.

Initial plan kept --surface-raised untouched and hard-coded the bubble in dark mode, leaving a follow-up issue to recalibrate the tier globally. Discarded — it would have left the dark raised tier permanently sitting at 1.13:1 and made the bubble fix a local patch on a broken system. Recalibrating the token in this PR fixes the bubble and every other raised surface in one move, no debt.

Related Issue

#601

Human Review Status

Pending. Visual decision was driven by an 8-product survey and HTML side-by-side comparisons; a human should taste-check the final dark and light bubbles in the running app before merge.

Review Focus

  • Light bubble: is --surface-interactive-base (cream tint of brand orange) reading as warm/calm rather than orange-tinted?
  • Dark bubble: --surface-raised recalibration affects ~6 component roles documented in DESIGN.md (dialog, dock, command palette, menu, toast, keycap). Hand-tested but worth a re-check.
  • Max-width drop from 64ch ceiling: wide messages no longer snap to a narrow column. Confirm this reads better, not worse, for long content.
  • No brand orange enters the bubble fill — Restrained palette discipline preserved.

Risk Notes

  • --surface-raised is consumed by ~71 callsites across the UI. Hand-tested the high-traffic ones (dialogs, command palette, menus, toasts) in dark mode; no regressions observed.
  • Settings page has a separate --bg-base / --surface-base 1.14:1 readability issue surfaced during testing. Out of scope — that's the base tier, not the raised tier. Follow-up tracked separately.
  • No JS/TS changed. CSS + JSON token only.
  • Local-only files updated to match: DESIGN.md L455-461, docs/design/preview/message-flow.html.

How To Verify

Manual (light): short / long / multi-line bubbles, with and without attachments — pass
Manual (dark): same matrix — pass
Manual (dark, raised tier sweep): dialog, command palette, menus, toasts — pass
Hand-tested by maintainer on macOS in dev:desktop build
No JS/TS changes; tsc/perf gates not exercised by this diff

Screenshots or Recordings

Visual decision artifacts (local-only, not in repo):

  • docs/research/2026-05-14-user-bubble-contrast.md — 8-product survey
  • docs/design/scratch/bubble-final-Y.html — final mockup

Live screenshots from the running build were reviewed during hand-testing and confirmed by the maintainer.

Checklist

  • Human review status is stated above as pending
  • I linked the related issue ([Task] UI rewrite v2 Area A: message flow modular rollout #601)
  • This PR has type (enhancement), area (ui), and priority (P2) labels
  • I described the review focus and risks
  • I listed the verification steps and key results
  • I did not introduce unrelated refactors, dependencies, or generated files
  • I manually checked the visible UI changes (light + dark, multiple message shapes, raised-tier sweep)
  • No platform-specific code path touched (CSS + token JSON only)
  • Called out the out-of-scope dark base-tier issue; local-only DESIGN.md / preview updates noted
  • Reviewed the final diff — 3 files, +16 -9, no surprises
  • Targeting dev; title and commit use Conventional Commits in English

Summary by CodeRabbit

  • Style

    • Updated dark theme color palette values for improved visual consistency
    • Refined user message styling with optimized container dimensions and enhanced background appearance
    • Improved dark mode CSS selector logic for better theme switching compatibility
    • Updated switch component styling for dark mode display
  • Tests

    • Added automated test suite to validate CSS dark mode convention compliance across components

Review Change Stack

issue #601 area A · first visual slice.

light: bubble fills with --surface-interactive-base (#fdf6f0), removes
hairline border, bumps radius to 14px and padding to 12/16. brand orange
stays out of the bubble fill (Restrained palette discipline).

dark: bubble fills with --surface-raised. raised tier was previously
#2a2622, only 1.13:1 against --bg-base #1a1714 — visually inseparable.
recalibrated to #3a3431 (1.46:1) so the bubble (and other raised-tier
surfaces: dialogs, command palette, menus, toasts, keycaps) read as a
distinct layer above base. dialog/menu/toast callsites hand-tested.

max-width: shifted from min(82%, 64ch) to a flat 75% for both
attachments and message body so wide messages don't snap to a narrow
column.

DESIGN.md L455-461 updated (local-only) to reflect the fill direction
and the raised-tier recalibration; preview/message-flow.html mirrored.
@github-actions github-actions Bot added the ui Design system and user interface label May 14, 2026
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Suggested priority: P2 (includes non-doc, non-test paths outside the low-risk bucket).

P1/P0 are reserved for maintainer confirmation. Please relabel manually if this is a release blocker, security issue, data-loss risk, or updater/runtime failure.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 14, 2026

Warning

Rate limit exceeded

@Astro-Han has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 56 minutes and 23 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8cc42fce-03ed-4df4-86d3-5c66b5588055

📥 Commits

Reviewing files that changed from the base of the PR and between ad5db46 and b0af82b.

📒 Files selected for processing (3)
  • packages/ui/src/theme/index.ts
  • packages/ui/src/theme/loader.ts
  • packages/ui/test/dark-media-guard.test.ts
📝 Walkthrough

Walkthrough

This PR tightens dark-mode selectors and lightens the dark raised-surface token to #3a3431, reworks user-message layout/appearance (fixed 75% widths, updated message-text padding/background/radius), and adds a test enforcing guarded prefers-color-scheme: dark media blocks.

Changes

User message styling and dark theme refinement

Layer / File(s) Summary
Dark theme surface-raised token update
packages/ui/src/styles/theme.css, packages/ui/src/theme/themes/pawwork.json
The --surface-raised token is updated from #2a2622 to #3a3431 in the explicit :root[data-color-scheme="dark"] selector and the @media (prefers-color-scheme: dark) mirror, and the pawwork theme override is synchronized.
User message layout and appearance updates
packages/ui/src/components/message-part.css, packages/ui/src/components/switch.css
user-message-attachments and user-message-body max-width changed to 75%. user-message-text background, padding (12px 16px), and border-radius (14px) are updated, with dark-mode overrides forcing --surface-raised. Inline code in reasoning-part markdown has adjusted dark-mode opacity. A switch thumb dark selector was tightened to ignore forced light root.
Dark-media guard test
packages/ui/test/dark-media-guard.test.ts
Adds a test that scans .css files under packages/ui/src/components/ and packages/ui/src/styles/ to ensure any @media (prefers-color-scheme: dark) blocks are preceded by :root:not([data-color-scheme=\"light\"]) guard; the test fails listing violations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 In twilight themes I hop and cheer,
A softer raised surface now is near.
Messages snug at seventy-five,
Dark guards set so styles survive—
Hops and CSS, tidy and clear.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(ui): fill user message bubble (#601 area A)' directly describes the main change: filling the user message bubble component as part of issue #601 area A, following Conventional Commits format.
Description check ✅ Passed The PR description thoroughly covers all required template sections: Summary, Why, Related Issue, Human Review Status, Review Focus, Risk Notes, How To Verify, Screenshots/Recordings, and a completed Checklist with clear details on changes, rationale, verification, and scope management.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/i601-bubble-fill

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 and usage tips.

@Astro-Han Astro-Han added enhancement New feature or request P2 Medium priority labels May 14, 2026
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the styling for user messages by adjusting dimensions, padding, and background colors, alongside a recalibration of the --surface-raised theme token. The review identified a missing guard in the dark mode media query that could cause theme switching issues, a regression in hover contrast for list items, and a visual inconsistency between message text and attachments due to the removal of borders.

Comment thread packages/ui/src/components/message-part.css Outdated
Comment thread packages/ui/src/styles/theme.css
Comment thread packages/ui/src/components/message-part.css
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 14, 2026

Perf delta summary

Comparator: pass

Profile / Scenario interaction median interaction worst long task max tbt frame gap p95 frame gap max jank count cls status
default / homepage-cold 32 -> 24 (-8) 48 -> 48 (0) 76 -> 71 (-5) 26 -> 21 (-5) 16.8 -> 16.8 (0) 133.3 -> 100 (-33.3) 4 -> 3 (-1) 0 -> 0 (0) pass
default / session-streaming-long 48 -> 40 (-8) 56 -> 56 (0) 0 -> 0 (0) 0 -> 0 (0) 33.3 -> 16.8 (-16.5) 50 -> 33.4 (-16.6) 0 -> 0 (0) 0 -> 0 (0) pass
default / tool-call-expand 16 -> 16 (0) 16 -> 24 (+8) 0 -> 0 (0) 0 -> 0 (0) 16.7 -> 16.8 (+0.1) 16.7 -> 16.8 (+0.1) 0 -> 0 (0) 0 -> 0 (0) pass
default / terminal-side-panel-open 40 -> 40 (0) 48 -> 64 (+16) 0 -> 0 (0) 0 -> 0 (0) 16.7 -> 16.8 (+0.1) 16.8 -> 16.8 (0) 0 -> 0 (0) 0 -> 0 (0) pass
default / session-scroll-reading 24 -> 24 (0) 32 -> 32 (0) 0 -> 0 (0) 0 -> 0 (0) 16.8 -> 16.8 (0) 16.8 -> 16.8 (0) 0 -> 0 (0) 0.505 -> 0.505 (0) warn: cls

Astro-Han added 2 commits May 14, 2026 15:28
The nested `@media (prefers-color-scheme: dark)` inside
`[data-slot="user-message-text"]` lacked the project's
`:root:not([data-color-scheme="light"])` mirror guard
(see theme.css L430). When the OS is dark but the user has
explicitly set PawWork to Light, the bubble would read the
light theme's --surface-raised (#ffffff) and blend into the
white canvas.

Moved the rule outside the parent and added the guard so it
mirrors the rest of the theme system.

Caught by Gemini and GPT Pro on PR #616.
…ests

Two other components had the same bug as the user bubble: a bare
`@media (prefers-color-scheme: dark)` without the project's
`:root:not([data-color-scheme="light"])` guard. When the OS prefers
dark but the user has set PawWork to Light, these blocks fired and
overrode light-theme tokens with dark-theme values.

- `message-part.css` reasoning-part inline code: opacity 0.6 applied
  in Light theme on dark-OS systems. Also lacked the parallel
  `[data-color-scheme="dark"]` selector, so explicit Dark on a
  light-OS system had no effect at all. Added both.
- `switch.css` thumb: dark `#f3ede4` thumb leaked into Light theme on
  dark-OS systems while the rest of the switch stayed light. Added
  the guard; the explicit attribute path was already present.

Added `packages/ui/test/dark-media-guard.test.ts` to scan all UI CSS
and fail when any `@media (prefers-color-scheme: dark)` block is
missing the guard. Runs in `bun test`, no browser needed.
GPT Pro flagged that the prior comment ("all UI CSS that ships to the
browser") oversold the scope: the test only scans static CSS files
under src/components and src/styles, and does not see the template
literal in src/theme/loader.ts that builds non-default theme
stylesheets at runtime. The loader.ts gap is tracked in #618.
@Astro-Han Astro-Han force-pushed the claude/i601-bubble-fill branch from b743254 to ad5db46 Compare May 14, 2026 08:11
`packages/ui/src/theme/loader.ts` and its barrel re-exports in
`theme/index.ts` had no callsites anywhere in the monorepo. The live
theme application path is `theme/context.tsx`'s `applyThemeCss`, which
emits CSS per-mode without `@media (prefers-color-scheme: dark)` at
all. `desktop-electron/src/renderer/theme-context.test.ts:8-9` already
enforced that the renderer must not import from the `theme/` barrel.

GPT Pro's PR #616 review flagged unguarded `@media` blocks inside
loader.ts on the assumption it was active; verification showed it was
dead. Removing the file is cleaner than guarding code no one calls.

Verified: `bun --cwd packages/ui run typecheck`, same for app and
desktop-electron, all pass. `dark-media-guard` test still passes and
its scope note is trimmed accordingly.
@Astro-Han Astro-Han merged commit e779a20 into dev May 14, 2026
24 checks passed
@Astro-Han Astro-Han deleted the claude/i601-bubble-fill branch May 14, 2026 08:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request P2 Medium priority ui Design system and user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant