Call Controls
A meeting bar with microphone, camera, and captions controls. Each one is an independent toggle rather than part of a group, since no combined value ties them together.
The mic and camera treat pressed as off: they turn red and a CSS-drawn slash grows over the icon, so no second icon variant is needed. Captions treat pressed as on and take the accent instead. A live region under the bar announces every change, fed by the pressedchange events bubbling up from the toggles.
Reduced Motion
Your system is set to reduce motion, so this animation will not play for you.
Microphone on
Code
The following example assumes that you have imported the component and set up the theme.
<div class="call-controls">56 collapsed lines
<div class="call-bar"> <sv-toggle class="control muting" aria-label="Mute microphone" data-pressed-status="Microphone muted" data-released-status="Microphone on" title="Mute microphone" > <span class="icon-stack" aria-hidden="true"> <!-- Microphone --> <svg class="icon" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg"> <path d="M480-400q-50 0-85-35t-35-85v-240q0-50 35-85t85-35q50 0 85 35t35 85v240q0 50-35 85t-85 35Zm-40 280v-123q-104-14-172-93t-68-184h80q0 83 58.5 141.5T480-320q83 0 141.5-58.5T680-520h80q0 105-68 184t-172 93v123h-80Z" ></path> </svg> <span class="slash"></span> </span> </sv-toggle>
<sv-toggle class="control muting" aria-label="Turn off camera" data-pressed-status="Camera off" data-released-status="Camera on" title="Turn off camera" > <span class="icon-stack" aria-hidden="true"> <!-- Camera --> <svg class="icon" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg"> <path d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h480q33 0 56.5 23.5T720-720v180l160-160v440L720-420v180q0 33-23.5 56.5T640-160H160Z" ></path> </svg> <span class="slash"></span> </span> </sv-toggle>
<sv-toggle class="control enabling" aria-label="Turn on captions" data-pressed-status="Captions on" data-released-status="Captions off" title="Turn on captions" > <span class="icon-stack" aria-hidden="true"> <!-- Captions --> <svg class="icon" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg"> <path d="M200-160q-33 0-56.5-23.5T120-240v-480q0-33 23.5-56.5T200-800h560q33 0 56.5 23.5T840-720v480q0 33-23.5 56.5T760-160H200Zm0-80h560v-480H200v480Zm80-120h120q17 0 28.5-11.5T440-400v-40h-60v20h-80v-120h80v20h60v-40q0-17-11.5-28.5T400-600H280q-17 0-28.5 11.5T240-560v160q0 17 11.5 28.5T280-360Zm280 0h120q17 0 28.5-11.5T720-400v-40h-60v20h-80v-120h80v20h60v-40q0-17-11.5-28.5T680-600H560q-17 0-28.5 11.5T520-560v160q0 17 11.5 28.5T560-360ZM200-240v-480 480Z" ></path> </svg> </span> </sv-toggle> </div>
<p class="status" aria-live="polite">Microphone on</p></div>
<script type="application/x-typescript" module>7 collapsed lines
const bar = document.querySelector(".call-bar")!; const status = document.querySelector(".status")!;
bar.addEventListener("pressedchange", event => { const toggle = event.target as Toggle; status.textContent = toggle.pressed ? (toggle.dataset.pressedStatus ?? "") : (toggle.dataset.releasedStatus ?? ""); });</script>
<style>75 collapsed lines
.call-controls { --anim-dur: 250ms;
display: grid; gap: 1em; justify-items: center; padding-block: 1em;
@media (prefers-reduced-motion: reduce) { --anim-dur: 0s; } }
.call-bar { display: flex; gap: 0.75em; padding: 0.6em; background-color: var(--sv-gray-7); border: solid var(--sv-bdr-sz-sm) var(--sv-gray-5); border-radius: calc(infinity * 1px); }
.control { padding: 0.6em; background-color: var(--sv-gray-6); border: none; border-radius: 50%;
.icon-stack { position: relative; display: grid; place-items: center; }
.icon { display: block; grid-area: 1 / 1; inline-size: 1.3em; block-size: 1.3em; fill: currentcolor; }
.slash { position: absolute; grid-area: 1 / 1; inline-size: 1.7em; block-size: 0.14em; background-color: currentcolor; border-block-start: solid 0.1em var(--sv-gray-6); rotate: -45deg; scale: 0 1; transition: scale var(--anim-dur) ease; } }
.control.muting:state(--pressed) { color: #fff; background-color: #dc2626;
.slash { border-block-start-color: #dc2626; scale: 1 1; } }
.control.enabling:state(--pressed) { color: var(--sv-accent-content); background-color: var(--sv-accent); }
.status { margin: 0; font-size: 0.85em; color: var(--sv-gray-3); }</style>