Theming

Every color the React controls draw comes from a --listens-* CSS custom property. The kit ships a light and a dark value for each one and switches between them on its own, so you only set the tokens you want to change.

Change a color

Set the token on :root in your global stylesheet. The kit's own styles sit in a cascade layer, @layer listens, and plain CSS always beats a layer, so your value wins without !important.

index.css

:root {
  /* Labels and content while the mic is open. */
  --listens-accent: #7c3aed;
  /* Focus, highlighted options, and checkbox, radio and slider fills. */
  --listens-interactive: #7c3aed;
}

A value set this way applies in light and dark mode alike. To give dark mode its own value, see different colors in light and dark.

Light and dark mode

The controls, the listening bar and the popup follow the device's light or dark setting automatically. To switch them yourself, set data-listens-theme to "dark" or "light" on the <html> element, and remove it to follow the device again. The controls only read the attribute there, so it has no effect on an inner element.

document.documentElement.setAttribute('data-listens-theme', 'dark');

The React setup has a dark mode switch built from a ListensToggle, so people can tap it or say "dark mode".

Different colors in light and dark

Dark mode turns on in two ways: the device is set to dark, or your app sets data-listens-theme="dark". Cover both with the same selectors the kit uses:

index.css

:root {
  --listens-accent: #7c3aed;
}

/* The device is dark, and the app hasn't forced light. */
@media (prefers-color-scheme: dark) {
  :root:not([data-listens-theme='light']) {
    --listens-accent: #a78bfa;
  }
}

/* The app forced dark. */
:root[data-listens-theme='dark'] {
  --listens-accent: #a78bfa;
}

Theme one part of a page

Custom properties are inherited, so a token set on any element reaches every control inside it. Give a section a class and set its tokens there:

index.css

.checkout {
  --listens-accent: #0a7c42;
  --listens-interactive: #0a7c42;
  --listens-success: #0a7c42;
}

Checkout.tsx

export function Checkout() {
  return (
    <section className="checkout">
      {/* …every control in here uses the green */}
    </section>
  );
}

This also keeps a section light on a dark page, or dark on a light one: set the whole palette on it, using the values in the token reference.

Style one control

Tokens restyle every control at once. To change just one, give it a className, which every control takes and merges onto its root element. Your class's rules beat the kit's layer, and because tokens are inherited, a class can also retheme that one control:

index.css

.danger-toggle {
  --listens-success: #e53935;
}
<ListensToggle
  className="danger-toggle"
  label="Delete my data"
  command="delete my data"
/>

Most controls also take classNames, which puts your classes on individual parts, such as a text field's label or input. Each control's page lists its classNames parts, CSS classes and the tokens it reads under Styling hooks, for example the label button's.

The listening bar and popup

The bar and the popup have their own stylesheet, with frosted light and dark backgrounds, so the tokens don't change them. They follow the device and data-listens-theme like the controls do. Their colors are props instead: waveColor on both, and backgroundColor and textColor on the popup. See the listening bar and popup page.

Token reference

The web kits share these tokens, so the same CSS restyles React and Angular.

TokenLightDark
Listening signal
--listens-accent

Labels and content while the mic is open. The one color every control shares.

#ff0000#ff0000
Text
--listens-text

Primary control text.

#222222#ededed
--listens-text-secondary

Values and secondary readouts.

#444444#c2c2c2
--listens-label

Field labels.

#666666#a6a6a6
--listens-text-muted

Idle toggle button text and “no results” messages.

#888888#8f8f8f
--listens-text-subtle

Icons, empty states, delete buttons and disabled text.

#999999#7d7d7d
--listens-text-strong

The strongest emphasis, such as the selected ring.

#000000#ffffff
--listens-on-accent

Text and icons on an accent fill.

#ffffff#ffffff
--listens-placeholder

Input placeholders.

#9a9a9a#7d7d7d
Surfaces and borders
--listens-surface

Inputs, menus, list items and cards.

#ffffff#2a2a2a
--listens-border

Default borders and input outlines.

#d0d0d0#4a4a4a
--listens-border-subtle

Faint dividers.

#e0e0e0#3a3a3a
--listens-button-border

The soft edge around buttons.

rgba(0, 0, 0, 0.12)rgba(255, 255, 255, 0.13)
--listens-button-face

Button fill.

#efefef#6b6b6b
--listens-on-button

Text on a button fill.

#222222#ffffff
--listens-menu-hairline

The edge of the combobox menu.

rgba(0, 0, 0, 0.05)rgba(255, 255, 255, 0.12)
--listens-ring

The selection ring’s shadow.

rgba(0, 0, 0, 0.2)rgba(255, 255, 255, 0.28)
Interactive
--listens-interactive

Focus, highlighted options, and checkbox, radio and slider fills.

#007aff#0a84ff
--listens-success

The toggle’s track when on.

#4caf50#46c463
--listens-track

The toggle’s track when off.

#dddddd#555555
--listens-toggle-thumb

The toggle’s thumb.

#ffffff#f0f0f0
--listens-segment-on

A checked toggle button’s fill.

#64b5f6#0a84ff
--listens-segment-on-border

A checked standalone toggle button’s border.

#2196f3#409cff
--listens-danger

Destructive hovers, such as delete.

#e53935#ff6b6b

Was this page helpful?