Formatting Toolbar
An editor toolbar built from two groups in one visual bar: text style as a multi-press group and alignment as an exclusive one. Each group keeps its own accessible name and its own valuechange listener, which applies the value to the preview paragraph below.
The valuechange event does not bubble, so the listeners sit on the groups themselves. Releasing the pressed alignment empties the exclusive group's value, and the preview falls back to the default alignment.
The quick brown fox jumps over the lazy dog.
Code
The following example assumes that you have imported the components and set up the theme.
<div class="editor">48 collapsed lines
<div class="toolbar"> <sv-toggle-group class="style-group" aria-label="Text style" value="bold"> <sv-toggle aria-label="Bold" title="Bold" value="bold"> <span class="glyph bold" aria-hidden="true">B</span> </sv-toggle>
<sv-toggle aria-label="Italic" title="Italic" value="italic"> <span class="glyph italic" aria-hidden="true">I</span> </sv-toggle>
<sv-toggle aria-label="Underline" title="Underline" value="underline"> <span class="glyph underline" aria-hidden="true">U</span> </sv-toggle> </sv-toggle-group>
<span class="divider" aria-hidden="true"></span>
<sv-toggle-group class="align-group" aria-label="Text alignment" exclusive value="left"> <sv-toggle aria-label="Align left" title="Align left" value="left"> <!-- Left-aligned lines --> <svg class="icon" aria-hidden="true" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg"> <path d="M120-120v-80h720v80H120Zm0-160v-80h480v80H120Zm0-160v-80h720v80H120Zm0-160v-80h480v80H120Zm0-160v-80h720v80H120Z" ></path> </svg> </sv-toggle>
<sv-toggle aria-label="Align center" title="Align center" value="center"> <!-- Centered lines --> <svg class="icon" aria-hidden="true" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg"> <path d="M120-120v-80h720v80H120Zm160-160v-80h400v80H280ZM120-440v-80h720v80H120Zm160-160v-80h400v80H280ZM120-760v-80h720v80H120Z" ></path> </svg> </sv-toggle>
<sv-toggle aria-label="Align right" title="Align right" value="right"> <!-- Right-aligned lines --> <svg class="icon" aria-hidden="true" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg"> <path d="M120-760v-80h720v80H120Zm240 160v-80h480v80H360ZM120-440v-80h720v80H120Zm240 160v-80h480v80H360ZM120-120v-80h720v80H120Z" ></path> </svg> </sv-toggle> </sv-toggle-group> </div>
<p class="preview bold">The quick brown fox jumps over the lazy dog.</p></div>
<script type="application/x-typescript" module>13 collapsed lines
const styleGroup = document.querySelector<ToggleGroup>(".style-group")!; const alignGroup = document.querySelector<ToggleGroup>(".align-group")!; const preview = document.querySelector<HTMLElement>(".preview")!;
styleGroup.addEventListener("valuechange", () => { for (const style of ["bold", "italic", "underline"]) { preview.classList.toggle(style, styleGroup.value.includes(style)); } });
alignGroup.addEventListener("valuechange", () => { preview.style.textAlign = alignGroup.value[0] ?? ""; });</script>
<style>86 collapsed lines
.editor { display: grid; gap: 1em; justify-items: center; max-inline-size: 26rem; margin-inline: auto; }
.toolbar { display: flex; gap: 0.25em; align-items: center; padding: 0.25em; background-color: var(--sv-gray-6); border-radius: var(--sv-bdr-rad-md);
.divider { inline-size: var(--sv-bdr-sz-sm); block-size: 1.4em; margin-inline: 0.25em; background-color: var(--sv-gray-4); }
sv-toggle-group { gap: 0.25em; }
sv-toggle { padding: 0.45em; background-color: transparent; border: none; border-radius: var(--sv-bdr-rad-sm);
&:state(--pressed) { color: var(--sv-accent); background-color: color-mix(in srgb, var(--sv-accent) 15%, transparent); } }
.glyph { display: block; inline-size: 1.2em; block-size: 1.2em; line-height: 1.2em; text-align: center;
&.bold { font-weight: 700; }
&.italic { font-style: italic; }
&.underline { text-decoration: underline; } }
.icon { display: block; inline-size: 1.2em; block-size: 1.2em; fill: currentcolor; } }
.preview { inline-size: 100%; padding: 1em; margin: 0; border: solid var(--sv-bdr-sz-sm) var(--sv-gray-5); border-radius: var(--sv-bdr-rad-md);
&.bold { font-weight: 700; }
&.italic { font-style: italic; }
&.underline { text-decoration: underline; } }</style>