Develop
A circular play / pause control. The button’s outline acts as the visible ring; drop a <div class="tng-media-button-progress"> inside to overlay a 360° progress arc on top.
<button class="tng-media-button" aria-label="Play"> <i class="tng-icon icon-player" aria-hidden="true"></i></button>Elements
Section titled “Elements”Progress ring
Section titled “Progress ring”The progress ring carries role="progressbar" plus aria-valuemin / aria-valuemax / aria-valuenow for screen readers, and the --tng-media-button-progress custom property (a number between 0 and 1) drives the visual fill. Keep aria-valuenow (0–100) and the custom property (0–1) updated together so visuals and announcements stay in sync.
<button class="tng-media-button" aria-label="Play"> <div class="tng-media-button-progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" style="--tng-media-button-progress: 0" ></div> <i class="tng-icon icon-player" aria-hidden="true"></i></button><button class="tng-media-button" aria-label="Pause"> <div class="tng-media-button-progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="42" style="--tng-media-button-progress: 0.42" ></div> <i class="tng-icon icon-ui-pause" aria-hidden="true"></i></button><button class="tng-media-button" aria-label="Replay"> <div class="tng-media-button-progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="100" style="--tng-media-button-progress: 1" ></div> <i class="tng-icon icon-player" aria-hidden="true"></i></button>The default size is lg (64 × 64). Use is-sm for the compact 40 × 40 variant — typically secondary controls in a player toolbar.
<button class="tng-media-button is-sm" aria-label="Play"> <i class="tng-icon icon-player" aria-hidden="true"></i></button><button class="tng-media-button is-lg" aria-label="Play"> <i class="tng-icon icon-player" aria-hidden="true"></i></button>States
Section titled “States”Disabled is expressed via the native disabled attribute. Hover, active and focus states are driven by the browser and styled by the design system — no extra classes needed.
<button class="tng-media-button" aria-label="Play"> <i class="tng-icon icon-player" aria-hidden="true"></i></button><button class="tng-media-button" disabled aria-label="Play"> <i class="tng-icon icon-player" aria-hidden="true"></i></button>Recipes
Section titled “Recipes”Video player
Section titled “Video player”Wires the media button to a <video> element. The toggle flips between play and pause icons, the aria-label and aria-pressed track the playback state, and --tng-media-button-progress is updated from a requestAnimationFrame loop scoped to playback so the ring traces playback time.
Press play to see the progress ring trace playback time.
The same wiring works for any source — <audio>, custom playback engines, HLS streams. The contract is “set the number on the progress element”; everything else is decoupled.