Files
kvitt/docs/ux/tokens.md
T
jacobh2 b72ac5bb9e UX sprint U1: three directions, IA, screens, flows, components, tokens, strings
Three visual directions (Skärgård, Kvitto, Kalas) as self-contained HTML pages with
every SPEC §13.3 screen in light and dark, Swedish, plus PNG exports and the exporter
script. Direction-independent docs: ia.md, screens.md, flows.md, components.md,
tokens.md (values for all three directions), strings.csv (key,en,sv,notes), and the
comparison with a recommendation in directions/README.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 08:27:51 +02:00

16 KiB
Raw Blame History

Kvitt: design tokens

Status: U1 proposal (2026-10-17). One token set of names (binding once the owner picks a direction) with values for all three directions (directions/1-skargard, 2-kvitto, 3-kalas), so :core:design can be built from whichever is chosen. After the pick, U2 copies the chosen column into design-spec.md and deletes the other two here (one source of truth). Each direction's review page recomputes every contrast ratio below in JavaScript and marks failures; the values here were checked there.

Contrast targets (SPEC §13.1): text ≥ 4.5:1 against the surface it sits on; icons and graphics ≥ 3:1; nothing conveyed by colour alone.

1. How tokens map to Compose

Token group Compose home in :core:design Notes
Material 3 colour roles (§2) lightColorScheme(...) / darkColorScheme(...) names map 1:1 (on-primary-container → onPrimaryContainer)
Kvitt semantic roles (§3) KvittColors data class in a CompositionLocal, light and dark instance owed*, owing*, settled*, warning*, pending, avatar*
Category colours (§4) KvittColors.category(ColorToken) and .categoryContainer(ColorToken) ColorToken enum from :core:model (§14.2.4)
Chart colours (§5) KvittColors.chartCategorical[0..7], chartSequential[0..4], chartGrid, chartAxisLabel
Type (§6) Typography(...) + KvittTypography(amountHero, amountLarge, amountMedium, amountSmall) amounts always fontFeatureSettings = "tnum"
Spacing (§7) object KvittSpacing { val s1 = 4.dp … }
Shapes (§8) Shapes(extraSmall…extraLarge) + KvittShapes for the Expressive sizes and custom shapes
Elevation, motion (§9) MotionScheme (Expressive) or durations/easings constants

Dynamic colour (Material You): offered only by Skärgård, as an off-by-default option that replaces §2 only; §3–§5 keep their values in every case.

2. Material 3 colour roles

L = light, D = dark.

Token Skärgård L Skärgård D Kvitto L Kvitto D Kalas L Kalas D
primary #1A6476 #8ED0E2 #23408E #B3C3FF #B23A1C #FFB59F
on-primary #FFFFFF #00363F #FFFFFF #112A6A #FFFFFF #5E1604
primary-container #C2E8F3 #0E4D5C #DCE3F6 #2B4590 #FFDBD0 #8A2A10
on-primary-container #0B4C5C #C2E8F3 #14295E #DDE3FF #3D0B00 #FFDBD0
secondary #4E5F69 #B6C9D4 #4E5466 #C2C6D8 #4B6A2A #B2D38A
on-secondary #FFFFFF #20333B #FFFFFF #2B3040 #FFFFFF #1F3701
secondary-container #D3E3EE #374952 #DFE2EB #3B4050 #D3EFAE #344F15
on-secondary-container #374851 #D3E5F0 #1B2030 #DEE1F1 #112000 #D3EFAE
tertiary #7B5C24 #E8C48A #73552A #DCC39A #7A5900 #F2C14E
on-tertiary #FFFFFF #422C00 #FFFFFF #3E2D10 #FFFFFF #402D00
tertiary-container #F7DFB4 #5D4410 #F1E2C8 #574425 #FFDF8E #5A3F00
on-tertiary-container #5A410E #FFDEA8 #2E1F06 #F7E1BD #261A00 #FFDF8E
error #B3261E #F2B8B5 #B0261B #FFB4A8 #BA1A1A #FFB4AB
on-error #FFFFFF #601410 #FFFFFF #690004 #FFFFFF #690005
error-container #F9DEDC #8C1D18 #F9DCD6 #8E1E14 #FFDAD6 #93000A
on-error-container #8C1D18 #F9DEDC #5A0E08 #FFDAD4 #410002 #FFDAD6
surface #F6FAFC #0F1417 #F7F4EC #1C1A17 #FFF8F1 #1D1415
on-surface #171C1F #DEE3E6 #1D1B17 #ECE6DA #231918 #F1DFDB
surface-variant #DBE4E8 #40484C #E7E2D6 #4A463E #F5DED6 #53433F
on-surface-variant #40484C #BFC8CC #58534A #C0B9AB #53433F #D8C2BB
surface-container-lowest #FFFFFF #0A0F11 #FFFDF8 #161512 #FFFFFF #170F10
surface-container-low #F0F4F7 #171C1F #F2EEE5 #211F1B #FFF1E8 #251B1C
surface-container #EAEFF2 #1B2124 #EDE9DF #26241F #FAEADF #2A1F20
surface-container-high #E4E9EC #252B2E #E6E1D6 #302D28 #F4E4D8 #352A2A
surface-container-highest #DEE3E6 #303639 #E0DBCF #3B3832 #EEDED2 #403434
surface-dim #D6DBDE #0F1417 #D9D4C8 #1C1A17 #E6D6CB #1D1415
surface-bright #F6FAFC #353A3D #FBF9F3 #42403A #FFF8F1 #463A3A
inverse-surface #2C3134 #DEE3E6 #32302B #ECE6DA #392E2C #F1DFDB
inverse-on-surface #EDF1F4 #2C3134 #F4F0E7 #32302B #FFEDE7 #392E2C
inverse-primary #8ED0E2 #1A6476 #B3C3FF #23408E #FFB59F #B23A1C
outline #70787C #899296 #7E786C #8D877A #85736E #A08C87
outline-variant #BFC8CC #40484C #D3CDC0 #48443C #D8C2BB #53433F
scrim #000000 (40 %) #000000 #000000 (42 %) #000000 #000000 (38 %) #000000

