Forms
Toolbar
Groups related controls, such as formatting buttons, into one bar. Tab reaches it once; the arrow keys move along it.
Installation
npx sinaui add toolbarCopy src/lib/ui/Toolbar.svelte and tokens.css. No dependencies.
Examples
Formatting
Toggles show when they're on. Tab into the bar, then use the arrow keys; the menu at the end opens with Down.
Light travels in straight lines from every point of a lit object.
<script lang="ts">
import {
ArrowDown01Icon,
TextAlignCenterIcon,
TextAlignLeftIcon,
TextAlignRightIcon,
TextBoldIcon,
TextItalicIcon,
TextUnderlineIcon,
ArrowTurnBackwardIcon,
ArrowTurnForwardIcon
} from '@hugeicons/core-free-icons';
import Button from '#lib/ui/Button.svelte';
import Icon from '#lib/ui/Icon.svelte';
import Toolbar from '#lib/ui/Toolbar.svelte';
import * as Dropdown from '#lib/ui/dropdown/index.js';
let bold = $state(true);
let italic = $state(false);
let underline = $state(false);
let align = $state<'left' | 'center' | 'right'>('left');
const aligns = [
{ value: 'left', label: 'Align left', icon: TextAlignLeftIcon },
{ value: 'center', label: 'Center', icon: TextAlignCenterIcon },
{ value: 'right', label: 'Align right', icon: TextAlignRightIcon }
] as const;
</script>
<Toolbar label="Formatting">
<Button
variant="ghost"
size="sm"
square
aria-label="Bold"
aria-pressed={bold}
onclick={() => (bold = !bold)}
>
<Icon icon={TextBoldIcon} size={18} />
</Button>
<Button
variant="ghost"
size="sm"
square
aria-label="Italic"
aria-pressed={italic}
onclick={() => (italic = !italic)}
>
<Icon icon={TextItalicIcon} size={18} />
</Button>
<Button
variant="ghost"
size="sm"
square
aria-label="Underline"
aria-pressed={underline}
onclick={() => (underline = !underline)}
>
<Icon icon={TextUnderlineIcon} size={18} />
</Button>
<span role="separator"></span>
{#each aligns as a (a.value)}
<Button
variant="ghost"
size="sm"
square
aria-label={a.label}
aria-pressed={align === a.value}
onclick={() => (align = a.value)}
>
<Icon icon={a.icon} size={18} />
</Button>
{/each}
<span role="separator"></span>
<Button variant="ghost" size="sm" square aria-label="Undo"
><Icon icon={ArrowTurnBackwardIcon} size={18} /></Button
>
<Button variant="ghost" size="sm" square aria-label="Redo" disabled
><Icon icon={ArrowTurnForwardIcon} size={18} /></Button
>
<span role="separator"></span>
<Dropdown.Root>
{#snippet trigger(props)}
<Button variant="ghost" size="sm" {...props}
>Insert <Icon icon={ArrowDown01Icon} size={14} /></Button
>
{/snippet}
<Dropdown.Item>Marginal note</Dropdown.Item>
<Dropdown.Item>Diagram</Dropdown.Item>
<Dropdown.Item>Table of stars</Dropdown.Item>
</Dropdown.Root>
</Toolbar>
<div class="page">
<p class="sample" class:bold class:italic class:underline style:text-align={align}>
Light travels in straight lines from every point of a lit object.
</p>
</div>
<style>
/* Its own row under the toolbar, the text block centered in it. */
.page {
flex-basis: 100%;
}
.sample {
inline-size: min(26rem, 100%);
margin: 1rem auto 0;
font-size: 0.9375rem;
}
.bold {
font-weight: 600;
}
.italic {
font-style: italic;
}
.underline {
text-decoration: underline;
}
</style>Props
| Prop | Type | Default |
|---|---|---|
label | string | required |
orientation | 'horizontal' | 'vertical' | 'horizontal' |
Put any buttons inside. Divide groups with <span role="separator"></span>; give toggles aria-pressed.
Accessibility
- One tab stop for the whole bar; it remembers where you were.
- Arrow keys move along it (Up and Down when vertical), wrapping; Home and End jump to the ends. Right to left, the arrows follow the reading direction.
- Disabled controls are skipped.