Chat chrome: one gutter, one radius scale, one even glass recipe
The header and composer were full-bleed bands (flush to the top/right/bottom viewport edges, composer corners off-screen) next to a rail that floats with a 12px margin. The new --layout-gutter (12px) spaces the rail, header, empty-state card and composer identically on every side; --radius-panel/-control/-chip (-pill) replace the ad-hoc radii across the shared classes, so every panel is rounded on all four corners and shared controls match in every theme. The desktop-only ::after hairlines and the left-corner-only radius are gone. Aero: the rail and the chat chrome (answers included) share one even recipe - the wallpaper extra-blurred into a hue-free wash (background-glass.webp) under a uniform ~50% white veil and a whisper of gloss. Measured within ~10 RGB units across the rail top->bottom and the card/composer left->right; the blue->green smear and the teal composer are gone. The composer's field is a clean even tile with no wallpaper gradient inside it. Chat fixes: send is a filled primary tile shaped exactly like attach (dimmed while the input is empty), suggestion/context chips use the shared .chip token (40/44px target, visible rim, full-contrast text, raw model id in the tooltip), the AI note reads at 12px --text-muted (.ai-disclaimer), the selected sidebar row carries the accent border + accent icon, the theme toggle is back in Aero (the moon flips to Dark; Settings brings Aero back), and the empty state is centered exactly between header and composer. Outside CSS: the wallpaper's top-left HUD-circle decoration (it peeked through the 12px gutters on wide windows) was healed out of background.webp and background-blur.webp; the orbs/bubbles ride one masked .ice-floats layer that fades them under the chrome bands and the rail strip, so none is sliced by a panel edge (still parked under reduced motion). Version 0.6.0, SW -> freezmo-v82. Tests: chat suite pins the new geometry (12px gutter, 24px corners, even wash on all four panels, send-vs-attach shape, chips/input radii); mobile pins the phone chrome and the Aero toggle; bubbles pins the floats layer + its reduced-motion opt-out.
This commit is contained in:
parent
8153fc8dae
commit
786d6cf1ae
21 changed files with 562 additions and 290 deletions
|
|
@ -578,22 +578,22 @@ export function ChatScreen() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full min-h-0 w-full">
|
||||
<div className="flex h-full min-h-0 w-full" style={{ paddingBottom: "var(--chat-keyboard, 0px)" }}>
|
||||
{/* Desktop's conversation list lives in the main sidebar (on /chat). */}
|
||||
<div className="relative flex h-full min-h-0 min-w-0 flex-1 flex-col" style={{ paddingBottom: "var(--chat-keyboard, 0px)" }}>
|
||||
<header className="glass chat-header sticky top-0 z-30 flex h-14 shrink-0 items-center gap-2 px-2 sm:px-4">
|
||||
<div className="chat-column relative flex h-full min-h-0 min-w-0 flex-1 flex-col gap-[var(--layout-gutter)] p-[var(--layout-gutter)]">
|
||||
<header className="glass-panel chat-header z-30 flex h-14 shrink-0 items-center gap-2 px-2 sm:px-4">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => (window.history.length > 1 ? router.back() : router.push("/"))}
|
||||
aria-label={t("chat.back")}
|
||||
title={t("chat.back")}
|
||||
className="grid size-11 shrink-0 place-items-center rounded-2xl text-[var(--text-muted)] transition hover:bg-[var(--hover)] hover:text-[var(--text)] lg:hidden"
|
||||
className="grid size-11 shrink-0 place-items-center rounded-[var(--radius-control)] text-[var(--text-muted)] transition hover:bg-[var(--hover)] hover:text-[var(--text)] lg:hidden"
|
||||
>
|
||||
<ChevronLeftIcon className="size-5" />
|
||||
</button>
|
||||
<div className="min-w-0 flex-1">
|
||||
<h1 className="truncate text-[15px] font-semibold text-[var(--text)]">{title || t("chat.title")}</h1>
|
||||
<p className="truncate text-[11.5px] text-[var(--text-subtle)]">
|
||||
<p className="truncate text-[11.5px] text-[var(--text-muted)]">
|
||||
{scopeText}
|
||||
{seed ? ` · ${seed.label}` : ""}
|
||||
</p>
|
||||
|
|
@ -605,20 +605,20 @@ export function ChatScreen() {
|
|||
onClick={() => setHistoryOpen(true)}
|
||||
aria-label={t("chat.history")}
|
||||
title={t("chat.history")}
|
||||
className="grid size-11 place-items-center rounded-2xl border border-[var(--glass-border)] bg-[var(--surface-strong)] text-[var(--text-muted)] transition hover:bg-[var(--hover)] hover:text-[var(--text)] lg:hidden"
|
||||
className="grid size-11 place-items-center rounded-[var(--radius-control)] border border-[var(--glass-border)] bg-[var(--surface-strong)] text-[var(--text-muted)] transition hover:bg-[var(--hover)] hover:text-[var(--text)] lg:hidden"
|
||||
>
|
||||
<HistoryIcon className="size-5" />
|
||||
</button>
|
||||
<ThemeToggle
|
||||
plain
|
||||
className="grid size-11 place-items-center rounded-2xl border border-[var(--glass-border)] bg-[var(--surface-strong)]"
|
||||
className="grid size-11 place-items-center rounded-[var(--radius-control)] border border-[var(--glass-border)] bg-[var(--surface-strong)]"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={newChat}
|
||||
aria-label={t("chat.new")}
|
||||
title={t("chat.new")}
|
||||
className="grid size-11 place-items-center rounded-2xl border border-[var(--glass-border)] bg-[var(--surface-strong)] text-[var(--text-muted)] transition hover:bg-[var(--hover)] hover:text-[var(--text)]"
|
||||
className="grid size-11 place-items-center rounded-[var(--radius-control)] border border-[var(--glass-border)] bg-[var(--surface-strong)] text-[var(--text-muted)] transition hover:bg-[var(--hover)] hover:text-[var(--text)]"
|
||||
>
|
||||
<ChatPlusIcon className="size-5" />
|
||||
</button>
|
||||
|
|
@ -638,16 +638,16 @@ export function ChatScreen() {
|
|||
{messages.length === 0 ? (
|
||||
<div className="chat-empty space-y-5 py-2">
|
||||
<div className="text-center">
|
||||
<span className="mx-auto mb-4 grid size-12 place-items-center rounded-2xl border border-[var(--hairline)] bg-[var(--surface-strong)] text-accent-600 dark:text-accent-200">
|
||||
<span className="mx-auto mb-4 grid size-12 place-items-center rounded-[var(--radius-control)] border border-[var(--glass-border)] bg-[var(--surface-strong)] text-accent-600 dark:text-accent-200">
|
||||
<ChatIcon className="size-6" />
|
||||
</span>
|
||||
<h2 className="text-[20px] font-semibold tracking-[-0.01em] text-[var(--text)]">{t("chat.emptyTitle")}</h2>
|
||||
<p className="mx-auto mt-1.5 max-w-sm text-[13.5px] leading-relaxed text-[var(--text-subtle)]">
|
||||
<p className="mx-auto mt-1.5 max-w-sm text-[13.5px] leading-relaxed text-[var(--text-muted)]">
|
||||
{t("chat.emptyHint")}
|
||||
</p>
|
||||
</div>
|
||||
{missingNotes ? (
|
||||
<p className="rounded-2xl border border-amber-300/50 bg-amber-50/70 px-3.5 py-3 text-[12.5px] leading-relaxed text-amber-800 dark:border-amber-400/25 dark:bg-amber-400/10 dark:text-amber-200">
|
||||
<p className="rounded-[var(--radius-control)] border border-amber-300/50 bg-amber-50/70 px-3.5 py-3 text-[12.5px] leading-relaxed text-amber-800 dark:border-amber-400/25 dark:bg-amber-400/10 dark:text-amber-200">
|
||||
{t("chat.oldDecksNote")}
|
||||
</p>
|
||||
) : null}
|
||||
|
|
@ -658,7 +658,7 @@ export function ChatScreen() {
|
|||
type="button"
|
||||
disabled={!online || busy}
|
||||
onClick={() => send(suggestion)}
|
||||
className="max-w-full rounded-2xl border border-[var(--glass-border)] bg-[var(--surface-strong)] px-3.5 py-2.5 text-left text-[13px] text-[var(--text-muted)] transition hover:bg-[var(--hover)] hover:text-[var(--text)] disabled:opacity-55"
|
||||
className="chip max-w-full px-3.5 py-2 text-left text-[13px] disabled:opacity-55"
|
||||
>
|
||||
{suggestion}
|
||||
</button>
|
||||
|
|
@ -697,10 +697,9 @@ export function ChatScreen() {
|
|||
))}
|
||||
</>
|
||||
)}
|
||||
<div className="h-2" aria-hidden />
|
||||
{messages.length > 0 ? <div className="h-2" aria-hidden /> : null}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!pinned && messages.length > 0 ? (
|
||||
<button
|
||||
type="button"
|
||||
|
|
@ -721,7 +720,7 @@ export function ChatScreen() {
|
|||
{error ? (
|
||||
<div
|
||||
role="alert"
|
||||
className="mx-3 mb-2 shrink-0 rounded-2xl border border-rose-300/60 bg-rose-50/80 p-3 dark:border-rose-400/30 dark:bg-rose-500/10"
|
||||
className="shrink-0 rounded-[var(--radius-control)] border border-rose-300/60 bg-rose-50/80 p-3 dark:border-rose-400/30 dark:bg-rose-500/10"
|
||||
>
|
||||
<p className="text-[13px] leading-relaxed text-rose-800 dark:text-rose-200">{error.message}</p>
|
||||
<div className="mt-2 flex flex-wrap items-center gap-2">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue