967f20f629604e5e38abc471b3da4eb7ea965b76
8 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| ce784e58ab |
v0.3 Phase 5c polish: tighter header, disabled-record clarity, softer notice, attached action bar
Focused polish pass on the Dictation quietware layout per round-10
feedback. No colour exploration; only the eight specific tweaks.
1. Capture header tightened.
Record button + status block now grouped in their own flex
container (gap-3) so they read as one capture component. Record
size dropped from 72px to 64px so the group balances against the
status text. Timer pushed to far right via flex-1 on the inner
group. The trio (record / status / timer) feels like one unit.
2. Disabled Record affordance now reads as record.
Browser-preview state no longer renders as a neutral grey blob.
Instead:
bg-transparent
border-2 border-[color-mix(in_srgb,var(--button-record-bg)_45%,
transparent)]
opacity-80
cursor-not-allowed
inner muted-red dot bg-[color-mix(in_srgb,var(--button-record-bg)
_55%,transparent)]
Result: clearly a record control, clearly disabled, doesn't look
clickable. aria-label updated to "Record (desktop app only)" in
that state so screen readers carry the same message.
3. Slim notice border softened.
LumotiaNotice slim variant now uses border-border-subtle for the
outer border instead of the role-coloured border. Left bar stays
full role colour (the visible signal). Icon stays role colour.
Background stays at the role tinted bg. Net effect: notice is
ambient, not loud.
4. Action bar attached to transcript surface.
Dropped the LumotiaPageSkeleton actionBar slot for Dictation;
moved the buttons into the primary snippet as a bottom row inside
the same surface. Internal border-t + bg-bg-elevated/40 separator
keeps it visually nested. Reads as transcript actions, not a
generic page footer.
Also dropped primaryBleed so LumotiaPageSkeleton's default card
chrome wraps the transcript + action dock together — that gives
the surface boundary Jake asked for in light mode without
introducing a card-heavy treatment.
5. Compact one-line metadata footer.
Was: "Smart · {model} · Local only" + "{formatMode} · {profile}"
Now: "{formatMode} · {model} · Local only / Browser preview · {profile}"
Right-aligned. Single line. No duplicated "Smart". JetBrains Mono
via the existing --font-family-mono. text-tertiary.
6. Typography corrected.
Status title moved from Young Serif italic (font-display) to Work
Sans medium-weight (default body). Young Serif italic is now
reserved for the empty-state "Talk now, think later." line, which
remains the only emotional moment in the page.
7. Light mode surface intentional.
By dropping primaryBleed the skeleton's default surface chrome
(bg-bg-card + border-border-subtle + rounded-lg) wraps the
transcript canvas. Light mode now reads as a deliberate paper
surface, not an open page. Same boundary applies in dark.
8. Colour restraint preserved.
No token changes. Same red/blue/green/yellow/orange grammar.
Wireline contract unchanged. Brand orange still reserved for
logo/identity.
Verified.
- npm run check: 0 errors, 0 warnings across 5707 files.
- Headless screenshots confirm both quietware modes deliver the
polish: tight header, recognisable disabled-record, softer
notice border, attached action dock, compact metadata,
Work Sans status title, clear surface boundary.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 001d8fe83d |
v0.3 Phase 4i: counterlines as interaction-affordance identity
Round-7 redirect (Option D): move counterlines from notices (where
they're invisible) to interactive controls (where they add identity).
Three-level model:
Level 0 no counterline panels, notices (default), content, disabled
Level 1 quiet controls, chips, active nav
1 px, 48% opacity dark / 34% light
Level 2 focus / strong keyboard focus, recording state
2 px, 85% opacity
Notices retire from default counterline rendering. Notice already
carries enough semantic language: bar + icon + border + bg + label.
A complementary inset on top was adding nothing. Notice can opt in
via <LumotiaNotice counterline ... /> when it deliberately mimics
control identity.
Token deltas vs Phase 4h.
--counterline-width: 1px unchanged
--counterline-width-focus: 2px new (Level-2 width)
--counterline-opacity-dark: 0.48 was 0.32 (raised so Level-1
actually reads on controls)
--counterline-opacity-light: 0.34 was 0.22
--counterline-opacity-focus: 0.85 new
--role-brand-counterline: #3A6BFF new (blue counter for the
orange brand accent so
primary buttons get an
identity edge like the
other roles)
--button-{role}-counterline new (per-role component tokens
subscribing to role-counterline
via color-mix)
--focus-ring-color new (defaults to brand accent;
HC overrides to #005FCC)
LumotiaButton applies counterlines to primary + destructive variants
only. Secondary + tertiary stay clean. All variants get a Level-2
focus-visible ring at --focus-ring-color * opacity-focus, with the
existing ring-offset-2 ring-offset-bg pattern.
LumotiaNotice gains a `counterline` boolean prop, default false. When
set, the previous Phase 4h inset shadow re-applies.
HC contract: counterline-width 0 + all -counterline tokens transparent.
Focus width stays 2 px because the HC focus ring IS the tactile
detail in that mode. focus-ring-color forces to #005FCC.
Honest evaluation of the visible result.
Notices: visibly cleaner without the default inset shadow. Reads
with more confidence. Good change.
Buttons: counterline applied at 1 px / 48% dark / 34% light is
perceptible at standard viewing but screenshot-zoom subtle. Focus
state implemented but not visible in static screenshots; requires
manual tab-test in the dev server.
Recommend keeping the architecture even if the visual is restrained,
because the focus-state work is genuinely valuable accessibility
scaffolding regardless of how the Level-1 reads.
Verified.
- npm run check: 0 errors, 0 warnings across 5707 files.
Phase 5c (Dictation layout migration) still queued for a focused
fresh sitting. This commit does not block it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 74bcc293bb |
v0.3 Phase 4h: counterlines test on LumotiaNotice
Test commit for Jake's round-6 spec. Subtle 1-px inset shadow in a
softened complementary hue, applied to LumotiaNotice only. Other
test surfaces (Button.destructive, status pills, record ring, active
nav) reserved for after evaluation.
Tokens (quietware scope only, v0.2 surface unchanged):
--counterline-width: 1px
Raw complementary hues per Jake's table:
--role-info-counterline var(--color-accent) /* copper for blue */
--role-danger-counterline #6EA8FF /* soft blue for red */
--role-success-counterline #B891FF /* soft violet for green */
--role-caution-counterline #3A6BFF /* soft blue for yellow */
Tinted per-mode via color-mix:
Dark mode: 32% opacity (slightly stronger against dark surface)
Light mode: 22% opacity (whisper-quiet against cream)
HC mode: all transparent, --counterline-width: 0
Per-usage notice tokens emitted:
--notice-{role}-counterline
LumotiaNotice applies via Tailwind arbitrary value:
shadow-[inset_0_0_0_var(--counterline-width,0)_var(--notice-{tone}-counterline,transparent)]
HC contract zeroes both the width and the colour token so the 2-px
HC border carries the tactile detail instead.
Honest evaluation of the visible result.
At 1px and 22%/32% opacity the counterline is implemented
correctly but reads as whisper-quiet to the point of being almost
invisible at standard viewing zoom. Doesn't look noisy (the risk
Jake flagged), but also doesn't add perceptible tactility.
Pending Jake's call:
(a) raise opacity to ~45% dark / ~35% light for visibility,
(b) keep at current opacity for the quietness,
(c) revert and proceed Phase 5c.
Phase 5c proceeds either way; this commit does NOT block the
layout migration.
Verified.
- npm run check: 0 errors, 0 warnings across 5707 files.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 2f11f493c5 |
v0.3 Phase 4g: four-tier semantic tokens + notice usage layer
Round-5 feedback flagged the muddy result of forcing one --color-caution
to be both bright yellow (signal) and accessible text (ochre). The
single-token-per-role model collapsed the visible identity. Caution
notices ended up reading as brown/khaki surfaces because color-mix(
in oklab, var(--color-caution) 8%, transparent) over cream produced
muddy results whatever the source hex.
New architecture: four-tier per-role tokens, hand-tuned -bg surfaces,
plus usage-specific notice tokens on top.
Tier model — each semantic role publishes four tokens:
signal Brand-true colour. Left bars, large icons, dots, focus rings.
Looks like the role at a glance.
ink Accessible text variant. Used ONLY when text itself must
carry the role colour. WCAG AA 4.5:1 on its surface.
border Middle value. Visible chip/notice outline; not text-safe.
bg Hand-tuned pale tint surface. NOT a color-mix derivation.
Example, light-mode caution:
--color-caution-signal #FFCD00 (bright yellow)
--color-caution-ink #7A5D00 (ochre, for small text only)
--color-caution-border #D9A900 (mid gold)
--color-caution-bg #FFF7D6 (clean pale yellow tint)
--color-{role} retained as a backward-compat alias pointing at -signal.
v0.2 callers keep working; new code reaches for the specific tier.
Usage layer — components subscribe to usage-specific tokens, not
role-tier tokens directly:
--notice-{role}-bar left bar, signal-tier
--notice-{role}-icon signal in dark, ink in light, signal in HC
--notice-{role}-border outer border colour
--notice-{role}-bg hand-tuned pale surface
LumotiaNotice reads these via Tailwind arbitrary-value classes
(bg-[var(--notice-info-bg)] etc). v0.2 fallback values defined at
:root (outside quietware blocks) using color-mix from v0.2 --color-
{role} tokens so the Notice keeps rendering sensibly when quietware
is off.
HC contract — every -bg token forces to transparent. HC notices
render text + icon + 2-px border + left bar, no body tint. Brand
atmosphere steps fully aside.
Per Jake's round-5 spec: yellow stays yellow as the visible signal,
ochre only appears as small-text ink, and brown/khaki never
represents the caution role's primary visual identity again. Same
discipline applies to red/blue/green — each role has a clean
hand-tuned -bg pale tint per theme.
Verified — visible result.
Light caution notice: bright #FFCD00 bar + signal icon + ink-darkened
small icon + pale #FFF7D6 surface + #D9A900 border. Clean,
semantically clear, no mud.
Dark caution notice: bright #FFCD00 bar + signal icon + dark warm
#29210A surface + bright yellow border. Reads as yellow at a glance.
HC modes: no body tint, strong bordered notices, semantic colours
preserved as primary identifier alongside icon + label.
npm run check: 0 errors, 0 warnings across 5707 files.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| 2fcb5aff78 |
v0.3 Phase 4f/5a/5b: token architecture + skeleton + browser-preview reclass
Three small phases land together for Jake's round-4 feedback. Each is
focused and reviewable. Larger Dictation/Settings/Tasks/History page
migrations are deferred to focused future sittings.
Phase 4f — semantic source / derived token architecture.
Added --semantic-{red,blue,green,yellow}-source raw-palette tokens.
These encode the role's hue identity from Jake's color.adobe.com
palette (#FF0700 / #FFCD00 / #00FF56 / #000AFF) and stay constant
across all themes. The existing --color-{danger,caution,success,info}
tokens are now documented as theme-tuned derivations meeting WCAG
AA in context. Source tokens make the brand-to-runtime relationship
traceable in code.
Added --color-{role}-bg subtle-fill tokens derived via
color-mix(in oklab, var(--color-{role}) 8%, transparent). Used by
Notice backgrounds, hover tints and focus halos. HC mode forces
-bg tokens to transparent so HC notices read as text + icon +
2-px border + left bar with no body tint.
Phase 5a — page skeleton primitive + slim notice variant.
NEW src/lib/ui/LumotiaPageSkeleton.svelte. Six-zone layout:
header (optional)
notice (optional, slim ambient state)
primary work surface (required, primaryBleed for full-bleed)
right rail (optional, lg-screen drawer)
action bar (optional, bottom)
metadata (optional, mono micro-footer)
Every zone except primary is opt-in. Foundation for the
page-skeleton sweep without forcing any page migration yet.
LumotiaNotice gained a slim prop. When true: padding collapses
(px-3 py-2 vs px-4 py-3), icon shrinks (14 vs 16), title block is
suppressed. For ambient page-level notices like browser-preview.
Phase 5b — browser-preview reclassification.
src/lib/pages/DictationPage.svelte: the browser-preview state used
to render as a red error block. That is an environment limitation,
not a failed action. Reclassified as a slim info notice with
friendlier copy:
"You're in a browser preview. Local transcription only works in
the Lumotia desktop app."
Other error states (transcription failed, needs review) still
render through the original danger-tinted block with the
technical-details affordance preserved. Only the browser-preview
path branches into LumotiaNotice tone="info" slim.
The larger Dictation page restructure (header recomposition,
Template/Extract Tasks demotion to bottom action bar, empty-state
typography) is reserved for a focused Phase 5c sitting since
DictationPage.svelte is 1 262 LOC of state-heavy code.
Verified.
- npm run check: 0 errors, 0 warnings across 5707 files.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| dab9c7b5a6 |
v0.3 Phase 4d/4e: palette revision + HC rendering contract
Round-4 feedback (2026-05-15) pulled the system away from the
color.adobe.com primaries toward muted-Material values, separated
brand accent from semantic caution, and reframed high-contrast as a
behavioural rendering contract rather than a palette override.
Two phases land together because the palette revision and the HC
contract are inherently linked — HC mode needs both palette overrides
AND behavioural-token overrides to deliver "different rendering
contract" semantics.
Phase 4d palette revision.
Dark mode (was wine-aubergine #2A1620, now brown-charcoal #12100E):
--color-bg #12100E
--color-bg-elevated #1A1713
--color-bg-card #211D18
--color-bg-input #181510
--color-sidebar #0F0E0C
--color-border #4A4035
--color-border-subtle #2C261F
Brand accent (new — was unset, fell through to v0.2 amber that
competed with semantic yellow):
Dark: --color-accent #C97845 (copper)
Light: --color-accent #9D5F32 (deeper copper)
Semantic colours (muted-Material, both modes):
Dark: danger #FF8A8A caution #F2C94C success #79D59B info #8AB4F8
Light: danger #B3261E caution #7A5D00 success #1B6B3A info #2457A6
Light mode work surface (slight paper tone, not pure white):
--color-bg-card #FFFDF8 (was #FFFFFF)
--color-bg-elevated #F6F1EA
Caution fill-only-on-cream rule retires. Ochre #7A5D00 passes AA
as foreground text on cream under the muted palette, so the single-
token-per-role convention applies across all four semantic colours
in both modes.
LumotiaNotice opacity rebalance:
Background tint 10% -> 8%
Outer border neutral subtle -> role at 40%
Icon --color-text -> role colour
Left bar role at 100% (unchanged)
Title / body --color-text (unchanged)
Phase 4e HC rendering contract.
Behavioural tokens published alongside palette:
--grain-opacity 0.06 dark / 0.07 light / 0 in HC
--shadow-strength 1 default / 0 in HC
--border-width-control 1px default / 2px in HC
--focus-ring-width 2px default / 3px in HC
--panel-radius 8px (reserved for future tightening)
--quietware-texture-opacity retained as a legacy alias pointing at
--grain-opacity so Phase 4c slider keeps working through the rename.
HC palette: pure-black or pure-white base, the other for borders,
single strong-focus blue #005FCC replaces accent. Brand atmosphere
steps aside. Selector splits via :not([data-theme="light"]) so
HC-light and HC-dark variants diverge cleanly.
Verified.
- npm run check: 0 errors, 0 warnings across 5706 files.
- Plan doc updated with full before/after tables, behavioural-token
contract table, and Phase 4c / 4d / 4e log sections.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| db9c50c548 |
v0.3 Phase 3: status grammar — LumotiaNotice left-bar refactor
Phase 3 audit found that both LumotiaStatusPill and LumotiaNotice
already shipped in v0.2 Phase 5. Phase 3 reduced to an audit-and-adapt
pass.
LumotiaStatusPill ($lib/components/StatusPill.svelte) is already
correct for quietware. Pattern: neutral pill background + neutral
label text + role colour confined to a 6x6 px dot. Colour is
supplementary, label is always perceivable. Works unchanged across
all three quietware modes. No changes shipped.
LumotiaNotice ($lib/ui/LumotiaNotice.svelte) refactored to the
left-bar accent pattern. Previously the role colour rendered on the
icon outline and on the entire surround border at 30% opacity; in
quietware light mode that left the bright #FFCD00 caution colour
faded against cream paper. New pattern:
- 4-px solid LEFT border in the tone colour, 100% opacity.
- Soft tone-tinted background (10% opacity) for ambient cue.
- Subtle neutral outer border on the other three sides.
- Icon, title and body text all use --color-text.
Visible signal lives on the large bar (works at any contrast level);
foreground text uses the always-legible neutral. Matches Material
Design "banner with leading accent" and IBM Carbon "inline
notification" guidance. ARIA semantics (role="alert" for danger,
role="status" for the rest) preserved.
Design-system-v2 preview route already imports both primitives. The
updated Notice renders correctly with the existing preview content;
no additional wiring required.
Caution remains a fill-only convention on cream by design. Any
darkened yellow reads as olive ("looks like poop", per Jake), so the
fill-only rule stays in force and this pattern delivers it cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|||
| c60f0aa5a5 |
v0.2 Phase 5: 11 primitives + gated design-system-v2 preview
Custom-styled primitives (no headless dep): LumotiaButton — primary/secondary/tertiary/destructive × sm/md/lg LumotiaIconButton — square icon-only; ghost/filled/destructive LumotiaNotice — info/caution/danger/success inline notice LumotiaProgress — native <progress> + token theming LumotiaField — plain + Formsnap modes share the same markup Bits UI 2.18.1 wrappers (warm-brutalist styling): LumotiaSelect — single-select, options=[] LumotiaCombobox — searchable; one-way inputValue + oninput LumotiaDialog — controlled open; closable + footer snippet LumotiaTabs — orchestrates List/Trigger/Content from a tabs array LumotiaTooltip — wraps Provider + Root + Trigger + Content LumotiaMenu — DropdownMenu items=[] with destructive variant design-system-v2 preview route: src/routes/design-system-v2/+page.ts gates with VITE_LUMOTIA_DESIGN_SYSTEM_V2=1. Without the flag the load() throws 404 — route-level gate, not nav- hidden. Run via VITE_LUMOTIA_DESIGN_SYSTEM_V2=1 npm run dev:frontend to see the showcase. Browser-mode component test: src/lib/ui/LumotiaButton.browser.test.ts. Covers render, click, and disabled-blocks-click. Validates that vitest-browser-svelte + the @vitest/browser-playwright provider land Phase 1's tooling contract end-to-end. 3/3 passing in Chromium. Type fix: LumotiaIconButton and LumotiaMenu accept icon: any so lucide-svelte's legacy SvelteComponentTyped shape composes with our Svelte 5 wrappers without forcing a // @ts-nocheck escape hatch on every call site. Tightens to Component<…> once lucide-svelte ships a Svelte 5 build. Type fix: LumotiaCombobox honours Bits UI 2.x Combobox.Root's one-way inputValue contract. The wrapper drops bind:inputValue and exposes an oninput callback so caller-owned filter pipelines (HistoryPage FTS5, ModelDownloader) can drive options upstream. Phase 5 per-page gate green: npm run check (0/0/5700 files), npm test, npm run test:browser (3/3 in Chromium), npm run test:e2e (16/16), guard-no-skeleton clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |