Files
flafleurandgithub-actions[bot] 8e165c0eb6 [AI] Implement standard sizes on Button, Text and Input components (#9002)
* [AI] Add standard size system to Button, Text and Input components

* [AI] Migrate modals, settings, rules, schedules and sidebar text to standard sizes

* [AI] Migrate mobile, budget, manager, banksync and transactions text to standard sizes

* [AI] Migrate reports, formula and news text to standard sizes

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #9002

* Revert "Update VRT screenshots"

This reverts commit 35c947ef54.

* [AI] Fix line-height rendering as px strings in size tokens

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #9002

* [AI] Tighten bank sync mobile row gap so larger labels fit on one line

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #9002

* [AI] Restore amount display size to preserve underline spacing

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #9002

* [AI] Pass caller-provided size through SingleAutocomplete render input

* [AI] Omit forced line-height on medium-sized controls to match the default look

* [AI] Document standard component sizes in DESIGN.md

* [AI] Adopt sidebar spacing tokens where values match exactly

* [AI] Scope the mobile touch-target rule to touch-primary control sizes

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-10-05 16:41:38 +00:00

12 KiB
Raw Permalink Blame History

name, description, colors, typography, rounded, spacing, components
name description colors typography rounded spacing components
Actual Budget Local-first personal finance, built around envelope budgeting
actual-purple actual-purple-hover navy-ink navy-slate navy-mist navy-frost page-text surface-white positive-green negative-red link-blue warning-gold
#8719e0 #a368fc #102a43 #627d98 #e8ecf0 #f7fafc #272630 #ffffff #147d64 #e12d39 #1980d4 #b88115
display headline title body label
fontFamily fontSize fontWeight
Inter Variable, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif 30px 600
fontFamily fontSize fontWeight letterSpacing
Inter Variable, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif 20px 700 0.5px
fontFamily fontSize fontWeight
Inter Variable, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif 15px 500
fontFamily fontSize fontWeight fontFeature
Inter Variable, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif 16px 400 tnum, ss01, ss04
fontFamily fontSize fontWeight
Inter Variable, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif 13px 400
sm md
4px 6px
xs sm md lg
5px 10px 16px 20px
button-primary button-primary-hover button-normal input
backgroundColor textColor rounded padding
{colors.actual-purple} {colors.surface-white} {rounded.sm} 5px 10px
backgroundColor textColor
{colors.actual-purple-hover} {colors.surface-white}
backgroundColor textColor rounded padding
{colors.surface-white} {colors.navy-ink} {rounded.sm} 5px 10px
backgroundColor textColor rounded padding
{colors.surface-white} {colors.page-text} {rounded.sm} 5px

Design System: Actual Budget

1. Overview

Creative North Star: "The Home Office"

Actual feels like a tidy personal desk: familiar, unpretentious, everything within reach. It is a tool people open weekly for years to reconcile accounts and move envelope money around, so the interface optimizes for routine, not first impressions. Density is moderate-to-high (this is a table-driven app), feedback is instant, and decoration is close to zero. The financial numbers are the interface; everything else exists to keep them legible and trustworthy.

The system explicitly rejects fintech-startup gloss (gradient heroes, glassmorphism, crypto-dashboard neon) and corporate banking UI (navy-and-gold enterprise-portal density). It is calm, trustworthy, and practical, and it must render identically well in three themes: light, dark, and midnight.

Key Characteristics:

  • Table-first layouts with tabular numerals everywhere money appears
  • One accent (Actual Purple) used sparingly for primary actions and selection
  • Semantic color tokens only; components never hardcode hex values
  • Utilitarian, compact components built for daily repetition
  • Flat-first surfaces; shadows reserved for transient overlays

2. Colors

A calm navy-neutral base with one confident purple accent and strict semantic roles for money.

All hex values in this file (frontmatter included) are the light-theme palette mapping. The dark and midnight themes remap the same semantic roles to different palette values, so never use these hexes directly in components — route every color through the theme.* semantic tokens (see The Semantic Token Rule below).

Primary

  • Actual Purple (#8719e0): The single brand accent. Primary buttons, selected rows and borders, active navigation, mobile header. Hover lightens to Lifted Purple (#a368fc).

Neutral

  • Navy Ink (#102a43): Sidebar background, darkest text. The app's anchor dark.
  • Page Ink (#272630): Default body text on light surfaces.
  • Navy Slate (#627d98): Secondary and subdued text, table headers.
  • Navy Mist (#e8ecf0): Page background, table borders, dividers.
  • Navy Frost (#f7fafc): Hover rows, raised header rows.
  • Surface White (#ffffff): Tables, cards, menus, modals.

Tertiary (semantic money and status colors)

  • Positive Green (#147d64): Positive amounts and funded budgets.
  • Negative Red (#e12d39): Negative amounts, overspending, failures.
  • Link Blue (#1980d4): Links and informational highlights.
  • Warning Gold (#b88115): Underfunded templates, pending states.

Named Rules

The Semantic Token Rule. Components never use raw palette values or hex codes. Every color goes through the theme.* semantic layer (--color-* custom properties) so all three themes (light, dark, midnight) stay correct. A hardcoded hex in a component is a bug.

The One Accent Rule. Actual Purple appears on well under 10% of any screen: primary action, current selection, active nav. It never decorates.

The Never-Color-Alone Rule. Positive/negative money state is conveyed by sign and context as well as color; green/red are reinforcement, never the only signal.

3. Typography

Body Font: Inter Variable (with system-ui fallback stack) Label/Mono behavior: Same family; financial figures switch on tabular OpenType features

Character: One workhorse sans at compact sizes. No display serif, no font pairing games: hierarchy comes from weight and size, and the typographic star is the number column.

Hierarchy

  • Display (600, 30px): Page-level headings and large balances. Rare.
  • Headline (700, 20px, 0.5px letter-spacing): Section titles.
  • Title (500, 15px): Emphasized in-table and card text.
  • Body (400, 16px): Default text.
  • Label (400, 13px): Table meta, menus, dense secondary text; 12px and 10px steps exist for the tightest spots.

Standard Component Sizes

Button, Text and Input accept a size prop: small | medium | large | extra-large (the ComponentSize vocabulary in packages/component-library/src/tokens.ts). Omitting the prop renders exactly as before — fully backward compatible. Sizes are responsive: they step up one notch on mobile/narrow for readability and touch targets, and collapse to the compact desktop scale from 512px/730px up. Breakpoint groups mirror the useResponsive view modes: narrow <512, small 512–729, medium 730–1099, wide ≥1100.

Text values (fontSize / lineHeight, px):

Size narrow small medium wide
small 12 / 16 12 / 16 12 / 16 12 / 16
medium 13 / 18 13 / 18 13 / 18 13 / 18
large 16 / 22 15 / 20 15 / 20 15 / 20
extra-large 17 / 24 17 / 24 16 / 22 16 / 22

Control values for Button/Input (paddingY / paddingX / min-height, px):

Size narrow small medium wide
small 3 / 8 / 24 3 / 8 / 24 3 / 8 / 24 3 / 8 / 24
medium 5 / 10 / — 5 / 10 / — 5 / 10 / — 5 / 10 / —
large 8 / 12 / 36 6 / 12 / 32 6 / 12 / 32 6 / 12 / 32
extra-large 10 / 14 / 40 8 / 12 / 36 8 / 12 / 36 8 / 12 / 36

size="medium" reproduces today's default control look exactly (5px/10px padding, 13px text, no min-height) and, on controls, inherits line-height like the default; the other sizes apply their scale line-height. Text always applies its size's line-height, while the omitted prop forces no line-height at all. extra-large narrow hits the 40px mobile touch target. The touch-target guarantee applies to touch-primary controls: at narrow, use large or extra-large for controls the user taps; small stays the compact 24px desktop-density choice at every breakpoint and is not meant for touch-primary controls.

Named Rules

The Tabular Number Rule. Every standalone financial figure renders with font-feature-settings: "tnum", "ss01", "ss04" (via FinancialText or styles.tnum) so digits align in columns and disambiguate. A proportional-figure money column is a bug.

4. Elevation

Flat-first with ambient shadows. Structure comes from 1px borders (Navy Mist) and background shifts (White on Mist, Frost on hover), not depth. Shadows exist only to lift transient surfaces above the page: menus, tooltips, popovers, modals. Persistent surfaces like tables and cards sit flat or carry the faint card shadow at most.

Shadow Vocabulary

  • Card (box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)): Resting cards and small raised widgets.
  • Ambient (box-shadow: 0 2px 4px 0 rgba(0,0,0,0.1)): Focused inputs, subtle lift.
  • Large (box-shadow: 0 15px 30px 0 rgba(0,0,0,0.11), 0 5px 15px 0 rgba(0,0,0,0.08)): Tooltips, popovers, floating panels.

Named Rules

The Transient-Only Rule. If a surface stays on screen, it gets a border. If it appears on interaction and disappears, it may cast a shadow.

5. Components

Utilitarian and quick: compact paddings, instant state feedback, built for daily repetition. All values below are the light theme; every color routes through the semantic token layer.

Buttons

  • Shape: Gently rounded (4px radius), compact padding (5px 10px)
  • Primary: Actual Purple background, white text; hover lifts to Lifted Purple with a soft shadow transition (box-shadow .25s)
  • Normal: White background, Navy Ink text, 1px navy border
  • Bare: Transparent, 5px padding; background tint on hover/press. The workhorse for in-table actions

Inputs / Fields

  • Style: White background, 1px border, 4px radius, 5px padding
  • Focus: Border switches to the selected accent; big inputs drop the border and take the ambient shadow instead
  • Big variant: 10px padding for mobile and prominent forms (40px minimum touch height on mobile)

Cards / Containers

  • Corner Style: 6px radius on table containers (top corners), 4px elsewhere
  • Background: Surface White on Navy Mist page background
  • Shadow Strategy: Card shadow at most; structure via 1px Navy Mist border
  • Internal Padding: 16-20px

Navigation

  • Sidebar: Navy Ink background, light navy text; hover darkens the row, selection marked with a purple accent and purple text. Status states (pending/positive/failed) tint the item background gold/green/red
  • Mobile: Purple header, white nav bar, purple selected item

Pills / Chips

  • Style: Editor pills: tinted background, 4px radius, 3px 5px padding. Used for rule conditions and inline tokens

Signature Component: The Money Table

The core surface of the app. White rows on 1px Navy Mist borders, Frost hover, purple-bordered selection, sticky header with Slate 13px text, amounts right-aligned in tabular figures colored by the semantic money tokens. Alternate-row striping is theme-controlled, never hardcoded.

6. Do's and Don'ts

Do:

  • Do route every color through theme.* semantic tokens so light, dark, and midnight themes all work. Test all three.
  • Do wrap standalone financial numbers in FinancialText or apply styles.tnum.
  • Do keep components compact and quick: 4px radii, 5-10px paddings, instant hover/press states.
  • Do reuse the existing component library (@actual-app/components) before writing new UI.
  • Do keep Actual Purple scarce: primary action and selection only.
  • Do respect the breakpoints: 512px (small), 730px (medium), 1100px (wide); mobile touch targets are at least 40px tall.

Don't:

  • Don't use fintech-startup gloss: gradient heroes, glassmorphism, neon accents, crypto-dashboard styling (PRODUCT.md anti-reference).
  • Don't use corporate banking UI patterns: navy-and-gold, enterprise-portal density, legalese energy (PRODUCT.md anti-reference).
  • Don't hardcode hex values or raw --palette-* colors in components; the semantic layer is the only entry point.
  • Don't rely on color alone for positive/negative amounts.
  • Don't put shadows on persistent surfaces; shadows are for transient overlays only.
  • Don't use border-left/border-right thicker than 1px as a colored accent stripe.
  • Don't animate layout properties; transitions are for color, opacity, and shadow (like the button's box-shadow .25s).