Colors & themes

Colors named by their role, so every screen works in light, dark and high contrast.

On this page

Usage

import { Theme, Text, useTheme } from '@envsemble/envui';

function ThemeLabel() {
  const { theme, contrast } = useTheme();
  return (
    <Text>
      Current theme: {theme}, {contrast} contrast
    </Text>
  );
}

<Theme theme="dark" contrast="high">
  <ThemeLabel />
</Theme>;
NameTakes
Theme themeRequired: light or dark; scopes the tokens and provides the theme to React
Theme contrasthigh; standard, even when the system asks for more; or system, the default, which follows prefers-contrast: more; inherited from the enclosing Theme
Theme scalesystem, comfortable or compact, the app's scale; inherited from the enclosing Theme
useTheme(){ theme, contrast, scale } of the nearest Theme, also across envUI's portals
ThemePreferenceProviderStores the preference, follows the system and other windows, and themes the document root; see setup
useThemePreference()A ThemePreferenceValue: preference (light, dark or system), the resolved theme, setPreference and toggleTheme
ThemeToggleAn IconButton that switches between light and dark

The words of the figures

The Design tokens page of the Docs lists every value in each theme, and this guide ends with the palette, which shows each role's value in the theme you are reading in and lets you try another.

  • Page: --env-color-bg-page, the document's background, behind everything: below the panes and cards on it.
  • Recessed surface: --env-color-bg-recessed, a well on the page, background="recessed", such as the stage of a preview: below the panes, and in dark a shade deeper than the page too; in light, where nothing deeper than the page keeps edges at 3:1, between the page and the panes.
  • Surface: --env-color-bg-default: Surface's background="default", panes, the navigation and sheets, a step lighter than the page.
  • Raised surface: --env-color-bg-raised: tables, docked panels and background="raised", a step above the panes with the filled card's fill: white in light.
  • Filled card: --env-color-bg-muted: a group inside a surface, a Card's fill, background="muted", list rows and tab rails, a step above the surface: white in light.
  • Text: --env-color-fg-default, Text's default, for headings and the main words.
  • Supporting text: --env-color-fg-muted: emphasis="muted" on Text, details, captions, hints and icons.
  • Primary: --env-color-bg-primary-emphasis, the main action's fill; --env-color-fg-primary and fg-link in text, such as links and what is selected.
  • Edges: --env-color-border-default, the outline of fields and outline buttons, which have no fill.
  • Selected: --env-color-bg-selected with --env-color-fg-on-selected.

Status tones

Status icons, short status text and badges share these tokens, at least 4.5:1 on the page, surfaces and rows in both themes, and 7:1 at high contrast.

TokenMeaning
--env-color-fg-mutedNeutral: no particular state, such as archived, and most actions
--env-color-fg-primaryPrimary: what is current or highlighted
--env-color-fg-accentAccent: what stands out, in purple, such as a featured item
--env-color-bg-info-strongInfo, as a strong fill: something to know, neither good nor bad
--env-color-fg-successSuccess: healthy, ready or saved
--env-color-fg-warningWarning: needs attention soon
--env-color-fg-dangerDanger: failed, or an action that destroys something
--env-color-fg-doneDone: completed work
--env-color-bg-{tone}-mutedThe tone's tint behind badges and alerts
--env-color-bg-{tone}-emphasisA solid fill in the tone, with fg-on-emphasis
--env-color-fg-{tone}-on-strongA toast's tone icon on its dark fill: success, info or danger
.work-status[data-status='blocked'] {
  color: var(--env-color-fg-warning);
}

Composition

Semantic tokens

