Aura Coach — ClayLegacy format

Clay is the design system of Aura Coach AI, a Flutter app for learning English (UI in English and Vietnamese). It features pastel accents on a warm cream canvas, cards with offset shadows, dark ink accents, and press-down interactions.

Accent hexes never move with brightness. Dark mode stays in the warm purple-blue family: the dark surface IS the light text colour#2D3047
background#FFF8F0
surface#FEFCF9
surfaceAlt#F5EDE3
Headline
Aa
Search
Body
Aa
Label
Aa
Label

Color Palette

Typography

displayLgFredoka · 32px · Extra Bold

Every letter tells a story worth reading, and every typeface gives that story a new voice waiting to be heard.

displayMdFredoka · 28px · Bold

Every letter tells a story worth reading, and every typeface gives that story a new voice waiting to be heard.

titleNunito · 20px · Bold

Every letter tells a story worth reading, and every typeface gives that story a new voice waiting to be heard.

labelMdNunito · 13px · SemiBold

Every letter tells a story worth reading, and every typeface gives that story a new voice waiting to be heard.

bodyMdInter · 16px · Regular

Every letter tells a story worth reading, and every typeface gives that story a new voice waiting to be heard.

buttonNunito · 15px · Bold

Every letter tells a story worth reading, and every typeface gives that story a new voice waiting to be heard.

captionSmInter · 10px · Regular

Every letter tells a story worth reading, and every typeface gives that story a new voice waiting to be heard.

Clay is the design system of Aura Coach AI, a Flutter app for learning English (UI in English and Vietnamese). It features pastel accents on a warm cream canvas, cards with offset shadows, dark ink accents, and press-down interactions.

Components

Buttons

Cards

Card Title

Sample body text for the card component.

Elevation & Depth

control
controlBold
card

Do's & Don'ts

Do

Use dark ink on accents via `surfaces.inkOn(fill)` with `surfaces.tinted(bandFill(fill))` or `accentInkOr(AppColors.warmDark)`
Cast blur-0 offset drops on controls and none on sunken surfaces (wells, trays)

Don't

Put white on accents like #5FB5AB or #8A6FB0; those have low contrast ratios (1.63:1 to 2.92:1)
Add blur to control drops in classic/intaglio, which reduces shadow visibility at dark surface intersections
Hardcode border widths; always use `AppBorders` for 0.5/1.0/1.2/1.5/2.0 values

Icons

Material Icons
star
plus
?
chat
?
comment
?
moon
?
stop
?
table
?
appicon

Library: Material Icons · Style: outline · Size: 20px

Theming Axes (Brightness · Skin · Topic)

Three questions, three orthogonal axes, three ThemeExtensions on every ThemeData:

Brightness — how bright is the room. ClayPalette flips chrome; accents stay.

Skin — what a widget is MADE of: bands, drops, radii, press depth, on-accent ink. ClaySkinSurfaces. Persisted as aura.set.claySkin; picker in Settings › App › Skin.

Topic — WHERE we are: ground, ornament vocabulary, later icons. ClayTopicScape. Persisted as aura.set.clayTopic; three topics are offered (shape, school, space); unknown values clamp to shape.

Any skin can sit in any topic (pebble-in-space is valid): a topic never touches widget grammar, a skin never touches the ground.

Skins

classic — flat fills (raised/well/tray null), white on-accent ink, decorative border everywhere, no washes, sharp drops, motifLevel 0. Pinned by 18 literal hex tests. Exempt from AA.

intaglio (default) — the 70/30 Clay×Lumi hybrid (spec count 135 Clay / 46 Lumi / 11 WCAG slots): canvas unchanged, band gradients, ink #1E202F, borderControl at ≥ 3.0:1, sharp drops kept, motifLevel 1.

pebble — the 30/70 inverse: warm deep canvas separating by colour (1.17:1), blurred warm drops, radii 28/20, press 0.96, borders erased with width preserved, bands 18%, motifLevel 2.

Skin API a widget may use raised / well / tray · tinted(accent) · banded(fill, darkScale) · inkOn / bandFill / accentInkOr · inkBorderOr · focusRing · borderControl · radiusLg / radiusMd · pressScale · motifLevel · washFor(accent). Recipes: card-on-canvas → raised; accent control → tinted; arbitrary fill (tint card, white pill, notification row) → banded.

Skin and topic transitions snap the whole object at t = 0.5 rather than lerp per field: a half-lerped null gradient flipped every == null gate and rendered cards see-through for one frame.

Topics

shape — today's app; every ground field null, bit-identical to no-topic.

school — paper world in light mode: page #F2F6FC, surface #FFFFFF, ink #23293A, inkMuted #4F5769 (6.7:1). In dark mode it is the same room with the lights down — schoolDark runs at Brightness.dark on #1B1F2A → #222735 → #2A3040 with ink #EDF1F8. Stationery ornaments; accentMix 0.18. Only Space forces one brightness in both modes.

space — indigo sky in BOTH brightnesses (theme forced dark): ground #141C44 → #212857 → #2A2660, chrome bg #1E2454, surface #232A58, border #3A4180, ink #EEF2FF, muted #C3CBEC, faint #A6ADD6; after-midnight variant #0A0F2A → #141A45 → #241F5C; celestial ornaments; accentMix 0.16 in light, 0.14 in dark. The horizon moved from #3B3585 to #2A2660 because its luminance (.088) sat under the ornament ceiling (.095) and flattened every ornament.

The mode accent is blended into the horizon stop only (0 at the sky top); chat grounds use half the mix.

A topic with a ground recolours the WHOLE app: the palette comes from scape.paletteFrom(skin palette) and the skin's surfaces are rebasedOn(topic surface) — band gradients bake hue as well as geometry, so handing them over verbatim paints warm-brown cards on an indigo sky. Region-scoped theming was tried and removed. Geometry stays the skin's; colour becomes the topic's (test-locked).

Motion

Durations (ms) fast 150 (state swaps) · medium 200 (chips, check circles) · normal 300 (page transitions, message entrance) · press 80 · inputFocus 120 (faster than fast on purpose) · debounce 600 (also the StaggeredEntrance default) · stagger 800 (auth/onboarding) · score 900 (score sweep + count-up) · celebration 2000 · iconLoop 2400 (idle icon life) · float 2800 (mode-card icon drift 0 → −6px). Orphans with zero consumers: slow 500 (a Future.delayed only), typingWave 1200, pulse 2200, springGentle.

Curves. One house curve, easeClay = Curves.easeInOut. Press-in and StaggeredEntrance use easeOut; MessageEntrance uses easeClay. elasticOut appears at exactly two reward moments (score circle scale 0.6→1.0 over the first 50%; mind-map node pop capped at 1.08×) — an observed convention, not a declared rule. easeOutBack and bounceOut are absent.

Spring. springTap mass 1 / stiffness 400 / damping 15 (ζ ≈ 0.375 derived; documented as ~28% overshoot) — the only spring in the app, on press release. The spec rejected Lumi's 56% overshoot as too bouncy for a study app used in long sessions.

Page transitions. fadeTransitionPage for go() replacements (4 routes); slideFadeTransitionPage for push() (32 routes): fade + slide from 6% of height, 300ms easeClay.

Entrances. StaggeredEntrance: child i starts at i × 0.12 (clamped ≤ 0.7), window 0.4, 16px rise. MessageEntrance: 20px rise, 300ms. CelebrationOverlay: 40 confetti particles in the four accents, 4–10px, alpha 0.8, fading over the last 30% of 2000ms; no tiers — all three call sites use defaults.

Reduce motion (MediaQuery.disableAnimations): page transitions return the bare child; StaggeredEntrance becomes a Column; confetti is removed; icons hold frame 0; press skips the scale and snaps (haptic still fires); Lottie stops and the orb video never initialises. No test covers any motion token.

Accessibility Contract

Ruler. Every lock computes WCAG 2.x contrast from Color.computeLuminance: (Lmax + 0.05) / (Lmin + 0.05). Thresholds: text 4.5:1 (14px w800 button labels are NOT large text); UI boundaries and focus 3.0:1. All theme tests gate CI. No golden tests; no meetsGuideline.

Locked for intaglio and pebble, both brightnesses

onAccent ≥ 4.5:1 on teal, gold, coral, purple, success, error; purpleDeep asserted to FAIL so nobody "completes" the map.

inkOn(fill) pinned to #1E202F and ≥ 4.5:1 on bandFill(fill) for 9 fills; never worse than the previous ink on any fill (tolerance 0.005).

textMuted ≥ 4.5:1 on background, surface, surfaceAlt (classic exempt).

focusRing ≥ 3.0:1 vs the well mid-stop for teal, purple, gold, coral.

Space topic: ink and inkMuted ≥ 4.5:1, inkFaint ≥ 3.0:1 on every ground stop; four accents ≥ 4.5:1 on the space surface; horizon > 0.025 below the ornament ceiling.

Motifs: lighter than canvas, no shadow, textMuted ≥ 4.5:1 on every tone.

Source guards: surfaces.onAccent outside core/theme only in two allow-listed story files; onAccent.withValues( forbidden; bare border widths forbidden.

Band grammar: raised top brighter than bottom; well and tray inverted.

Classic fidelity: 18 palette hexes, null gradients, white ink, (3,3) drop.

Classic debts pinned so they can neither rot nor be silently patched — warmDark on purple 4.42:1 (±0.01); white on story gradients worst 1.63:1 (±0.02); white on purpleDeep CTAs 4.22:1. Founder decides.

Measured absences

No keyboard focus ring on any pressable (0 focus vs 124 pressable sites); the spec's two-tone ring (#14162A 3px / #FFFDF7 2px, self-contrast 17.53:1) is unimplemented.

Min tap target 44 is sized explicitly at only a handful of shared-widget sites; there is no touch-target token.

textFaint is unguarded and still used at ~65 live sites at 2.32–2.63:1; the textDisabled rename has not landed.

AppColors.onAccent (#FFFFFF) survives at 43 painter sites (40 as glyph veils) outside the guard regex.

The accent-as-text tint ramp (154/154 solved pairs per the spec's own arithmetic) is unimplemented; the pattern fails at 1.27–3.49:1 wherever used.

borderControl is consumed at 3 sites; ~30–40 of 180 clay.border sites are real controls still on the 1.29:1 decorative hex.

The streak heatmap uses teal at alpha 0.35 / 0.6 / 0.8, unmeasured; the spec's SC 1.4.11 ramp #39978D → #2E7971 → #245E58 → #1A443F is not in code.

Painters baking warmDark render 1.00:1 on the dark surface; no guard.

Classic fails AA broadly (textMuted 4.42, border 1.25, white on accents 1.63–2.92) — a fidelity snapshot, not a target.

Download .md

License MIT
Uploaded 1 weeks ago
Version v1
File size 30.9 KB
Downloads 18
Copies 2

Use with MCP

Using designmd mcp, download the design system https://designmd.ai/luuphuc6297/aura-coach-clay and implement it in my code

Don't have the MCP? Install it here