Design system 0.6.0

Foundations

Tokens

Every value the app is allowed to use. Use the semantic names (bg, surface, text, muted, accent-text…) in CSS as var(--name); never the ramps, never a hex. Swatches show the dark value on the left and the light value on the right when they differ.

Jump to: Color · Type · Space · Radius · Shadow · Sizes · Motion · Layers and opacity

Color

Surfaces and text

bg{neutral-900} · {warm-150}

Page canvas. Text on it: text, muted.

surface{neutral-800} · {warm-50}

Cards, panels, inputs. Text on it: text (AA), muted (4.5:1).

surface-2{neutral-750} · {warm-100}

A second surface: hovered rows, nested wells.

line{neutral-700} · {warm-200}

Dividers and card edges. Decorative.

line-strong{neutral-500} · {warm-400}

Edges that identify a control: inputs, checks. 3:1 on every surface.

faint{neutral-500} · {warm-400}

Non-text marks: grips, pins, empty-state glyphs. 3:1; never text.

text{neutral-50} · {warm-900}

Primary text on bg, surface and surface-2.

muted{neutral-300} · {warm-600}

Secondary text. 4.5:1.

brand-ink{neutral-50} · {brand-navy}

The logo letters.

Accent (lime by default — the user picks one of 18)

accent{lime}

The user accent. Settings writes var(--<swatch>) on <html>; lime by default. Default swatch: lime. Derived per theme: accent-text, accent-ring, on-accent.

accent-text#c4e85f · #5a6c28

The accent as text. Lightness raised to at least 0.72 (OKLCH), which holds 4.5:1 for any color.

accent-ring#c4e85f · #748b36

Focus ring: 2 px outline, 2 px offset. 3:1 for any color.

on-accent#191919

Text on an accent fill: --ink on every palette color; off-white on a dark one.

accent-soft#c4e85f29

Accent fills: selected and arranged states.

accent-halo#c4e85f38

The 3 px focus halo on inputs. Decoration only; --accent-ring carries the 3:1.

accent-dash#889e4b · #cee28d

The dashed frame of arrange mode.

Brand

brand{brand-blue}

Top bar tint, front door, favicon, PDF stamp. Never a button, never a link, never the accent.

brand-blue#0080ff

The check in the final HeyGoal logo.

brand-navy#080044

The letters of the final HeyGoal logo on light.

topbar-tint#121f2c · #d7e3eb

10% brand mixed into bg: the glass top bar tint.

topbar-bg#121f2c59 · #d7e3eb59

Over a --glass-blur backdrop.

Status

good{green-500} · {green-600}

good-text{green-400} · #166e3f

70% of the base with black: the closest mix that passes 4.5:1 on light surfaces and on its own --good-soft tint.

good-soft#3ecf7e24 · #1f9d5a24

Tinted background. Paid, done, synced.

warning{amber}

warning-text{amber} · #7f5f27

53% of the base with black: the closest mix that passes 4.5:1 on light surfaces and on its own --warning-soft tint.

warning-soft#efb44a24

Tinted background. Paused, offline, upsell.

critical{coral}

critical-text#eb7a5e · #9c4732

89% coral with white: passes 4.5:1 on dark surfaces and on --critical-soft (raw coral reads 4.1:1 on its tint).

critical-soft#e96a4a24

Tinted background. Error, overdue, danger.

info{sky}

info-text{sky} · #596a75

49% of the base with black: the closest mix that passes 4.5:1 on light surfaces and on its own --info-soft tint.

info-soft#b6d8ee24

Tinted background. Neutral notices.

live{good} · {good}

The live dot: running timer, synced.

live-text{good-text} · {good-text}

Billing zones and priority

zone-invoices{amber}

Billing zone. Fixed; never a status.

zone-project{periwinkle}

Billing zone. Fixed; never a status.

zone-expenses{peach}

Billing zone. Fixed; never a status.

zone-payments{mint}

Billing zone. Fixed; never a status.

zone-neutral{stone}

Billing zone. Fixed; never a status.

priority-high{text} · {text}

Priority is an order, not a status: four strengths of one neutral, always with the word.

priority-medium{muted} · {muted}

priority-low{faint} · {faint}

priority-backburner{faint} · {faint}

Drawn as a hollow ring.

Palette — accent, project and client colors (ink text on all)

sage#c4d2bf

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

mint#b3dcc9

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

teal#93c9c0

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

sky#b6d8ee

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

blue#a8c3e4

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

periwinkle#b3bbeb

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

lilac#bdb2d6

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

blush#e7cbde

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

rose#eaaebb

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

peach#f2c4a5

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

clay#d8a88c

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

taupe#c6bbab

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

stone#bdb9b0

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

olive#cdd09b

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

butter#eee0a2

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

lime#c4e85f

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

amber#efb44a

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

coral#e96a4a

Palette swatch: an accent choice in Settings and a project/client color. Always dark ink text on top. Name is stored in saved data — never rename.

bone#e9e7df

Clock card only. Not in PALETTE.

On a pastel fill or an image

on-accent#191919

Text on an accent fill: --ink on every palette color; off-white on a dark one.

on-color-hover#00000014

A hover tint on a pastel fill: icon buttons on cards.

on-color-fill#0000001a

A resting control on a pastel fill: the edit tools, the status select (.09 in 1.19.0).

on-color-fill-hover#0000002e

The same control on hover.

on-color-edge#00000024

A hairline edge on a color: the color pill, the client pill (.18 in 1.19.0).

on-color-track#0000001f

A meter track on a pastel card.

on-color-line#0000001f

A divider on a pastel card: rows, the calendar grid, the At a glance list (.1 and .12 in 1.19.0).

on-color-edge-strong#00000059

The edge of a control on a pastel card, such as a task check: 3:1 on every swatch.

on-color-surface#ffffff57

A surface inside a pastel card: At a glance cards, shortcuts, calendar chips (.28 to .4 in 1.19.0).

on-color-surface-strong#ffffff8c

An input on a pastel card, in edit mode.

critical-on-color#8a1f10

Overdue text on a pastel card.

on-ink{neutral-50}

Text on an ink fill: a primary button or the today mark on a pastel card.

image-backdrop#111111

Behind a photo: the lightbox and image thumbnails.

image-scrim#0000008c

Under tools that sit on a photo.

on-image#ffffff

Icons on --image-scrim.

Neutral ramp · dark theme

neutral-50#f2f2f0

Dark-theme neutral ramp step. Use the semantic tokens (bg, surface, text…) in UI, never the ramp directly.

neutral-100#d4d4d1

Dark-theme neutral ramp step. Use the semantic tokens (bg, surface, text…) in UI, never the ramp directly.

neutral-200#b7b7b3

Dark-theme neutral ramp step. Use the semantic tokens (bg, surface, text…) in UI, never the ramp directly.

neutral-300#9a9a96

Dark-theme neutral ramp step. Use the semantic tokens (bg, surface, text…) in UI, never the ramp directly.

neutral-400#848480

Dark-theme neutral ramp step. Use the semantic tokens (bg, surface, text…) in UI, never the ramp directly.

neutral-500#6e6e6b

Dark-theme neutral ramp step. Use the semantic tokens (bg, surface, text…) in UI, never the ramp directly.

neutral-600#4d4d4b

Dark-theme neutral ramp step. Use the semantic tokens (bg, surface, text…) in UI, never the ramp directly.

neutral-700#2e2e2e

Dark-theme neutral ramp step. Use the semantic tokens (bg, surface, text…) in UI, never the ramp directly.

neutral-750#232323

Dark-theme neutral ramp step. Use the semantic tokens (bg, surface, text…) in UI, never the ramp directly.

neutral-800#1c1c1c

Dark-theme neutral ramp step. Use the semantic tokens (bg, surface, text…) in UI, never the ramp directly.

neutral-900#141414

