Theming
The list is colour-agnostic by default, like the rest of the family. Every colour derives from currentColor, so it fits a light page and a dark one with no setup, and the “on” states — the selected chip, the chosen Loops / One-shots button, the pressed Loop toggle, the playing row’s button — are inverted: the text colour as the fill, the page background as the ink. White on a dark page, black on a light one.
Theme it with custom properties on .waveform-sounds (or any ancestor). The stylesheet is @arraypress/waveform-sounds/styles.css — the framework wrappers never inject it.
.waveform-sounds { --ws-surface: #0a0a0a; /* your page background */ --ws-accent: #22d3ee; /* opt into a brand colour… */ --ws-on-accent: #04141a; /* …and the ink that sits on it */ --ws-radius: 6px; --ws-control-radius: 6px;}Custom properties
Section titled “Custom properties”| Property | Default | What it styles |
|---|---|---|
--ws-surface |
detected by the runtime | The page background behind the list — the ink on inverted fills, and the dropdowns’ background. See below. |
--ws-accent |
currentColor |
Fills and borders of the “on” states, focus rings, the focused search field and open menu button, and (through --ws-progress-color) the played part of a row. |
--ws-on-accent |
var(--ws-surface), else the inverse of the text colour |
The ink on an accent fill. |
--ws-muted |
currentColor at 62% |
Secondary text: the type, BPM, key and length columns, the count, placeholders, icons. |
--ws-border |
currentColor at 12% |
Row dividers and control borders. |
--ws-hover |
currentColor at 5% |
Hover backgrounds. |
--ws-current |
--ws-accent at 7% |
The current row’s background. |
--ws-field |
currentColor at 5% |
Control backgrounds (search, menus, the play buttons). |
--ws-wave-color |
currentColor at 30% |
The row waveforms’ bars, unless waveformColor is set. |
--ws-progress-color |
var(--ws-accent) |
The played part of a row waveform, unless progressColor is set. |
--ws-radius |
10px |
Dropdowns, the docked strip player. |
--ws-strip-position |
static |
The strip layout’s docked player. sticky keeps it at the bottom of the viewport while a long list scrolls (0.3.1+; it was always sticky before). |
--ws-control-radius |
999px |
Search, menu buttons, chips, the Loop toggle, Show more. |
--ws-row-height |
3.25rem |
Minimum row height. |
--ws-wave-height |
28px |
Row waveform height. |
--ws-mono |
ui-monospace, SFMono-Regular, Menlo, Consolas, monospace |
The BPM, key and length columns, and the counts on chips and menu options. |
--ws-popover-bg |
var(--ws-surface, Canvas) |
The dropdowns’ background. |
--ws-strip-bg |
Canvas |
The docked player’s background in the strip layout. |
The canvas can’t read CSS, so the runtime resolves --ws-wave-color and --ws-progress-color to real colours itself, and re-reads them when the page’s theme flips (a class, data-theme, data-color-scheme or style change on <html> or <body>, or a prefers-color-scheme change).
The page surface
Section titled “The page surface”--ws-surface is the colour behind the list. The inverted states use it as their ink, and the dropdowns use it as their background. The runtime measures it — the first (near-)opaque background at or above the list — and re-measures when the theme flips, unless you set it yourself.
Set it for a server-rendered list. The markup paints before any script runs, so until the runtime measures the page the first paint can only use what the CSS says (without it, the inverted ink falls back to the inverse of the text colour, which is close but not your exact background):
.waveform-sounds { --ws-surface: var(--color-bg); }Setting it in a theme that switches between light and dark? Point it at the same variable your page background uses, and it follows.
CSS classes
Section titled “CSS classes”| Class | Element |
|---|---|
.waveform-sounds |
The container. .waveform-sounds--inline / .waveform-sounds--strip for the layout. It’s an inline-size container, so the narrow row layout follows the list’s width, not the window’s. |
.ws-toolbar |
Everything above the rows. .ws-search / .ws-search-input the search box; .ws-controls the row of menus and Loop; .ws-meta the chips and count. |
.ws-menu / .ws-menu-btn / .ws-menu-pop / .ws-menu-list / .ws-menu-option |
A dropdown: the wrapper, its button, the popup, the listbox and an option (.is-active while highlighted, aria-selected when chosen). .ws-menu-search is its search field, .ws-menu-count an option’s count, .ws-menu-none the no-matches line. |
.ws-menu--bpm / .ws-bpm-pop |
The BPM menu and its panel; .ws-bpm-readout / .ws-bpm-clear its range and reset. |
.ws-range / .ws-range-input |
The two-handle range: the track (::before), the filled span (::after, .is-active once narrowed), and each handle (a native range input). |
.ws-loop |
The Loop toggle (aria-pressed). |
.ws-seg / .ws-seg-btn |
The All / Loops / One-shots control and its buttons (aria-pressed on the chosen one). |
.ws-types / .ws-chip |
The type chips (aria-pressed on the selected one); .ws-chip-count the count inside one. |
.ws-count |
The count line. |
.ws-list |
The <ul> of rows, with .ws-list--inline / .ws-list--strip. |
.ws-row |
A row. .is-current for the playing or paused sound, .is-playing while it plays, .is-error when it failed to load (its title is struck through). |
.ws-play |
A row’s play / pause button. |
.ws-title |
The title cell: .ws-title-text the name, .ws-loop-mark a loop’s icon. |
.ws-cells / .ws-cell |
The columns: .ws-type, .ws-bpm, .ws-key, .ws-duration. |
.ws-wave / .ws-canvas |
The row waveform (role="slider") and its canvas — inline layout only. |
.ws-download |
A row’s download link. |
.ws-empty / .ws-clear |
The no-matches message and its Clear filters button. |
.ws-more |
Show more. |
.ws-engine / .ws-engine--strip |
The engine player’s slot — hidden in inline, the docked player in strip. |
.ws-sr |
Visually hidden text for screen readers. |
The engine is a regular WaveformPlayer, so its own styling applies inside .ws-engine — set its colours through playerOptions.
Responsive
Section titled “Responsive”Below 560px of list width the rows switch to three lines — the title, then Bass · 128 · Fm · 0:08, then the waveform — and on coarse pointers the buttons grow to 44px and the inputs to 16px. See Mobile.