Skip to content

Design system

The brand system lives in docs/design/ in the repo (published as deep dives); this page is the working summary.

  1. Content is the colour. Posters carry colour; chrome is black, grey and glass.
  2. One accent, used for actions. Rose means “you can do something here” — play, apply, clear, retry. It never marks a state.
  3. Glass only for what floats. Nav bar, search field, sheets. Cards and lists are solid.
  4. Readable first. Every text token passes WCAG AA (4.5:1) — a test checks it.
  5. Motion explains. Nothing loops or bounces for decoration.
  6. Within thumb reach. The main input sits in the bottom third.
Token set File Covers
AppColors, AppSpace, AppRadius, AppMotion, AppSize lib/presentation/theme/app_tokens.dart Colour roles, spacing, radii, motion
AppText lib/presentation/theme/app_text.dart The type scale
GlassTokens + lib/presentation/widgets/glass/ glass_tokens.dart The Liquid Glass kit: GlassSurface, GlassPill, GlassChip, GlassCapsule, GlassEdgeFade

Use roles, not appTheme.* primitives or literals. tool/design_ratchet.dart fails the gate (exit 17) if untokenised values rise; --report lists the next files to migrate:

Terminal window
fvm dart run tool/design_ratchet.dart --report

Sizes are design points on a kDesignWidth-wide phone (370), scaled by one factor:

  • phones: s = width ÷ kDesignWidth
  • tablets: s = 1

lib/core/utils/design_scale.dart owns this. Rules of thumb:

  • Tokens (AppSize, AppSpace, AppRadius, AppText) scale themselves.
  • Raw lengths carry .s.
  • Never scale ratios, and scale Flutter constants (like kToolbarHeight) where they meet ours.
  • Text scale is clamped to [1.0, 1.1] so large-text accessibility settings can’t break layouts.

The old sizer units (.h / .v / .adaptSize / .fSize) are gone; Sizer only fills SizeUtils for legacy plugins.