From 2fcb5aff786ea40267dc5476242ae37dd874b1bb Mon Sep 17 00:00:00 2001 From: Jake Date: Fri, 15 May 2026 14:12:33 +0100 Subject: [PATCH] v0.3 Phase 4f/5a/5b: token architecture + skeleton + browser-preview reclass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- docs/release/v0.3-tactile-quietware.md | 39 +++++++++ src/design-system/v0.3-quietware-tokens.css | 68 +++++++++++++--- src/lib/pages/DictationPage.svelte | 55 ++++++++----- src/lib/ui/LumotiaNotice.svelte | 12 ++- src/lib/ui/LumotiaPageSkeleton.svelte | 87 +++++++++++++++++++++ 5 files changed, 227 insertions(+), 34 deletions(-) create mode 100644 src/lib/ui/LumotiaPageSkeleton.svelte diff --git a/docs/release/v0.3-tactile-quietware.md b/docs/release/v0.3-tactile-quietware.md index 41042d6..721333d 100644 --- a/docs/release/v0.3-tactile-quietware.md +++ b/docs/release/v0.3-tactile-quietware.md @@ -285,6 +285,45 @@ LumotiaNotice opacity rebalance: | Icon | `--color-text` | role colour | | Title / body | `--color-text` | `--color-text` (unchanged) | +### Phase 4f — Semantic source / derived token architecture. Landed 2026-05-15. + +Round-4 feedback formalised the relationship between the brand-source palette and the theme-derived semantic tokens. Source tokens are stable across all themes (they encode the role's hue identity); derived tokens are theme-tuned to meet WCAG AA in context. + +Added to `src/design-system/v0.3-quietware-tokens.css`: + +```css +:root[data-design="quietware"] { + --semantic-red-source: #FF0700; /* error / failed / destructive / blocked */ + --semantic-yellow-source: #FFCD00; /* needs review / caution / pending */ + --semantic-green-source: #00FF56; /* ready / saved / complete / safe */ + --semantic-blue-source: #000AFF; /* info / processing / system guidance */ +} +``` + +The existing `--color-{danger,caution,success,info}` tokens are documented as derivations of these sources, retuned per theme (muted-Material values in normal modes, clarity-first values in HC). New `--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 all `-bg` tokens to `transparent` so HC notices render as text + icon + 2-px border + left bar with no body tint. + +### Phase 5a — Page skeleton primitive + slim notice variant. Landed 2026-05-15. + +Foundation for the page-skeleton sweep without yet migrating any page. Two additions: + +- **`LumotiaPageSkeleton.svelte`** ([src/lib/ui/](../../src/lib/ui/LumotiaPageSkeleton.svelte)) — six-zone layout used by every quietware page: header / optional slim notice / primary work surface / optional right rail / optional bottom action bar / optional mono metadata footer. Sidebar lives in AppChrome above the skeleton. Every snippet is optional except `primary`. `primaryBleed` prop drops the surface's inner card chrome for full-bleed transcript canvases. + +- **`LumotiaNotice` `slim` prop** — collapses padding, drops the title block, smaller icon. For one-line ambient notices like browser-preview state. + +### Phase 5b — Browser-preview reclassification. Landed 2026-05-15. + +Targeted scope per Jake's round-4 feedback: the browser-preview state used to render as a red error block in `DictationPage.svelte`. That is an environment limitation, not a failed action. Reclassified as a slim info notice with friendlier copy: + +``` +Old: bg-danger/10 border-danger/20, red text, technical-details affordance +New: LumotiaNotice tone="info" slim, "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 the info-classed notice. + +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 — `DictationPage.svelte` is 1 262 LOC of state-heavy code and warrants surgical attention rather than a tail-end rush. + ### Phase 4e — High-contrast rendering contract. Landed 2026-05-15. High-contrast is not a colour variant — it's a different rendering contract that the entire UI subscribes to. The tokens block now publishes behavioural variables alongside the palette overrides, so components can opt into the contract by reading them. diff --git a/src/design-system/v0.3-quietware-tokens.css b/src/design-system/v0.3-quietware-tokens.css index 92993d1..ddd5c35 100644 --- a/src/design-system/v0.3-quietware-tokens.css +++ b/src/design-system/v0.3-quietware-tokens.css @@ -65,6 +65,33 @@ font-display: swap; } +/* ============================================================ + Semantic source palette (Phase 4f, 2026-05-15). + + These four hex values are the BRAND-identity source for the + semantic system. They are NEVER used directly as text or fill + in the runtime UI — each --color-{role} is a theme-tuned + derivation that meets WCAG AA in its context. The source tokens + exist so the relationship between brand-source and theme-derived + is traceable in code (and so a future re-tune of one role does + not require chasing every reference). + + Red -> error, failed, destructive, blocked + Yellow -> needs review, caution, missing setup, pending + Green -> ready, saved, complete, safe + Blue -> information, processing, neutral system guidance + + The brand accent (--color-accent, copper-clay) is intentionally + separate from semantic yellow. Brand is action / Lumotia + identity. Yellow is caution / review. + ============================================================ */ +:root[data-design="quietware"] { + --semantic-red-source: #FF0700; + --semantic-yellow-source: #FFCD00; + --semantic-green-source: #00FF56; + --semantic-blue-source: #000AFF; +} + /* ============================================================ Quietware — dark mode default. Warm brown-charcoal atmosphere. Reads as warm when you notice @@ -89,12 +116,22 @@ --color-accent-subtle: #C9784514; --color-accent-glow: #C9784525; - /* Semantic palette. Muted-Material hues. */ - --color-danger: #FF8A8A; - --color-caution: #F2C94C; + /* Semantic palette. Derived from --semantic-{role}-source by + lowering saturation/chroma and tuning lightness for AA on the + dark surface. Each role keeps the source hue identity. */ + --color-danger: #FF8A8A; /* derived from --semantic-red-source #FF0700 */ + --color-caution: #F2C94C; /* derived from --semantic-yellow-source #FFCD00 */ --color-warning: var(--color-caution); - --color-success: #79D59B; - --color-info: #8AB4F8; + --color-success: #79D59B; /* derived from --semantic-green-source #00FF56 */ + --color-info: #8AB4F8; /* derived from --semantic-blue-source #000AFF */ + + /* Subtle role fills for Notice backgrounds, hover tints, focus + halos. ~8% role over the surface — passes through atmosphere + without becoming a colour zone. */ + --color-danger-bg: color-mix(in oklab, var(--color-danger) 8%, transparent); + --color-caution-bg: color-mix(in oklab, var(--color-caution) 8%, transparent); + --color-success-bg: color-mix(in oklab, var(--color-success) 8%, transparent); + --color-info-bg: color-mix(in oklab, var(--color-info) 8%, transparent); --color-sidebar: #0F0E0C; --color-nav-active: #211D18; @@ -142,11 +179,17 @@ --color-accent-subtle: #9D5F3214; --color-accent-glow: #9D5F3225; - --color-danger: #B3261E; - --color-caution: #7A5D00; + /* Semantic palette — derivations for light mode, AA on cream. */ + --color-danger: #B3261E; /* derived from --semantic-red-source */ + --color-caution: #7A5D00; /* derived from --semantic-yellow-source */ --color-warning: var(--color-caution); - --color-success: #1B6B3A; - --color-info: #2457A6; + --color-success: #1B6B3A; /* derived from --semantic-green-source */ + --color-info: #2457A6; /* derived from --semantic-blue-source */ + + --color-danger-bg: color-mix(in oklab, var(--color-danger) 8%, transparent); + --color-caution-bg: color-mix(in oklab, var(--color-caution) 8%, transparent); + --color-success-bg: color-mix(in oklab, var(--color-success) 8%, transparent); + --color-info-bg: color-mix(in oklab, var(--color-info) 8%, transparent); --color-sidebar: #F3EEE6; --color-nav-active: #E8E2D6; @@ -191,6 +234,13 @@ --color-success: #1B6B3A; --color-info: #005FCC; + /* HC strips fill atmosphere. Notices become text + icon + 2-px + border + left bar with no body tint. Maximum clarity. */ + --color-danger-bg: transparent; + --color-caution-bg: transparent; + --color-success-bg: transparent; + --color-info-bg: transparent; + --color-sidebar: #FFFFFF; --color-nav-active: #000000; --color-hover: #F0F0F0; diff --git a/src/lib/pages/DictationPage.svelte b/src/lib/pages/DictationPage.svelte index d73f1da..60b854e 100644 --- a/src/lib/pages/DictationPage.svelte +++ b/src/lib/pages/DictationPage.svelte @@ -29,6 +29,10 @@ const prefs = getPreferences(); const tauriRuntimeAvailable = hasTauriRuntime(); const browserPreviewMessage = "You're viewing Lumotia in a normal browser. Local transcription only works in the Tauri desktop app window."; + // v0.3 Phase 5b — shorter calmer copy used for the info-classed + // notice when the same condition surfaces in the UI. Same physical + // limitation, friendlier framing per round-4 feedback. + const browserPreviewSlim = "You're in a browser preview. Local transcription only works in the Lumotia desktop app."; let transcript = $state(""); let segments = $state([]); @@ -1127,31 +1131,40 @@ {/if} - + {#if error}
-
-
- {#if transcriptionFailed} - - {:else} - + {#if error === browserPreviewMessage} + { error = ""; errorDetail = ""; }}> + {browserPreviewSlim} + + {:else} +
+
+ {#if transcriptionFailed} + + {:else} + + {/if} +

{error}

+
+ {#if errorDetail} +
+ Technical details +
{errorDetail}
+
{/if} -

{error}

+
+ +
- {#if errorDetail} -
- Technical details -
{errorDetail}
-
- {/if} -
- -
-
+ {/if}
{/if} diff --git a/src/lib/ui/LumotiaNotice.svelte b/src/lib/ui/LumotiaNotice.svelte index dc86136..d74cd7f 100644 --- a/src/lib/ui/LumotiaNotice.svelte +++ b/src/lib/ui/LumotiaNotice.svelte @@ -32,6 +32,9 @@ title?: string; dismissible?: boolean; onDismiss?: () => void; + /** Slim variant collapses to a single line with no title block. + For ambient page-level notices (eg. "You're in browser preview"). */ + slim?: boolean; children?: Snippet; classes?: string; } @@ -41,6 +44,7 @@ title, dismissible = false, onDismiss, + slim = false, children, classes = "", }: Props = $props(); @@ -85,13 +89,13 @@
-