Design pass (all themes + chat UI), model picker, reduce-motion toggle
- Aero: blue gradients back on the active segment and every primary
(Review due, the card's Study button, the composer's send button); a
frosted backing behind the page heading and the All decks label; a
bottom-weighted rail tint; chat header/composer/welcome panels; calmer
orbs; stronger card veil + a stronger blur bake.
- Dark/Light: a dedicated --track token makes progress bars read (the
first attempt shifted --surface-sunken and the pixel scan caught the
sheet-contrast regression); brighter dark secondary text; darker light
segmented labels and difficulty tints; stronger light card border and
shadow.
- Chat UI: friendly model chip ("Gemma 4 31B") with the raw name in a
tooltip, larger chips, plain centered disclaimer, vertically centered
welcome panel, distinct chat-plus icon for new chat.
- Chat models: every chat-capable model from the server's /api/tags is
selectable (favourites first, search field when long, live-list
validation in the route); default CHAT_MODEL_DEFAULT or gemma4:31b.
- Reduce motion: Settings toggle (default off) that parks the scene,
collapses CSS animations and drives framer-motion's calm mode.
- Folders hint, "New" badge on fresh decks.
Contrast: 0 findings, axe clean, mobile 126/126, chat 102/102, wizard
95/95, regression 44/44, i18n 13/13, native 33/33.
Version 0.4.6, SW -> freezmo-v71.
This commit is contained in:
parent
b70b0e83cf
commit
6635b5d405
29 changed files with 468 additions and 90 deletions
|
|
@ -26,6 +26,7 @@ export function Composer({
|
|||
online,
|
||||
scopeLabel,
|
||||
modelLabel,
|
||||
modelTitle,
|
||||
scopeOpen,
|
||||
modelOpen,
|
||||
onOpenScope,
|
||||
|
|
@ -43,6 +44,8 @@ export function Composer({
|
|||
online: boolean;
|
||||
scopeLabel: string;
|
||||
modelLabel: string;
|
||||
/** The raw model name, shown as the chip's tooltip. */
|
||||
modelTitle?: string;
|
||||
scopeOpen: boolean;
|
||||
modelOpen: boolean;
|
||||
onOpenScope: () => void;
|
||||
|
|
@ -168,8 +171,8 @@ export function Composer({
|
|||
onClick={onOpenScope}
|
||||
className={pickerChipClass(scopeOpen)}
|
||||
>
|
||||
<LayersIcon className="size-3.5 shrink-0" />
|
||||
<span className="max-w-[170px] truncate">{scopeLabel}</span>
|
||||
<LayersIcon className="size-4 shrink-0" />
|
||||
<span className="max-w-[190px] truncate">{scopeLabel}</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
|
|
@ -177,10 +180,11 @@ export function Composer({
|
|||
aria-haspopup="dialog"
|
||||
aria-expanded={modelOpen}
|
||||
onClick={onOpenModel}
|
||||
title={modelTitle ?? modelLabel}
|
||||
className={pickerChipClass(modelOpen)}
|
||||
>
|
||||
<ChatIcon className="size-3.5 shrink-0" />
|
||||
<span className="max-w-[170px] truncate">{modelLabel}</span>
|
||||
<ChatIcon className="size-4 shrink-0" />
|
||||
<span className="max-w-[190px] truncate">{modelLabel}</span>
|
||||
</button>
|
||||
{!online ? (
|
||||
<span role="status" className="ml-auto shrink-0 text-[11.5px] text-amber-600 dark:text-amber-300">
|
||||
|
|
@ -189,7 +193,7 @@ export function Composer({
|
|||
) : null}
|
||||
</div>
|
||||
|
||||
<AiDisclaimer className="mt-1.5" />
|
||||
<AiDisclaimer plain className="mt-1.5" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -200,9 +204,9 @@ export function Composer({
|
|||
*/
|
||||
function pickerChipClass(open: boolean): string {
|
||||
return cn(
|
||||
"flex min-w-0 items-center gap-1.5 rounded-xl border px-2.5 py-1.5 text-[12px] font-medium transition",
|
||||
"flex min-w-0 items-center gap-1.5 rounded-xl border px-3 py-2 text-[12.5px] font-medium transition",
|
||||
open
|
||||
? "border-[var(--nav-active-border)] bg-[var(--nav-active-bg)] text-[var(--text)]"
|
||||
: "border-[var(--hairline-soft)] bg-[var(--surface-sunken)] text-[var(--text-muted)] hover:text-[var(--text)]",
|
||||
: "border-[var(--hairline)] bg-[var(--surface-sunken)] text-[var(--text)] hover:bg-[var(--hover)]",
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue