Foundations

Color

Color distinguishes Flatpay's brand and reinforces consistent, restrained surfaces across every product. The neutral palette holds the typographic field; saturated hues earn their place by communicating state, status, or hierarchy.

Documentedby Derek Fidler

Color anatomy

Saturated colors

Saturated colors infuse meaning into an experience, highlight UI, or create associations between similar elements. Nine hue families, each on a 10-step ramp.

Neutral colors

Neutral colors apply to most backgrounds, text, and shapes. They don't typically carry meaning, though they can imply states like disabled.

The same primitive ramp shown on a light surface and a dark surface — what shifts is which step the theme treats as "ground" and which it treats as "type."

Alpha colors

Alpha colors carry varying levels of transparency. They let UI adapt to whatever surface or imagery sits beneath them — scrims over photography, hover overlays on colored panels, soft borders that pick up the surrounding hue.

If you aren't using design tokens, the color palette page has hex codes and RGBa values for every step.

Applying color with tokens

Every token starts with the prefix --color- followed by the property it applies to (background, text, border, icon), then the role and any modifier — emphasis level, interaction state.

css

/* Anatomy */
--color-{property}-{role}[-{emphasis}][-{state}]

/* Examples */
--color-background-danger
--color-background-danger-bold
--color-background-danger-bold-hovered
--color-text-success
--color-border-discovery-subtle
--color-icon-disabled

Reach for tokens, not primitives

Components consume --color-background-success, not --color-green-500. Primitives are the source of truth for the palette, but only semantic tokens cross the boundary into components — so when light/dark themes diverge, components don't need to change.

Color roles

Color roles describe the intention behind a color. Roles apply across background, text, border, and icon — pick the role first, then let the token system pick the right weight for the property.

Primary
Secondary
Warning
Danger

Flatpay has no brand color. Primary actions are charcoal; chroma enters only when a state earns it.

RoleDescription
  • primary

    Standard body copy and the chrome that frames the system — the default text emphasis.

  • secondary

    Supporting information — captions, descriptions, metadata. One step quieter than primary.

  • tertiary

    Placeholder text in inputs and the lowest-priority labels. Used sparingly — it's the quietest text on a surface.

  • disabled

    Inert affordances — disabled buttons, fields the user can't edit. Not meant to be read clearly.

  • inverse

    Text and surfaces that sit on top of bold-emphasis backgrounds.

  • information

    Informative UI — info icons, links, neutral status, and 'in progress' affordances.

  • success

    Positive outcomes — completed payouts, demo-ready prototypes, healthy services.

  • warning

    Caution before failure. Pending decisions, near-threshold metrics, delayed batches.

  • danger

    Destructive actions and serious errors. Declined transactions, killed prototypes.

  • discovery

    What's new — beta surfaces, onboarding, lab tags, and content the user hasn't seen before. Blurple lives here, not at the top of the action hierarchy.

  • accent

    Categorical hues without semantic meaning — neutral, pink, blurple, natural, and the alternate accents you'd swap freely on a chart or illustration.

Emphasis levels

Emphasis is a layering property of accent backgrounds — not a modifier you apply to every role. Each accent has three stacked surfaces: subtlest opens a surface, subtler is a card on that canvas, and subtle is an inner highlight on top of subtler. Never open a surface on subtle. Text has no layering — it has its own hierarchy (primary, secondary, tertiary), shown in the roles above.

background-accent-green-subtlest · canvas

background-accent-green-subtler · card on canvas

background-accent-green-subtle · inner highlight

See accent palettes for the full layering rule and worked examples across every accent hue.

Interaction states

Interactive surfaces resolve through three states: default, hover, and active. Pair them with an action level — primary, secondary, or tertiary — and components just request the state they need.

tsx

<button
  className="bg-[var(--background-interactive-primary-default)] hover:bg-[var(--background-interactive-primary-hover)] active:bg-[var(--background-interactive-primary-active)]"
>
  Approve
</button>

--background-disabled and --border-focus live as standalone tokens — they apply across every action level rather than vary by it.

Accessibility

Every text token in the system meets WCAG AA contrast against its intended background — 4.5:1 for body, 3:1 for large text and non-text UI elements. The bold-emphasis tokens are calibrated so white text remains legible on top.

Don't carry meaning in color alone

Pair every status color with an icon, label, or shape. A red dot next to "Killed" communicates twice — once for sighted users, once for everyone else.

Designing in dark mode

Dark mode reuses the same semantic tokens — only the primitive values they map to change. If you're consuming tokens correctly, the only thing that should change in dark mode is the underlying CSS variable. Components don't branch on theme.

Status

Dark-mode token mappings are still being calibrated. Today, components ship with light-only values; the full .dark override lands with the next theme pass.

Page history

4 revisions
  1. Documented
    Derek Fidler@derekfidler

    Roles section restructured around the four canonical examples; Discovery role corrected to map to blurple, not purple.

  2. Documented
    Derek Fidler@derekfidler

    Anatomy + roles redesigned: compact saturated grid, light/dark comparisons, role pills.

  3. Documented
    Derek Fidler@derekfidler

    First documented version. Tokens sourced from the Figma export.

  4. In progress
    Derek Fidler@derekfidler

    Initial draft — palette extracted, semantic mapping outlined.