Colour
Semantic colour roles for text, surfaces, borders, actions and feedback, and the palette behind them.
Build with the semantic roles. Each one has a meaning and a value for each theme, and every text and surface pair the roles are designed for meets WCAG AA contrast. Colour is authored in OKLCH.
The Tailwind column gives each colour's utility with bg-; the same name works with text-,
border- and the other colour utilities. Roles without a utility of their own are used through the
variable.
Text
| Role | Light | Dark | CSS variable | Tailwind |
|---|---|---|---|---|
| primary | oklch(0.16 0.001 60) | oklch(0.958 0.003 60) | --qx-color-text-primary | — |
| secondary | oklch(0.4 0.002 60) | oklch(0.857 0.003 60) | --qx-color-text-secondary | — |
| tertiary | oklch(0.49 0.003 60) | oklch(0.72 0.003 60) | --qx-color-text-tertiary | — |
| placeholder | oklch(0.49 0.003 60) | oklch(0.72 0.003 60) | --qx-color-text-placeholder | — |
| disabled | oklch(0.72 0.003 60) | oklch(0.49 0.003 60) | --qx-color-text-disabled | — |
| inverse | oklch(1 0 0) | oklch(0.16 0.001 60) | --qx-color-text-inverse | — |
| brand | oklch(0.53 0.165 38) | oklch(0.77 0.156 54.793) | --qx-color-text-brand | bg-brand |
| link | oklch(0.53 0.165 38) | oklch(0.77 0.156 54.793) | --qx-color-text-link | bg-link |
| link-hover | oklch(0.47 0.145 36) | oklch(0.842 0.103 57.312) | --qx-color-text-link-hover | bg-link-hover |
| success | oklch(0.522 0.118 159.971) | oklch(0.77 0.135 157.802) | --qx-color-text-success | bg-success-text |
| warning | oklch(0.522 0.109 77.44) | oklch(0.77 0.14 85.394) | --qx-color-text-warning | bg-warning-text |
| danger | oklch(0.522 0.189 21.633) | oklch(0.77 0.136 19.102) | --qx-color-text-danger | bg-destructive-text |
| info | oklch(0.522 0.138 247.265) | oklch(0.77 0.128 242.204) | --qx-color-text-info | bg-info-text |
| on-brand | oklch(1 0 0) | oklch(1 0 0) | --qx-color-text-on-brand | — |
| on-subtle | oklch(0.16 0.001 60) | oklch(0.958 0.003 60) | --qx-color-text-on-subtle | — |
| on-feedback | oklch(1 0 0) | oklch(0.11 0 0) | --qx-color-text-on-feedback | — |
| on-feedback-strong | oklch(1 0 0) | oklch(1 0 0) | --qx-color-text-on-feedback-strong | bg-on-feedback-strong |
| on-warning-strong | oklch(0.16 0.001 60) | oklch(0.16 0.001 60) | --qx-color-text-on-warning-strong | bg-on-warning-strong |
Surface
| Role | Light | Dark | CSS variable | Tailwind |
|---|---|---|---|---|
| canvas | oklch(0.985 0.002 60) | oklch(0.16 0.001 60) | --qx-color-surface-canvas | bg-canvas |
| default | oklch(1 0 0) | oklch(0.185 0.001 60) | --qx-color-surface-default | bg-surface |
| elevated | oklch(1 0 0) | oklch(0.21 0.001 60) | --qx-color-surface-elevated | bg-surface-elevated |
| overlay | oklch(1 0 0) | oklch(0.235 0.001 60) | --qx-color-surface-overlay | bg-surface-overlay |
| sunken | oklch(0.958 0.003 60) | oklch(0.135 0.001 60) | --qx-color-surface-sunken | bg-surface-sunken |
| subtle | oklch(0.974 0.0025 60) | oklch(0.21 0.001 60) | --qx-color-surface-subtle | bg-surface-subtle |
| interactive | oklch(0.958 0.003 60) | oklch(0.268 0.001 60) | --qx-color-surface-interactive | bg-surface-interactive |
| interactive-hover | oklch(0.937 0.003 60) | oklch(0.3 0.0015 60) | --qx-color-surface-interactive-hover | bg-surface-interactive-hover |
| interactive-active | oklch(0.912 0.003 60) | oklch(0.34 0.0015 60) | --qx-color-surface-interactive-active | bg-surface-interactive-active |
| brand-subtle | oklch(0.952 0.03 61.16) | color-mix(in oklab, oklch(1 0 0) 7%, transparent) | --qx-color-surface-brand-subtle | bg-brand-subtle |
| brand-subtle-hover | oklch(0.93 0.044 60.391) | color-mix(in oklab, oklch(1 0 0) 10%, transparent) | --qx-color-surface-brand-subtle-hover | bg-brand-subtle-hover |
| brand-subtle-active | oklch(0.906 0.06 59.551) | color-mix(in oklab, oklch(1 0 0) 13%, transparent) | --qx-color-surface-brand-subtle-active | bg-brand-subtle-active |
| rail | oklch(0.974 0.0025 60) | oklch(0.135 0.001 60) | --qx-color-surface-rail | — |
| inverse | oklch(0.21 0.001 60) | oklch(0.958 0.003 60) | --qx-color-surface-inverse | — |
Border
| Role | Light | Dark | CSS variable | Tailwind |
|---|---|---|---|---|
| default | oklch(0.912 0.003 60) | oklch(0.268 0.001 60) | --qx-color-border-default | — |
| subtle | oklch(0.937 0.003 60) | oklch(0.235 0.001 60) | --qx-color-border-subtle | bg-border-subtle |
| strong | oklch(0.857 0.003 60) | oklch(0.34 0.0015 60) | --qx-color-border-strong | bg-border-strong |
| control | oklch(0.61 0.003 60) | oklch(0.61 0.003 60) | --qx-color-border-control | bg-control |
| control-hover | oklch(0.49 0.003 60) | oklch(0.72 0.003 60) | --qx-color-border-control-hover | bg-control-hover |
| focused | oklch(0.585 0.1835 40) | oklch(0.77 0.156 54.793) | --qx-color-border-focused | — |
| hover | oklch(0.49 0.003 60) | oklch(0.72 0.003 60) | --qx-color-border-hover | — |
| brand | oklch(0.585 0.1835 40) | oklch(0.77 0.156 54.793) | --qx-color-border-brand | bg-border-brand |
| danger | oklch(0.6 0.209 20.837) | oklch(0.635 0.215 20.48) | --qx-color-border-danger | — |
| success | oklch(0.842 0.105 157.172) | oklch(0.6 0.137 159.289) | --qx-color-border-success | — |
| warning | oklch(0.842 0.109 87.703) | oklch(0.6 0.124 79.942) | --qx-color-border-warning | — |
| info | oklch(0.842 0.087 240.735) | oklch(0.6 0.153 245.673) | --qx-color-border-info | — |
Action
| Role | Light | Dark | CSS variable | Tailwind |
|---|---|---|---|---|
| primary | oklch(0.585 0.1835 40) | oklch(0.585 0.1835 40) | --qx-color-action-primary | — |
| primary-hover | color-mix(in oklab, oklch(0.585 0.1835 40), oklch(0.53 0.165 38)) | color-mix(in oklab, oklch(0.585 0.1835 40), oklch(0.53 0.165 38)) | --qx-color-action-primary-hover | — |
| primary-active | oklch(0.53 0.165 38) | oklch(0.53 0.165 38) | --qx-color-action-primary-active | — |
Feedback
| Role | Light | Dark | CSS variable | Tailwind |
|---|---|---|---|---|
| success | oklch(0.522 0.118 159.971) | oklch(0.77 0.135 157.802) | --qx-color-feedback-success | — |
| warning | oklch(0.522 0.109 77.44) | oklch(0.77 0.14 85.394) | --qx-color-feedback-warning | — |
| error | oklch(0.522 0.189 21.633) | oklch(0.77 0.136 19.102) | --qx-color-feedback-error | — |
| info | oklch(0.522 0.138 247.265) | oklch(0.77 0.128 242.204) | --qx-color-feedback-info | — |
| success-subtle | oklch(0.952 0.036 156.21) | color-mix(in oklab, oklch(0.68 0.15 158.589) 15%, transparent) | --qx-color-feedback-success-subtle | bg-success-subtle |
| warning-subtle | oklch(0.952 0.037 91.23) | color-mix(in oklab, oklch(0.705 0.144 83.309) 12%, transparent) | --qx-color-feedback-warning-subtle | bg-warning-subtle |
| error-subtle | oklch(0.952 0.023 17.245) | color-mix(in oklab, oklch(0.635 0.215 20.48) 15%, transparent) | --qx-color-feedback-error-subtle | bg-destructive-subtle |
| info-subtle | oklch(0.952 0.025 238.49) | color-mix(in oklab, oklch(0.64 0.16 244.857) 15%, transparent) | --qx-color-feedback-info-subtle | bg-info-subtle |
| success-strong | oklch(0.522 0.118 159.971) | oklch(0.522 0.118 159.971) | --qx-color-feedback-success-strong | bg-success-strong |
| warning-strong | oklch(0.77 0.14 85.394) | oklch(0.77 0.14 85.394) | --qx-color-feedback-warning-strong | bg-warning-strong |
| error-strong | oklch(0.522 0.189 21.633) | oklch(0.522 0.189 21.633) | --qx-color-feedback-error-strong | bg-destructive-strong |
| info-strong | oklch(0.522 0.138 247.265) | oklch(0.522 0.138 247.265) | --qx-color-feedback-info-strong | bg-info-strong |
Focus, selection and overlay
| Role | Light | Dark | CSS variable | Tailwind |
|---|---|---|---|---|
| ring | oklch(0.585 0.1835 40) | oklch(0.77 0.156 54.793) | --qx-color-focus-ring | — |
| Role | Light | Dark | CSS variable | Tailwind |
|---|---|---|---|---|
| background | color-mix(in oklab, oklch(0.686 0.1855 47.1629) 20%, transparent) | color-mix(in oklab, oklch(0.686 0.1855 47.1629) 32%, transparent) | --qx-color-selection-background | — |
| Role | Light | Dark | CSS variable | Tailwind |
|---|---|---|---|---|
| scrim | color-mix(in oklab, oklch(0.11 0 0) 40%, transparent) | color-mix(in oklab, oklch(0.11 0 0) 62%, transparent) | --qx-color-overlay-scrim | — |
Palette
The primitive ramps the roles are built from. They're published in @qeetrix/ui/tokens.css for
design tooling, but not in styles.css: build with the roles above. Hover a step for its variable
and value.
qeet
50
100
150
200
300
400
500
550
600
700
800
900
950
graphite
0
25
50
100
150
200
300
400
450
500
600
700
750
800
825
875
900
925
950
975
1000
neutral
0
50
100
200
300
400
500
600
700
800
850
900
950
1000
danger
50
100
200
300
400
500
600
700
800
900
950
success
50
100
200
300
400
500
600
700
800
900
950
warning
50
100
200
300
400
500
600
700
800
900
950
info
50
100
200
300
400
500
600
700
800
900
950