Tokens are named --env-color-{bg|fg|border}-{role}[-{emphasis}][-{state}], emphasis weakest first: subtle, muted, none, emphasis and strong. Every fg-on-X pairs with a bg-X, every state token has its resting token, and the contrast gate measures every pair a component paints, in all four themes.

  • Backgrounds: bg-page and bg-recessed, a well, below the surfaces; bg-default, and bg-muted and bg-raised a step above it, the surfaces; bg-popup, the fill of dialogs, menus and popovers, frosted or solid, white in light and in dark a step lighter than the surfaces they open over; bg-field, bg-selected; bg-backdrop, the backdrop behind dialogs.
  • Fills: bg-neutral-muted, a translucent layer of the text color under secondary buttons, chips, switch tracks and skeletons; bg-neutral-subtle, the state layer of controls without a fill, such as ghost and outline buttons; emphasis and strong solid fills.
  • Text: fg-default, fg-muted for supporting text and icons, fg-disabled for the label and value of a disabled control, fg-control, fg-link, fg-on-selected, and one per tone.
  • Borders: border-default, the only boundary of a control, at least 3:1; border-muted for the hairlines between a list's items, quote bars and other decorative edges; border-focus; border-media, the inner edge of images.

The colors come from an internal palette of eleven hues, and the pastel hues of avatars, in grades from 0 to 100, where the grade difference alone sets the contrast: 50 grades apart give at least 4.5:1. The light theme takes a nearly neutral gray, the dark theme a slightly blue-tinted one.

States and contrast

  • Hover and pressed are tokens of their own, other grades of the same hue, so labels keep their contrast in every state. A component given colors of its own through its color properties draws its states as state layers instead: the content color over the container at --env-state-hover-opacity, --env-state-focus-opacity and --env-state-pressed-opacity.
  • Selection stays apart from every other item, at rest and under the pointer, and carries a second cue: its label color, a check or a bar. Tree and table rows hover with a layer of their own, --env-color-bg-row-hover, quieter than the selection, so the selected row always reads strongest.
  • High contrast moves text to 7:1 and boundaries, indicators and focus rings to 4.5:1. A nested Theme and envUI's popups take the contrast and theme of where they open.
  • Elevation 0โ€“3 is an edge, shown only where a surface is solid: popups float at 2, dialogs, sheets and the command palette at 3, and at high contrast a solid popup takes level 3's, the strongest. Elsewhere a popup or a dialog separates by its fill and a soft shadow, a sheet by its fill, and a modal by its backdrop too.
  • Small popups are frosted: menus, lists, popovers, pickers, hover cards, tooltips and the command palette let a little of what is behind them through, blurred, with a soft shadow and no edge; a tooltip's strong fill covers a little less and its shadow is smaller. Dialogs take the popups' fill and shadow, solid over their backdrop. At high contrast and with reduced transparency all are solid, with their edge.
  • Shadows: a popup's, which dialogs share, a tooltip's and an avatar's faint one, which parts the avatars of a group, are envUI's only shadows.
  • Sheets keep the navigation's fill, so navigation that opens in one looks as it does at the window's edge, and have no edge but at high contrast.
  • Hairlines separate a list's items, never regions: Markdown rules, table rows and accordion items take a hairline across their container's full width, never inset from its edges. Regions, such as a top bar, a footer, a sticky header, a tab bar and two panes, separate by space and background instead; controls keep their edges. A popup or a dialog has none: a popup's groups part by space and a quiet label, a dialog's heading, content and actions by space.
  • Forced colors take system colors, such as Highlight and GrayText, for every state a fill carried.

Guidelines

  • Choose the role for what an element is, not the color it should have: fg-muted for any supporting text, border-muted for the line between a list's items. Separate regions by space or a background, not a line.
  • Use one role in both themes; the themes give it its grade.
  • Disabled controls take 0.48 opacity, which WCAG exempts from contrast.
  • Wrap the application's own portal content in <Theme {...useTheme()}>, so it takes the theme and contrast of where it opens.

Customize

Each component has public color properties, such as --env-button-container, for colors of its own on one instance. A nested <Theme> whose style sets the semantic tokens for each theme, such as --env-color-bg-primary-emphasis with its hover and pressed tokens, gives an area a color scheme of its own, such as a brand's. Customize and extend describes both.

TypeScript declarations provide the complete public API.

Words in code

