Skip to content

UI polish: Lucide icons, light/dark/auto theme toggle, notification r…#25

Merged
andrew-jon-p7a merged 1 commit intomainfrom
feature/ui-tweaks
Apr 29, 2026
Merged

UI polish: Lucide icons, light/dark/auto theme toggle, notification r…#25
andrew-jon-p7a merged 1 commit intomainfrom
feature/ui-tweaks

Conversation

@andrew-jon-p7a
Copy link
Copy Markdown
Contributor

…efactor

Three layered tracks of UI work, all on feature/ui-tweaks.

Icons

  • Install lucide-preact in @agentc7/web-shell.
  • New components/icons/ registry — index.ts curated re-exports plus BrandMark.tsx, the custom AgentC7 heptagon (was inlined in 4 places: Header, NavColumn, Login, Boot).
  • Migrated ~32 icon sites across the shell + apps/web:
    • Header: Menu, BrandMark, Search.
    • Composer: 5 toolbar icons (Paperclip, Slash, AtSign, Send) + expand/collapse chevrons.
    • NavColumn: Settings ×2, BrandMark, LogOut, plus the sidebar nav glyphs (⌂✎◇▤⊕ → Home/Inbox/Target/Folder/Users) and the channel #/+ glyphs.
    • Command palette: Search prefix + per-kind result icons (AtSign, Hash, MessageCircle, Target, Plus).
    • Inspector / RouteModal X close.
    • Callout / status indicators: ◆ → AlertTriangle (warn) or AlertCircle (err); inline pills like "Notif error" + "blocked".
  • Public API: icons + BrandMark re-exported from @agentc7/web-shell so apps/web (Login, Boot) consumes through the package boundary.
  • Brand-specific marks (heptagon) live alongside as local files, so swapping any single icon for a custom SVG later is a one-line change in the registry.
  • Login + Boot heptagons now use stroke="var(--ink)" to match the dashboard top-bar mark (was var(--steel)).

