Commit graph

2 commits

Author SHA1 Message Date
varutasu
906b332303
refactor(design-system): redesign-v2 refinements — tone down active/hover states + dedupe profile + seamless header (#109)
Operator feedback after the redesign-v2 epic shipped (PRs #102-#108):
the bold ember-gradient pill, the left-shifting hover, the duplicate
profile dropdown, and the divider below the header all read too
heavy. Four targeted refinements in one PR.

1. Move profile from sidebar bottom → TopSearchBar user-menu chip
   (top-right). The chip already existed (sub-convoy #3, PR #105);
   the sidebar's UserProfileDropdown was redundant. Removed from
   BOTH desktop sidebar and mobile drawer. Kept for logged-out
   visitors only (the top bar renders null when user is null, so
   the sidebar still surfaces the auth path via the existing
   Sign-in CTA branch).

2. Active state: bold ember-gradient pill → 1px ember border on
   transparent background.
   - styles/globals.css .nav-item-active: dropped the
     linear-gradient + 3-stop box-shadow glow. Now: transparent bg,
     accent-ember text color, inset 0 0 0 1px var(--accent-ember).
   - Dark theme variant uses a slightly hotter ember
     (rgb(255,138,80)) for eye-perception correction against the
     deep-navy substrate. AA contrast measured: 5.4:1 on dark
     navy bg, 4.6:1 on light cream bg — both pass 4.5:1 normal-
     text threshold.

3. Hover state: left-shifting border + transform → static
   transparent ember-tinted background.
   - Removed `border-left: 3px solid var(--accent-flame)` +
     `padding-left: calc(1rem - 3px)` on .nav-item-hover:hover
     (and focus-within). These were causing the 3px-width shift
     the operator called "movement with the left align."
   - Removed `transform: translateX(4px)` on .nav-item:hover and
     .nav-item-bottom:hover — the horizontal-jitter the operator
     also flagged.
   - Both classes now apply a flat `background-color:
     rgba(216, 67, 21, 0.08)` (light) / `rgba(255, 138, 80, 0.10)`
     (dark) on hover/focus-within with zero geometry shift.

4. TopSearchBar bottom divider removed.
   - styles change in components/ui/TopSearchBar.js: dropped the
     `0 1px 0 var(--border)` segment from the box-shadow
     composition. The rim-light-inner top highlight stays so the
     bar still reads as elevated chrome against the gradient body,
     but there's no longer a hairline below — page content flows
     visually seamlessly out of the header.

Test fix:
- test/components/Layout.test.js test #4 ("renders the supplied
  user email") asserted the FULL email `foo@bar.com`. The
  sidebar UserProfileDropdown used to render that; the TopSearchBar
  chip renders the username (or email's local-part as fallback) —
  `'foo'` for `foo@bar.com`. The assertion now checks for `'foo'`
  + retains the maintainer-email negative check. Renamed the
  test to "flows the supplied user through to the rendered
  surface (TopSearchBar chip)" with an inline comment explaining
  the shift; the three other P0 #7 regression-lock cases are
  unchanged and still pass.

Tests:
- npm run test:run: 113/113
- npm run lint: clean (1 pre-existing unused-disable warning)
- npm run build: green

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 11:45:57 -05:00
varutasu
e6e778080a
feat(design-system): redesign v2 #3 — TopSearchBar + Cmd+K + sweep page-header-glass (#105)
Sub-convoy #3 from .convoys/redesign-v2-from-mockups.md (umbrella
§ 7.3 — locked: sweep to ALL authenticated pages this convoy).

What ships:

- components/ui/TopSearchBar.js — the top horizontal chrome strip
  from the mockup. Layout: prominent search input on left (with
  magnifier icon + Cmd+K/Ctrl+K hint pill that adapts to platform)
  + notification bell with red badge (hidden when count=0) + mail
  icon + compact user-menu chip (gradient-tile avatar + display name
  + chevron). Avatar reads user.username with a fallback initial.
  Renders null for unauthenticated visitors (public marketing pages
  use their own header).

- components/ui/CommandPaletteModal.js — the surface that opens on
  ⌘K / Ctrl+K. Single search input, auto-focused. Enter submits to
  /cards?q=<query>. 3 quick-action buttons (Dashboard / Cards /
  Scanner) below the input. Eschews live-result preview, recent-
  search storage, and federated-search ranking; those are deferred
  to a follow-up convoy per umbrella § 7.2.

- components/Layout.js: TopSearchBar mounted in the main-content
  column ABOVE <main> for authenticated users (drops the legacy
  showSearch prop dependency — the prop stays for back-compat but
  no longer drives the header's visibility). Global keydown listener
  attached at Layout scope, toggles the CommandPaletteModal on
  ⌘K/Ctrl+K (preventDefault on the shortcut so the browser's native
  bookmark/search shortcut doesn't fire). The legacy <header>
  block that rendered an inline search input is removed; that
  surface is replaced by TopSearchBar + CommandPaletteModal.

- page-header-glass call-site sweep (umbrella § 7.3 contract:
  "no call site references it after this convoy"):
  - pages/dashboard.js
  - pages/my-cards.js
  - pages/community/collections.js
  - components/CollectionsPageView.js
  - components/CollectionPageView.js
  - components/CardsPageView.js
  Each `page-header-glass p-4 sm:p-6` is replaced with plain content
  padding (`px-4 sm:px-6 pt-6 pb-2`). Page titles + actions stay
  exactly where they were inside the content area; the glass chrome
  that previously framed them is now provided by TopSearchBar above.
  The .page-header-glass utility class stays in styles/globals.css
  (a downstream sweep convoy can remove it once the unused-CSS lint
  catches it).

- components/ui/index.js: barrel export updated with TopSearchBar +
  CommandPaletteModal.

Lint fix:
- CommandPaletteModal initially used useEffect(setQuery(''), [open])
  to reset the input on open; that hits the react-hooks/set-state-
  in-effect rule (we added the rule in fix-auth-bypass Brief 5). Use
  the "during render with previous-state tracking" pattern that
  NavigationContent uses (lines 168-178 of components/Layout.js)
  for the same purpose. No useEffect required.

Tests:
- npm run test:run: 113/113 (was 110; +3 new — implicit Layout
  tree-render coverage of the new TopSearchBar mount paths).
- npm run lint: clean (1 pre-existing unused-disable warning).
- npm run build: green.

Next: sub-convoy #6 (card-grid outer-glow), #7 (dashboard layout
rebuild), #8 (right-rail Card Spotlight).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 11:14:50 -05:00