Key contrast (text role vs surface, L / D): on-surface 16.4 / 14.3 · 15.6 / 14.0 · 16.3 / 14.0; on-surface-variant 8.9 / 10.9 · 6.9 / 8.9 · 8.9 / 10.6; primary 6.4 / 10.8 · 8.7 / 10.1 · 5.7 / 10.6. outline is used for graphics only (3.99–5.84).

Direction-specific extra aliases: Kvitto paper (= surface-container-lowest in light, surface-container-high in dark; the receipt surface). Kalas card (#FFFFFF / #2A1F20) and on-cat (#FFFFFF / #1D1415, icon colour on solid category tiles).

3. Kvitt semantic roles

Token Use Skärgård L D Kvitto L D Kalas L D
owed text/graphic: partner owes you #00695C #7DD8C5 #2C6A38 #92CC9A #1B6B45 #8BD8A8
on-owed #FFFFFF #00382F #FFFFFF #0E3818 #FFFFFF #003920
owed-container #C2EDE4 #005047 #DCEBD8 #1E3A24 #C4EFD2 #0F5233
on-owed-container #00443B #A3F2E0 #123A1C #BFE8C4 #00210F #A7F5C3
owing text/graphic: you owe partner #A33E1C #FFB59E #A23B25 #F2A890 #7E2F84 #F2AEF0
on-owing #FFFFFF #5E1700 #FFFFFF #4F1708 #FFFFFF #4C0F53
owing-container #FFDBCF #7E2C0E #F6DDD3 #4B2418 #F9D7F6 #66226C
on-owing-container #792A0B #FFDBCF #4D170A #FFDACD #33003A #FFD6F8
settled "Kvitt" / "Ni är kvitt" #4E5F69 #B6C9D4 #58534A #C0B9AB #6E5500 #F2D45C
settled-container #DCE5EA #2C3B43 #E6E1D6 #302D28 #FFE38F #5A3F00
on-settled-container #36464F #D3E5F0 #2A2823 #E5DFD2 #241A00 #FFE38F
warning over-settle, sync warnings #855700 #F5BD62 #875400 #EBC06C #8A4D00 #FFB86E
on-warning #FFFFFF #452B00 #FFFFFF #3E2900 #FFFFFF #4A2800
warning-container #FFDEAD #633F00 #F7E3BF #4D3708 #FFDDBA #6A3B00
on-warning-container #633F00 #FFDEAD #3B2600 #FCE3AE #2C1600 #FFDDBA
pending sync-pending marker #7B5C24 #E8C48A #875400 #EBC06C #00658F #86CFFF
avatar-1 initials background, user slot 1 #C2E8F3 #0E4D5C #3F5E4C #A5C9B0 #9A4A00 #FFB870
on-avatar-1 #0B4C5C #C2E8F3 #FFFFFF #10291A #FFFFFF #2E1500
avatar-2 initials background, user slot 2 #F2DDB8 #5D4410 #6B4C8A #CDB4E8 #2C5F9E #A8C8FF
on-avatar-2 #5A400E #F7DFB4 #FFFFFF #2F1B45 #FFFFFF #002F64

All owed/owing text values ≥ 5.6:1 on surface in both themes in all directions. Owed/owing hue pairs are chosen to stay distinct for red-green colour blindness (Skärgård sea-green vs coral, Kvitto green vs brick with a square marker, Kalas green vs purple); the words carry the meaning anyway. Avatar slot: a stable function of the user id (e.g. the last hex digit's parity), so each person keeps one colour on both phones (AC-4.5).

4. Category colours (SPEC §9.7 token names)

Use: the icon colour on its container (cat-<token> on cat-<token>-container), chart segments, Kalas solid tiles (on-cat icon on cat-<token>). Never text in light themes. Container rule: Skärgård 16 % (L) / 22 % (D) of the colour over surface; Kvitto 16 % / 24 %; Kalas 18 % / 24 %.

Baseline values (used unchanged by Kvitto and Kalas, and by Skärgård in dark):

Token Light Dark Skärgård light override
green #2E7D32 #81C784 #2A732E
orange #B84A00 #FFB74D #A84300
brown #795548 #C8B4AC —
yellow #8A6A00 #F2D45C #7D6000
blue #1565C0 #90CAF9 —
teal #00796B #80CBC4 #006F62
purple #7B1FA2 #D1A0DB —
red #C62828 #EF9A9A —
pink #AD1457 #F48FB1 —
grey #5F6B73 #B0BEC5 #58646C
indigo #3949AB #A5AEE0 —
lime #5B6B00 #C5D86D —

Measured: icon vs its container ≥ 3.7:1 (light) and ≥ 4.8:1 (dark) in every direction; colour vs surface ≥ 4.6:1 (light) and ≥ 7.7:1 (dark). These differ from the provisional hex values in SPEC §9.7 (orange, brown, yellow, purple, grey, indigo, lime in light; brown, yellow, purple, indigo, lime in dark): adopting them is a spec change (decisions entry + spec version bump) that the orchestrator makes after the pick (SPEC §13.4 U2).

Per-direction container hex values are listed on each review page (computed, not hand-typed).

5. Chart colours

Token Skärgård L Skärgård D Kvitto L Kvitto D Kalas L Kalas D
chart-cat-1 #1A6476 #8ED0E2 #23408E #B3C3FF #C2462A #FF9F86
chart-cat-2 #A8741A #E8C48A #B4602A #F0A673 #4F7A2B #A9D37F
chart-cat-3 #5B5FA8 #B8BCF4 #2D7A6C #7DCAB8 #8C6200 #F2C14E
chart-cat-4 #4D8559 #9BD3A3 #7B4E9E #CDA8EE #2D63AE #9CC2FF
chart-cat-5 #A0526E #EDA9C1 #7F7225 #D6C66B #8A3F92 #E2A6EA
chart-cat-6 #2F86A0 #5FB6D0 #AE3A5C #F29CB6 #00796F #7FD3C8
chart-cat-7 #7A6A58 #CDB9A1 #4D6A7A #A6BFCD #B0306A #FF9EC3
chart-cat-8 #66737C #AEBDC8 #73552A #DCC39A #5B6670 #B7C3CC
chart-seq-1 #D3ECF3 #1E3A42 #D6DDF2 #2A3352 #FBD8CC #4A2A23
chart-seq-2 #9FD3E2 #245A68 #A9B8E3 #3C4C80 #F4A68E #7A3B2C
chart-seq-3 #62AFC5 #2F7C8F #7890CF #5A70B0 #E3765A #B5563C
chart-seq-4 #2E869E #5EADC3 #4865B1 #8499DC #C24A2E #E8826A
chart-seq-5 #165A6B #A3DDEC #23408E #B3C3FF #8E2A14 #FFB59F
chart-grid #DEE3E6 #303639 #E3DED2 #37342E #EBDACF #3E3233
chart-axis-label #40484C #BFC8CC = on-surface-variant = on-surface-variant #53433F #D8C2BB

Rules: categorical colours are assigned to accounts in created_at order (Vardag 1, Huset 2, Gotland 2026 3, Japan 2027 4, cycling after 8); categories always use their own category colour, so a category looks the same in lists and charts. Sequential ramps are for single-series views (a highlighted bucket, "Min del" totals); seq-1 and seq-2 are backgrounds only (< 3:1). Stacked segments are separated by a 2 dp gap in the surface colour so adjacent similar hues stay distinct.

6. Typography

Direction Typeface(s) Licence Amounts
Skärgård Roboto Flex (variable: wght, wdth, opsz) OFL 1.1 Roboto Flex with tnum; hero uses wdth 84
Kvitto IBM Plex Sans (text), IBM Plex Mono (amounts, captions) OFL 1.1 Plex Mono (tabular by nature)
Kalas Nunito OFL 1.1 Nunito (default figures tabular, verified in renders)

Type scale (sp / line height / weight):

Style Skärgård Kvitto Kalas
display-large 57/64 400 57/64 400 (unused) 57/64 800
display-medium 45/52 400 45/52 400 (unused) 45/52 800
display-small 36/44 400 36/44 400 (unused) 36/44 800
headline-large 32/40 500 30/38 500 32/40 800
headline-medium 28/36 500 26/34 500 28/36 800
headline-small 24/32 500 22/30 500 24/32 800
title-large 22/28 500 20/28 500 22/28 800
title-medium 16/24 560 16/24 500 16/24 700
title-small 14/20 560 14/20 600 14/20 800
body-large 16/24 400 16/24 400 16/24 500
body-medium 14/20 400 14/20 400 14/20 500
body-small 12/16 400 12/16 400 12/16 600
label-large 14/20 560 14/20 500 14/20 800
label-medium 12/16 560 12/16 500 12/16 700
label-small 11/16 560 11/16 500 Mono caps, tracking 0.08 em 11/16 700
amount-hero 60/64 720 wdth 84, decimals and kr at 50 % 44/52 500 Mono 44/52 900
amount-large 32/40 650 wdth 92 28/36 500 Mono 28/36 900
amount-medium 16/24 620 15/22 500 Mono 18/24 800
amount-small 14/20 520 12/16 400 Mono 15/20 800

Font scale: sp follows Android's non-linear scaling (Android 14+, Compose default): text ≥ 24 sp grows less than smaller text, so a 60 sp amount does not double at 200 %. The 200 % frames approximate this. Amounts never ellipsize: they wrap or step down one size.

7. Spacing (dp)

All three use one 4 dp scale: space-1 4, space-2 8, space-3 12, space-4 16, space-5 20, space-6 24, space-8 32, space-10 40, space-12 48, space-16 64 (Kvitto does not use 40 and 64). Screen gutter 16 in all directions.

Measure Skärgård Kvitto Kalas
card padding 20 20 (receipt) 20
home account row ~72 (card row) 60 ~76 (card)
ledger row 72 60 72
settings row 56 56 56
keypad key 64 52 52
gap between grouped items 2 rule (1 dp dashed) 12

8. Shapes (corner radius, dp)

M3 shape tokens: extraSmall 4, small 8, medium 12, large 16, largeIncreased 20, extraLarge 28, extraLargeIncreased 32, extraExtraLarge 48, full.

Component Skärgård Kvitto Kalas
buttons, chips full small 8 full
text fields large 16 (outlined) extraSmall 4 large 16 (filled, no indicator)
cards extraLarge 28 none (receipt zig-zag edge, 10 dp teeth) 24–28
balance hero extraLargeIncreased 32 top corners 8, zig-zag bottom extraLarge 28
grouped/segmented lists outer 20, inner 4 none, rules outer 24, inner 8
category icon container medium 12 extraSmall 4 MaterialShapes Cookie4Sided (fallback 30 %)
avatars MaterialShapes Cookie9/12 (fallback circle) full MaterialShapes Sunny (fallback circle)
FAB largeIncreased 20 medium 12 largeIncreased 20
dialogs extraLarge 28 large 16 extraLarge 28
keypad keys full, morph to 16 on press small 8 full

9. Elevation and motion

Skärgård Kvitto Kalas
elevation model tonal (surface-container levels); 2 dp shadow on menus, 3 dp on FAB almost none: rules and tones; shadow only on menus, FAB, dialogs tonal + soft warm shadow on light cards (0 1 2, 0 2 8, 10 % brown); no shadows in dark
motion scheme MotionScheme.expressive() springs: spatial fast 0.6/800, default 0.8/380, slow 0.8/200; effects 1.0/3800, 1600, 800 standard easing curves: receipt print reveal 350 ms emphasizedDecelerate, number roll 250 ms per digit, "Kvitt" stamp 200 ms, push shared-axis X 300 ms, tabs fade-through 200 ms MotionScheme.expressive(); seesaw re-tilt spring 0.55/300; amount count-up 400 ms emphasizedDecelerate; bunting drop with 40 ms stagger when settled
stable fallback MotionScheme.standard() / tween 200–500 ms emphasized (already stable) MotionScheme.standard()
reduced motion everything except fades snaps everything becomes a 150 ms crossfade springs critically damped

10. Icons

Material Symbols (Apache 2.0), as a bundled variable font or vector drawables generated from it.

Skärgård Kvitto Kalas
style Rounded Sharp Rounded
weight / grade / optical size 400 / 0 / 24 300 / 0 / 20–24 500–600 / 0 / 24
fill 1 for selected nav item and category icons, else 0 0, except the selected nav item 1 for category icons and selected nav item

Category icons: the 30 tokens of SPEC §9.7. Other icons used by all directions: home, bar_chart, settings, add, close, arrow_back, more_vert, edit, delete, swap_horiz, payments, cloud_upload / cloud_off / cloud_done, sync, warning, info, history, event_repeat, devices, person_add, content_paste, share, content_copy, drag_indicator, archive / unarchive, backspace, system_update, phonelink_erase.