Theming

Every color the Angular components 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, src/styles.css. 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.

src/styles.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 components, 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 components only read the attribute there, so it has no effect on an inner element.

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

The Angular setup has a dark mode switch built from a <listens-toggle>, 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:

src/styles.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 component inside it, including through Angular's style scoping. Give a section a class and set its tokens there, in styles.css or in that component's own styles:

checkout.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-checkout',
  template: `
    <section class="checkout">
      <!-- …every component in here uses the green -->
    </section>
  `,
  styles: `
    .checkout {
      --listens-accent: #0a7c42;
      --listens-interactive: #0a7c42;
      --listens-success: #0a7c42;
    }
  `,
})
export class Checkout {}

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 component

Tokens restyle every component at once. To change just one, give it a class. Angular components have no className input; the ordinary class attribute does the same job, and Angular keeps the kit's own classes beside yours. Because tokens are inherited, a class can retheme that one component:

src/styles.css

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

To restyle a component's parts, target the kit's CSS classes, which plain CSS also overrides without a fight. Each component's page lists its classes, state attributes and tokens under Styling hooks, for example the label button's. Those parts belong to the kit's components, so put rules for them in styles.css, where Angular's scoping doesn't apply.

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 components do. Their colors are inputs 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 Angular and React.

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?