From de4e5637325e283460bfaec27899be2225104c0d Mon Sep 17 00:00:00 2001 From: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Date: Sat, 11 Jul 2026 14:49:03 -0700 Subject: [PATCH] Refine status-bar usage notice styling and test coverage - Replace hand-tuned light/dark card colors with existing design tokens (--popover, --border) and the documented floating elevation, so the callout stays in sync with the design system instead of duplicating its own palette - Add tests covering dismiss via X button, "Got it", and Escape - Scope the foreground-process confirm assertion to the pane's ptyId so an unrelated pane's delayed confirm can't cause a false failure --- src/renderer/src/assets/main.css | 60 ++++--------------- ...sagePercentageDisplayChangeNotice.test.tsx | 49 +++++++++++++++ .../terminal-pane/pty-connection.test.ts | 4 +- 3 files changed, 62 insertions(+), 51 deletions(-) diff --git a/src/renderer/src/assets/main.css b/src/renderer/src/assets/main.css index fe9d13a4136..25a5a4e751b 100644 --- a/src/renderer/src/assets/main.css +++ b/src/renderer/src/assets/main.css @@ -1210,46 +1210,14 @@ } /* Why: one-shot status-bar callout is portaled fixed above the meters. - Opaque elevated surfaces (not glass) so titlebar/terminal chrome cannot - bleed through; light and dark use separate fills. */ + Opaque popover surface (not glass) so titlebar/terminal chrome cannot + bleed through; use design tokens + the documented floating elevation. */ .status-bar-change-notice-card { - border: 1px solid color-mix(in srgb, var(--foreground) 16%, var(--border)); - background: var(--card); - color: var(--card-foreground); - box-shadow: - 0 0 0 1px color-mix(in srgb, var(--foreground) 6%, transparent), - 0 14px 36px color-mix(in srgb, var(--foreground) 14%, transparent), - 0 2px 8px color-mix(in srgb, var(--foreground) 8%, transparent); -} - -/* Light: pure paper above light chrome — lift with a cool edge, not gray fill. */ -:root:not(.dark) .status-bar-change-notice-card { - background: #ffffff; - border-color: #c4c9d2; - color: #0a0a0a; - box-shadow: - 0 0 0 1px rgb(15 23 42 / 0.06), - 0 16px 40px rgb(15 23 42 / 0.16), - 0 3px 10px rgb(15 23 42 / 0.08); -} - -:root:not(.dark) .status-bar-change-notice-card .text-muted-foreground { - color: #52525b; -} - -/* Dark: lifted charcoal above #0a0a0a / #171717 — not translucent glass. */ -.dark .status-bar-change-notice-card { - background: #2a2a2e; - border-color: color-mix(in srgb, #ffffff 26%, transparent); - color: #fafafa; - box-shadow: - 0 0 0 1px color-mix(in srgb, #ffffff 12%, transparent), - 0 18px 44px rgb(0 0 0 / 0.62), - 0 3px 12px rgb(0 0 0 / 0.4); -} - -.dark .status-bar-change-notice-card .text-muted-foreground { - color: color-mix(in srgb, #fafafa 68%, transparent); + border: 1px solid var(--border); + background: var(--popover); + color: var(--popover-foreground); + /* STYLEGUIDE: floating elevation for popovers that escape the editor surface. */ + box-shadow: 0 10px 24px rgb(0 0 0 / 0.18); } /* Why: caret points down at the usage meters this notice explains. */ @@ -1261,17 +1229,9 @@ width: 12px; height: 12px; transform: rotate(45deg); - border-right: 1px solid #c4c9d2; - border-bottom: 1px solid #c4c9d2; - background: #ffffff; - box-shadow: 2px 2px 5px rgb(15 23 42 / 0.1); -} - -.dark .status-bar-change-notice-card::after { - border-right-color: color-mix(in srgb, #ffffff 26%, transparent); - border-bottom-color: color-mix(in srgb, #ffffff 26%, transparent); - background: #2a2a2e; - box-shadow: 2px 2px 8px rgb(0 0 0 / 0.45); + border-right: 1px solid var(--border); + border-bottom: 1px solid var(--border); + background: var(--popover); } /* Why: the first-run Mobile Emulator intro sits directly under that menu row; diff --git a/src/renderer/src/components/status-bar/UsagePercentageDisplayChangeNotice.test.tsx b/src/renderer/src/components/status-bar/UsagePercentageDisplayChangeNotice.test.tsx index 61ed696dab8..cb8fea8a750 100644 --- a/src/renderer/src/components/status-bar/UsagePercentageDisplayChangeNotice.test.tsx +++ b/src/renderer/src/components/status-bar/UsagePercentageDisplayChangeNotice.test.tsx @@ -173,4 +173,53 @@ describe('UsagePercentageDisplayChangeNotice', () => { }) expect(storeState.dismissUsagePercentageDisplayChangeNotice).toHaveBeenCalled() }) + + it('dismisses from the X button', () => { + openNotice() + + const dismissButton = document.querySelector( + '.status-bar-change-notice-card button[aria-label="Dismiss"]' + ) + expect(dismissButton).toBeTruthy() + act(() => { + dismissButton?.dispatchEvent(new MouseEvent('click', { bubbles: true })) + }) + expect(storeState.dismissUsagePercentageDisplayChangeNotice).toHaveBeenCalledTimes(1) + }) + + it('dismisses from Got it', () => { + openNotice() + + const gotItButton = Array.from( + document.querySelectorAll('.status-bar-change-notice-card button') + ).find((button) => button.textContent === 'Got it') + expect(gotItButton).toBeTruthy() + act(() => { + gotItButton?.dispatchEvent(new MouseEvent('click', { bubbles: true })) + }) + expect(storeState.dismissUsagePercentageDisplayChangeNotice).toHaveBeenCalledTimes(1) + }) + + it('dismisses on Escape', () => { + openNotice() + + act(() => { + window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true })) + }) + expect(storeState.dismissUsagePercentageDisplayChangeNotice).toHaveBeenCalledTimes(1) + }) + + function openNotice(): void { + act(() => { + root.render( + + usage-meters + + ) + }) + act(() => { + vi.advanceTimersByTime(1_800) + }) + expect(document.querySelector('.status-bar-change-notice-card')).not.toBeNull() + } }) diff --git a/src/renderer/src/components/terminal-pane/pty-connection.test.ts b/src/renderer/src/components/terminal-pane/pty-connection.test.ts index c2815c88496..ae29c1e3589 100644 --- a/src/renderer/src/components/terminal-pane/pty-connection.test.ts +++ b/src/renderer/src/components/terminal-pane/pty-connection.test.ts @@ -17599,7 +17599,9 @@ describe('connectPanePty', () => { binding.sampleForegroundAgentOnFocus() await vi.advanceTimersByTimeAsync(10_000) - expect(window.api.pty.confirmForegroundProcess).not.toHaveBeenCalled() + // Scope to this pane's pty id: a delayed confirm for another test's + // default `tab-pty` pane can fire during this advance and is not our subject. + expect(window.api.pty.confirmForegroundProcess).not.toHaveBeenCalledWith(ptyId) } finally { restoreUserAgent() }