Theme toggle

  • Refactored dark-theme selector: .app { … }:root[data-theme="dark"] { … }. The .app class no longer carries theming responsibility (was double-duty: auth-surface marker + dark theme; now just a layout marker, harmless). Component deltas (btn-primary, callouts, etc.) updated to the new selector.
  • New lib/theme.ts: themeMode signal (light / dark / auto), effectiveTheme computed, setThemeMode, cycleThemeMode, initTheme(). Persisted in localStorage, follows prefers-color-scheme live in auto mode.
  • New <AppearancePanel> — Sun / Moon / Monitor pill picker surfaced in AccountPanel's new "Appearance" section. Shows "currently {light|dark}" caption when auto is selected.
  • Added two tokens for surfaces that previously hardcoded hex: --err-bg (pale red bg → dim red bg in dark) and --rail-bg (light: var(--ice) for a subtle alt surface; dark: #0b1420 deeper than --paper).
  • initTheme() called from apps/web/src/main.tsx before first render so <html data-theme> is set ahead of paint (no FOUC).
  • Internal rename: lib/theme.ts (the tiny senderTextClass helper) moved to lib/sender-color.ts to free the canonical slot.

Notification refactor

  • Toast polish:
    • Position: bottom-right (was top-right) so toasts never collide with modal close buttons or topbar chrome, and so a sticky "system status" toast can sit there without ever pushing layout.
    • Theme-aware surface: var(--paper) + var(--ink) + var(--rule). Toasts now live as part of the page, not as a dark-island floating overlay.
    • Enter motion: 220ms slide-up + scale-in.
    • Progress bar: pinned to bottom edge, width fills 100→0% over each toast's --toast-duration CSS var. Pauses on hover.
    • Functional hover-pause: JS dismiss timer captures elapsed time on mouseenter and resumes from the remainder on mouseleave — a 5s toast no longer resets to a fresh 5s every cursor entry.
    • Lucide icons replacing unicode (CheckCircle2 / AlertTriangle / AlertCircle / Info).
    • Action button rendered as an underlined text-link in the kind's accent color (was a bordered .btn-ghost btn-sm).
  • Banner collapse — the layout-pushing banner region is gone. All persistent system messages route through sticky tagged toasts:
    • DisconnectedBanner.tsx is now a renderless bridge that emits/replaces/clears a stream-status toast as the live stream cycles disconnected → reconnected-with-loss → healthy.
    • TeamShell mount-error is a mount-error sticky toast, cleared via dismissToastsByTag on a clean re-bootstrap.
    • AppShell banner slot removed entirely.
    • New dismissToastsByTag(tag) helper exported.
  • Orphan .banner CSS deleted (~50 lines, both light + dusk).
  • New .callout--compact variant — tighter padding, 18px non-chip icon — for inline form errors. ChannelSettings's hand-rolled inline error migrated to it as a first consumer.
  • New <Hint kind> primitive — inline-flex status-colored text with an optional Lucide icon, for "Saved" / "Copied" / "Field too short" style use cases. Sits below .callout and toasts in the feedback hierarchy.

Summary

What changed

Test plan

  • [ ]
  • [ ]

Related

Checklist

  • All commits are signed off (git commit -s) — the DCO bot will confirm
  • pnpm lint is clean
  • pnpm typecheck is clean
  • pnpm test passes
  • Docs/README updated if user-facing behavior changed

…efactor

  Three layered tracks of UI work, all on `feature/ui-tweaks`.

  Icons
  - Install `lucide-preact` in @agentc7/web-shell.
  - New `components/icons/` registry — `index.ts` curated re-exports
    plus `BrandMark.tsx`, the custom AgentC7 heptagon (was inlined
    in 4 places: Header, NavColumn, Login, Boot).
  - Migrated ~32 icon sites across the shell + apps/web:
    - Header: Menu, BrandMark, Search.
    - Composer: 5 toolbar icons (Paperclip, Slash, AtSign, Send) +
      expand/collapse chevrons.
    - NavColumn: Settings ×2, BrandMark, LogOut, plus the sidebar
      nav glyphs (⌂✎◇▤⊕ → Home/Inbox/Target/Folder/Users) and the
      channel #/+ glyphs.
    - Command palette: Search prefix + per-kind result icons (AtSign,
      Hash, MessageCircle, Target, Plus).
    - Inspector / RouteModal X close.
    - Callout / status indicators: ◆ → AlertTriangle (warn) or
      AlertCircle (err); inline pills like "Notif error" + "blocked".
  - Public API: icons + BrandMark re-exported from
    @agentc7/web-shell so apps/web (Login, Boot) consumes through
    the package boundary.
  - Brand-specific marks (heptagon) live alongside as local files,
    so swapping any single icon for a custom SVG later is a one-line
    change in the registry.
  - Login + Boot heptagons now use `stroke="var(--ink)"` to match
    the dashboard top-bar mark (was `var(--steel)`).

  Theme toggle
  - Refactored dark-theme selector: `.app { … }` →
    `:root[data-theme="dark"] { … }`. The `.app` class no longer
    carries theming responsibility (was double-duty: auth-surface
    marker + dark theme; now just a layout marker, harmless).
    Component deltas (`btn-primary`, callouts, etc.) updated to the
    new selector.
  - New `lib/theme.ts`: `themeMode` signal (light / dark / auto),
    `effectiveTheme` computed, `setThemeMode`, `cycleThemeMode`,
    `initTheme()`. Persisted in `localStorage`, follows
    `prefers-color-scheme` live in auto mode.
  - New `<AppearancePanel>` — Sun / Moon / Monitor pill picker
    surfaced in AccountPanel's new "Appearance" section. Shows
    "currently {light|dark}" caption when auto is selected.
  - Added two tokens for surfaces that previously hardcoded hex:
    `--err-bg` (pale red bg → dim red bg in dark) and `--rail-bg`
    (light: `var(--ice)` for a subtle alt surface; dark: `#0b1420`
    deeper than `--paper`).
  - `initTheme()` called from `apps/web/src/main.tsx` before first
    render so `<html data-theme>` is set ahead of paint (no FOUC).
  - Internal rename: `lib/theme.ts` (the tiny `senderTextClass`
    helper) moved to `lib/sender-color.ts` to free the canonical
    slot.

  Notification refactor
  - Toast polish:
    - Position: bottom-right (was top-right) so toasts never collide
      with modal close buttons or topbar chrome, and so a sticky
      "system status" toast can sit there without ever pushing
      layout.
    - Theme-aware surface: `var(--paper)` + `var(--ink)` + `var(--rule)`.
      Toasts now live as part of the page, not as a dark-island
      floating overlay.
    - Enter motion: 220ms slide-up + scale-in.
    - Progress bar: pinned to bottom edge, width fills 100→0% over
      each toast's `--toast-duration` CSS var. Pauses on hover.
    - Functional hover-pause: JS dismiss timer captures elapsed time
      on mouseenter and resumes from the remainder on mouseleave —
      a 5s toast no longer resets to a fresh 5s every cursor entry.
    - Lucide icons replacing unicode (`CheckCircle2 / AlertTriangle /
      AlertCircle / Info`).
    - Action button rendered as an underlined text-link in the
      kind's accent color (was a bordered `.btn-ghost btn-sm`).
  - Banner collapse — the layout-pushing banner region is gone.
    All persistent system messages route through sticky tagged
    toasts:
    - `DisconnectedBanner.tsx` is now a renderless bridge that
      emits/replaces/clears a `stream-status` toast as the live
      stream cycles disconnected → reconnected-with-loss → healthy.
    - TeamShell mount-error is a `mount-error` sticky toast,
      cleared via `dismissToastsByTag` on a clean re-bootstrap.
    - `AppShell` `banner` slot removed entirely.
    - New `dismissToastsByTag(tag)` helper exported.
  - Orphan `.banner` CSS deleted (~50 lines, both light + dusk).
  - New `.callout--compact` variant — tighter padding, 18px
    non-chip icon — for inline form errors. ChannelSettings's
    hand-rolled inline error migrated to it as a first consumer.
  - New `<Hint kind>` primitive — inline-flex status-colored text
    with an optional Lucide icon, for "Saved" / "Copied" /
    "Field too short" style use cases. Sits below `.callout` and
    toasts in the feedback hierarchy.

Signed-off-by: Andrew Jon Przybilla <andrew@przy.email>
@andrew-jon-p7a andrew-jon-p7a merged commit 943a481 into main Apr 29, 2026
1 check passed
@andrew-jon-p7a andrew-jon-p7a deleted the feature/ui-tweaks branch April 29, 2026 23:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant