Draft · v0.1
Action hierarchy
How buttons share a screen. One action leads; the rest support it. This page turns the unwritten calls we already make into rules the whole team, and the AI, can follow.
One primary action per screen. Everything else is secondary or a text link. Yellow is what you do next; green is what is already true. They never compete on the same screen. In dark modes, brand/action resolves to lime automatically.
The types
Section titled “The types”The DS Button has three types. One Primary (the yellow CTA) per screen; everything else supports it. Pick the lowest-emphasis type that still reads as the right importance.
| Type | Example | Color token | Flutter (M3) |
|---|---|---|---|
| Primary | Save | brand/action. Yellow → lime | FilledButton |
| Secondary | Not now | button/secondary, neutral tonal. No longer green | FilledButton.tonal ¹ |
| Tertiary | Skip | button/tertiary = surface, drawn by stroke/strong | OutlinedButton |
Always radius/full (pill), Inter Bold 16/24, no icon by default. In Light all three
labels are black (onPrimary, onSecondary, onTertiary); in Carbon and Navy they lighten
with the mode. White on green only ever reached 3.24:1, which is part of why green left the
buttons in the first place.
Only one button is ever coloured, and it is always yellow
Section titled “Only one button is ever coloured, and it is always yellow”Yellow is what you do next. Green is what is already true. Since August 2026 green is not a button at all.
If a screen has a commit, that commit is Primary yellow, whether it is “Go to Stellar Plan” or “Save”. Anything that accompanies it drops to Secondary (neutral tonal) or to a text link if it is an escape. Two coloured pills on one screen means the hierarchy was never decided.
Count the yellow on any screen and the answer must be 0 or 1. Zero is a perfectly legal screen: a list of settings or a navigation screen has no commit and needs no CTA.
Yellow is rationed by position, not by importance. It is not a reward you save for the big moments. If you ration it by importance, ordinary screens lose their primary, degrade into a wall of neutral buttons, and nobody can tell where the commit is.
Two actions that belong together stack: the yellow on top, the escape as a centered text link underneath. Never two solid pills side by side.
Why green is not a button
Section titled “Why green is not a button”Do
- One yellow, or none. Continue alone, with Not now or a text link beside it.
- Green for what is already true. Selected borders, feature checks, the active nav destination, positive amounts, chevrons.
- Green for what leads somewhere. An actionable line icon, a link to real content.
Don’t
- A green button. Not as a confirm, not as a “continue”, not as the second action beside a yellow one.
- Two coloured pills on one screen. If two actions belong together they stack, and only the top one is coloured.
- Saving yellow for the big moments. An ordinary screen with a commit still gets its yellow.
The reason is a tense, and it is worth carrying in your head because it decides every future case on its own.
Green already means “already true” in nine different places: a selected plan, a feature check, the active nav destination, an accent word, a positive amount, a chevron, a spinner, progress, a link. A button means “about to become true”. Those are opposite tenses, and asking one colour to hold both is how green emptied out in the legacy app the first time.
So green did not lose a job here. It kept all nine and gave up the one that contradicted them.
Green is not being rationed for scarcity. It is on nearly every screen in the product already, doing work no button could add to. Full rationale in ADR-013.
Primary vs. secondary
Section titled “Primary vs. secondary”A secondary button never appears alone. It exists to support a primary. If a screen has only one action, that action is primary, full stop. When two actions sit together, the affirmative one is primary and the supporting one drops to secondary or text.
Use secondary when
- It sits beside a primary action (Cancel next to Save).
- The action is reversible or non-committal.
- You need a second action visible but clearly lower.
Don’t use secondary when
- It’s the only action. Promote it to primary.
- To fit a second “important” action. Rank them instead.
- For navigation. Use a text link.
Two buttons together
Section titled “Two buttons together”Never place two high-emphasis buttons side by side. The eye can’t tell which one leads. Pair one primary with one secondary (or text). On the 360×667 floor, if two actions don’t fit on one row, stack them: primary on top.
Dialog actions
Section titled “Dialog actions”Dialogs take at most two actions, both text buttons. Cancel sits left, confirm right
(confirm is always last). When stacked on a narrow screen, confirm goes on top. A
destructive confirm keeps the affirmative slot but takes its color from
feedback/error. Don’t invent a new token.
Tokens this guideline relies on
Section titled “Tokens this guideline relies on”The parity contract. The same tokens Kevin consumes in Flutter. Values resolve per mode.