Dark theme canvas (#141414 anchor).

Warm ramp · light theme

warm-50#fbfbf8

Light-theme warm neutral ramp step. Use the semantic tokens in UI, never the ramp directly.

warm-100#f2f1ec

Light-theme warm neutral ramp step. Use the semantic tokens in UI, never the ramp directly.

warm-150#efeee9

Light-theme warm neutral ramp step. Use the semantic tokens in UI, never the ramp directly.

warm-200#dcdad2

Light-theme warm neutral ramp step. Use the semantic tokens in UI, never the ramp directly.

warm-300#b2b0a8

Light-theme warm neutral ramp step. Use the semantic tokens in UI, never the ramp directly.

warm-400#898780

Light-theme warm neutral ramp step. Use the semantic tokens in UI, never the ramp directly.

warm-500#7a7872

Light-theme warm neutral ramp step. Use the semantic tokens in UI, never the ramp directly.

warm-600#6b6a64

Light-theme warm neutral ramp step. Use the semantic tokens in UI, never the ramp directly.

warm-700#4f4e4a

Light-theme warm neutral ramp step. Use the semantic tokens in UI, never the ramp directly.

warm-800#343331

Light-theme warm neutral ramp step. Use the semantic tokens in UI, never the ramp directly.

warm-900#1b1b1a

Light-theme warm neutral ramp step. Use the semantic tokens in UI, never the ramp directly.

Everything else

green-400#5fe09a

Status green ramp: feeds good, good-text and live.

green-500#3ecf7e

Status green ramp: feeds good, good-text and live.

green-600#1f9d5a

Status green ramp: feeds good, good-text and live.

ink#191919

Text and icons on any palette fill, both themes.

ink-soft#000000b5

Secondary text on palette fills. 0.71 alpha: the lowest that passes 4.5:1 on all 19 swatches (1.19.0: .56).

paper#ffffff

Paper white: invoice sheet, report, calendar print.

paper-ink#161616

Text on paper.

paper-muted#6b6b66

Labels on paper.

paper-line#e4e3dc

Rules on paper.

paper-line-strong#c9c8c2

Grid lines on the printed calendar, where --paper-line is too light to see.

paper-soft#f2f1ec

Tinted cells on paper.

paper-good#2f8f5b

Paid stamp.

paper-critical#b02c16

Overdue on paper.

scrim#00000080

Behind dialogs.

glass-line{line} · {line}

glass-bg#1c1c1c99 · #fbfbf899

Floating glass (timer). The top bar uses its own brand-tinted --topbar-bg on the same blur and line.

good-soft-hover#3ecf7e38 · #1f9d5a38

The synced account card on hover.

good-edge#3ecf7e66 · #1f9d5a66

The edge of a good-state surface: the synced account card.

warning-edge#efb44a66

The edge of a warning-state surface: the offline account card.

critical-edge#e96a4a66

The edge of a critical-state surface, and the danger button (45% in 1.19.0).

scrim-drawer#00000073

muted-2{faint} · {faint}

Deprecated. Text uses move to --muted; marks and edges to --faint / --line-strong.

logo-ink{brand-ink} · {brand-ink}

1.19.0 alias of brand-ink.

logo-blue{brand}

1.19.0 alias of brand.

Type

Bricolage Grotesque for display, Inter for everything else. Nothing goes below 11 px. Kickers are the only uppercase.

Display

Good morning, Gabrieldisplay · 50px / 1.04 · 800 · tracking -0.035em — Page titles and the Home greeting. Bricolage 800, −.035em. Fluid clamp(32px, 4.4vw, 50px) in the app. CSS: font: var(--type-display)
Projectstitle · 24px / 1.1 · 800 · tracking -0.025em — Card and dialog titles. CSS: font: var(--type-title)
Due soonheading · 18px / 1.3 · 700 · tracking -0.01em — Section heads inside a page or card. CSS: font: var(--type-heading)
US$12,480number · 46px / 1.05 · 800 · tracking -0.04em — The big number on Home tiles: always tabular, sizes to its card 28–46 px (`text-number-fit`). CSS: font: var(--type-number)

Interface

Saved in this browser only, until you sign in.body · 15px / 1.5 · 400 · tracking 0 — Running text and list rows. CSS: font: var(--type-body)
Add a clientbutton · 14px / 1.3 · 600 · tracking 0 — Buttons and segment labels. CSS: font: var(--type-button)
Client namelabel · 14px / 1.3 · 500 · tracking 0 — Field labels, menu items, pills. CSS: font: var(--type-label)
Last synced 3:42 PMnote · 13px / 1.45 · 400 · tracking 0 — Secondary lines, help-tip text, meta. CSS: font: var(--type-note)
day 4 of 12small · 12px / 1.4 · 400 · tracking 0 — Captions and dense meta. CSS: font: var(--type-small)
AT A GLANCEkicker · 11px / 1.3 · 800 · tracking 0.14em — Kickers above a section — the only uppercase in the UI. Uppercase, +.14em. CSS: font: var(--type-kicker)
3 of 5 donemicro · 11px / 1.3 · 600 · tracking 0 — Counts and the tiniest labels. Nothing goes below 11 px. CSS: font: var(--type-micro)

Space

A 4 px base. Lay out with gap, not margins.

--space-4
--space-8
--space-12
--space-16
--space-20
--space-24
--space-32
--space-40
--space-56
TokenValueUse
--space-44pxIcon-to-label gap, tight inline gaps.
--space-88pxGap inside a control group, chip padding.
--space-1212pxGap between form fields in an add row.
--space-1616pxCard padding (small), list row padding.
--space-2020pxPanel padding.
--space-2424pxCard padding, gap between Home cards.
--space-3232pxGap between page sections.
--space-4040pxLarge section breaks.
--space-5656pxMaximum page padding (page-pad-max).
--page-pad56pxPage side padding: clamp(18px, 4vw, 56px) in the app; 56 at desktop.

Radius

Six steps, picked by role: chip 8 · control 10 · inner 12 · card 16 · floating 24 · round.

radius-chip
radius-control
radius-inner
radius-card
radius-floating
radius-round
TokenValueUse
--radius-chip8pxChips, filter pills, checkboxes, calendar chips and bars.
--radius-control10pxButtons, inputs, icon buttons, menu rows and the nav highlight.
--radius-inner12pxA surface nested in a card or dialog: overview cards, stats, quick-access cards, previews, thumbnails; and tooltips.
--radius-card16pxPanels, tiles, project cards, lists and other top-level cards.
--radius-floating24pxDialogs, popovers, the toast, the account menu, the floating timer.
--radius-round999pxAvatars and status pills.
--radius-88pxRadius scale step. Use the role tokens (radius-chip … radius-round) in UI.
--radius-1010pxRadius scale step. Use the role tokens (radius-chip … radius-round) in UI.
--radius-1212pxRadius scale step. Use the role tokens (radius-chip … radius-round) in UI.
--radius-1616pxRadius scale step. Use the role tokens (radius-chip … radius-round) in UI.
--radius-2424pxRadius scale step. Use the role tokens (radius-chip … radius-round) in UI.
--radius-full999pxRadius scale step. Use the role tokens (radius-chip … radius-round) in UI.
--r16px1.19.0 alias of radius-card (was 18). Kept two minor versions.

Shadow

Flat by default. Only things that float cast a shadow.

elevation-0Flat: cards, panels, tiles. Shadows never decorate containers.
elevation-1Raised: popover, toast, floating timer (timer also glass).
elevation-2Floating: dialogs, always with `scrim` behind.
shadow-dragA tile or menu item held while dragging.
shadow-drawerThe phone drawer.
shadow-paperThe invoice sheet on screen: paper over the app. Print drops it.

Sizes

TokenValueUse
--control-height44pxEvery add-form box: input, select, date, button, color pill.
--control-height-compact36pxCompact buttons in dense rows.
--icon-button-size40px40 px icon buttons; reach 44 px touch area under pointer: coarse.
--topbar-height56pxThe glass top bar.
--topbar-line1.25pxBottom divider, drawn as an inset shadow so the fraction survives 125–200% display scale.
--sidebar-width248pxFull sidebar.
--sidebar-width-rail76pxCollapsed icon rail.
--nav-indicator-width4.5px
--main-max-width1240pxMain content column max width.
--page-pad-min18pxPage padding floor at phone width.
--page-pad-max56pxPage padding ceiling.
--breakpoint-phone860pxReference only: @media cannot read custom properties. Phone layout at ≤ 860 px.
--icon-size-sm16pxIn text and pills.
--icon-size20pxMenu and controls.
--icon-size-lg24pxPhone bar.
--logo-height-bar24pxLogo on the desktop top bar.
--logo-height-phone20pxLogo on the phone bar.
--logo-height-door52pxLogo on the front door (sign-in).
--favicon-size16pxFavicon.
--avatar-size36pxThe account card and lists.
--avatar-size-sm32pxThe phone bar.
--avatar-size-xl112pxThe Account page.
--border-width1pxEvery hairline (line).
--border-width-strong1.5pxTask check, help bubble, client pill.
--glass-blur16pxBackdrop blur on the top bar and floating timer.
--scrim-blur2pxBackdrop blur behind dialogs.
--text-number-min28pxThe smallest a big number gets in a narrow card.

Motion

The signature curve is cubic-bezier(0,0,0,1). Every entrance has an exit. Under Reduced, movement stills and fades stay.

Easing

TokenValueUse
--ease-outcubic-bezier(0,0,0,1)The HeyGoal curve: hovers, entrances, presses. Default for everything.
--ease-incubic-bezier(.4,0,1,1)Exits only, over duration-fast.
--ease-softcubic-bezier(.2,.7,.2,1)The Home intro and the front door.
--ease-fadeeasePlain fades.

Durations

TokenValueUse
--duration-fast0.16sColor, opacity and press (1.19.0 --t-fast).
--duration-in0.26sThe way in: hover, enter, page-out (1.19.0 --t).
--duration-out0.4sThe way back: hover out, toast (1.19.0 --t-slow).
--duration-page0.36sPage blocks rising in.
--duration-wipe0.42sMenu highlight wipe and indicator fade.
--duration-crossfade-out0.12sReduced motion: old page fades.
--duration-crossfade-in0.18sReduced motion: new page and menu highlight fade.
--duration-drawer0.25sPhone drawer and scrim.
--duration-collapse0.2sSidebar and timer-dock column change.
--duration-theme0.3sTheme switch color fade; Billing zone flash.
--duration-page-out0.26sThe old page fading out on a page change.
--duration-intro0.55sThe Home intro: each tile rising in.
--duration-door0.9sThe front door: the wordmark scaling and fading in.
--duration-door-rise0.65sThe front door: the wordmark moving up for the sign-in card.
--duration-door-card0.5sThe front door: the sign-in card coming in.
--duration-pulse1.6sOne cycle of the live dot pulse.
--duration-ring2.4sOne cycle of the synced dot ring.
--duration-sync-pulse1.1sThe account card dot while it syncs (1.19.0: ease-in-out, now --ease-fade).
--duration-flash0.3sA Billing zone flashing when its jump pill is used.
--delay-door-card0.15sThe sign-in card waits this long after the wordmark starts to move.

Layers and opacity

TokenValueUse
--z-raised2A lifted card over its siblings.
--z-local5Local stacking inside a component.
--z-tip20The ? help tip.
--z-shell45Top bar and sidebar.
--z-floating50Floating timer.
--z-gate55Front door (sign-in).
--z-scrim55Dialog scrim.
--z-drawer60Phone drawer.
--z-toast60Toast.
--z-popover70Popovers and the account menu.
TokenValueUse
--opacity-disabled0.5A control that cannot be used right now, such as a button while a PDF builds.
--opacity-hover0.8The logo on hover.
--opacity-placeholder0.28The empty slot a Home card leaves while it is dragged.
--glass-saturate1.4Backdrop saturate on the floating timer glass.

Files: tokens.json (this page's data) · tokens.w3c.json (the W3C Design Tokens source of truth) · heygoal-tokens.css (the generated :root block) · heygoal-tokens.js · contrast-report.md.

HeyGoal design system 0.6.0 · generated from tokens.json and the component CSS in design-system\HeyGoal design system · works offline, open any page in a browser.