WordsIn code
A quieter surfacebackground="page" on a Surface or Card, so it parts from the page by space rather than a fill
Success or warningtone on Badge, Alert, Toast, Button and the components that take one: Badge takes neutral, primary, accent, success, warning, danger and done; Alert info, success, warning and danger; Toast neutral, info, success and danger; Button neutral, accent and danger. In your own CSS, --env-color-fg-{tone} and their tints
Its own colorThe component's color properties, such as --env-button-container; most components have them, listed on each one's page in the Docs under Color properties; see Customize and extend
A dark areaA nested <Theme theme="dark">, or light on a dark page
High contrastcontrast="high" on Theme, or system, the default, which follows the reader's system

Try the palette

Each swatch shows a token's value in the theme you are reading in. Press one to pick another color: the whole catalogue follows, in this theme only, until you reload.

Page & surfaces

Page background--env-color-bg-page
Recessed surfaces ยท preview stages--env-color-bg-recessed
Pane surfaces ยท navigation & sheets--env-color-bg-default
Popup surfaces ยท menus & dialogs--env-color-bg-popup
Filled surfaces ยท cards & tab rails--env-color-bg-muted
Alternate surfaces--env-color-bg-raised

Text & focus

Main text--env-color-fg-default
Supporting text--env-color-fg-muted
Captions--env-color-fg-muted
Disabled labels--env-color-fg-muted
Text buttons & inline links--env-color-fg-link
Focus rings--env-color-border-focus
General borders--env-color-border-muted

Cards

Card action strip--env-color-bg-default

Rows

Row background--env-color-bg-list-item
Contrast row background--env-color-bg-raised
Row text--env-color-fg-default
Row details--env-color-fg-muted

Buttons

Primary button background--env-color-bg-primary-emphasis
Primary button label--env-color-fg-on-emphasis
Secondary button background--env-color-bg-neutral-muted
Secondary button label--env-color-fg-control
Outlined button background--env-color-bg-raised
Outlined button label--env-color-fg-primary
Outlined button border--env-color-border-default
Accent button background--env-color-bg-accent-strong
Important button label--env-color-fg-on-strong
Destructive button background--env-color-bg-danger-strong
Destructive button label--env-color-fg-on-strong

Navigation

Navigation label--env-color-fg-control
Navigation icon--env-color-fg-muted
Selected navigation background--env-color-bg-selected
Selected navigation label--env-color-fg-on-selected

Direction links

Direction link background--env-color-bg-raised
Direction link title--env-color-fg-default
Direction link caption--env-color-fg-muted
Direction link icon--env-color-fg-primary
Direction link border--env-color-border-muted

Text fields

Field background--env-color-bg-field
Field text--env-color-fg-default
Field label--env-color-fg-muted
Field hint--env-color-fg-muted
Field placeholder--env-color-fg-muted
Field border--env-color-border-default
Field active border--env-color-border-primary-emphasis
Field validation error--env-color-fg-danger

Select options

Select option background--env-color-bg-popup
Select option label--env-color-fg-control
Selected option background--env-color-bg-selected
Selected option label--env-color-fg-on-selected

Radio

Radio selection--env-color-bg-primary-emphasis
Radio row background--env-color-bg-muted
Radio label--env-color-fg-default
Radio details--env-color-fg-muted

Checkboxes

Checked checkbox background--env-color-bg-primary-emphasis
Checkbox mark--env-color-fg-on-emphasis
Unchecked checkbox border--env-color-fg-muted
Checkbox label--env-color-fg-default

Switches

Switch off background--env-color-bg-neutral-muted
Switch on background--env-color-bg-primary-emphasis
Switch off thumb--env-color-fg-control
Switch on thumb--env-color-fg-on-emphasis
Switch label--env-color-fg-default

Feedback

Info chip background--env-color-bg-neutral-muted
Info chip label--env-color-fg-primary
Disclosure text--env-color-fg-muted
Toast background--env-color-bg-neutral-strong
Success toast icon--env-color-fg-success-on-strong
Info toast icon--env-color-fg-info-on-strong
Error toast icon--env-color-fg-danger-on-strong
Toast text--env-color-fg-on-strong
Dialog backdrop--env-color-bg-backdrop

Content & loading

Table, Markdown and menu hairlines--env-color-border-muted
Loading placeholders--env-color-bg-neutral-muted