UI polish: Lucide icons, light/dark/auto theme toggle, notification r…#25
Merged
andrew-jon-p7a merged 1 commit intomainfrom Apr 29, 2026
Merged
UI polish: Lucide icons, light/dark/auto theme toggle, notification r…#25andrew-jon-p7a merged 1 commit intomainfrom
andrew-jon-p7a merged 1 commit intomainfrom
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…efactor
Three layered tracks of UI work, all on
feature/ui-tweaks.Icons
lucide-preactin @agentc7/web-shell.components/icons/registry —index.tscurated re-exports plusBrandMark.tsx, the custom AgentC7 heptagon (was inlined in 4 places: Header, NavColumn, Login, Boot).stroke="var(--ink)"to match the dashboard top-bar mark (wasvar(--steel)).Theme toggle
.app { … }→:root[data-theme="dark"] { … }. The.appclass 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.lib/theme.ts:themeModesignal (light / dark / auto),effectiveThemecomputed,setThemeMode,cycleThemeMode,initTheme(). Persisted inlocalStorage, followsprefers-color-schemelive in auto mode.<AppearancePanel>— Sun / Moon / Monitor pill picker surfaced in AccountPanel's new "Appearance" section. Shows "currently {light|dark}" caption when auto is selected.--err-bg(pale red bg → dim red bg in dark) and--rail-bg(light:var(--ice)for a subtle alt surface; dark:#0b1420deeper than--paper).initTheme()called fromapps/web/src/main.tsxbefore first render so<html data-theme>is set ahead of paint (no FOUC).lib/theme.ts(the tinysenderTextClasshelper) moved tolib/sender-color.tsto free the canonical slot.Notification refactor
var(--paper)+var(--ink)+var(--rule). Toasts now live as part of the page, not as a dark-island floating overlay.--toast-durationCSS var. Pauses on hover.CheckCircle2 / AlertTriangle / AlertCircle / Info)..btn-ghost btn-sm).DisconnectedBanner.tsxis now a renderless bridge that emits/replaces/clears astream-statustoast as the live stream cycles disconnected → reconnected-with-loss → healthy.mount-errorsticky toast, cleared viadismissToastsByTagon a clean re-bootstrap.AppShellbannerslot removed entirely.dismissToastsByTag(tag)helper exported..bannerCSS deleted (~50 lines, both light + dusk)..callout--compactvariant — tighter padding, 18px non-chip icon — for inline form errors. ChannelSettings's hand-rolled inline error migrated to it as a first consumer.<Hint kind>primitive — inline-flex status-colored text with an optional Lucide icon, for "Saved" / "Copied" / "Field too short" style use cases. Sits below.calloutand toasts in the feedback hierarchy.Summary
What changed
Test plan
Related
Checklist
git commit -s) — the DCO bot will confirmpnpm lintis cleanpnpm typecheckis cleanpnpm testpasses