Keyboard-friendly, accessible and highly customizable Svelte components. View the docs
Every component is a named export from the package root. MultiSelect, CommandMenu,
PageSearch, Toc and Masonry also have a direct subpath import
(svelte-widgets/Toc.svelte) so bundlers can skip the rest:
| Component | What it does | Docs |
|---|---|---|
MultiSelect |
Keyboard-friendly multi/single select with grouping, async loading and deep style hooks | docs |
CommandMenu |
Command palette with fuzzy search, hotkeys, recents and async actions | docs |
PageSearch |
Pagefind-backed site search built on CommandMenu |
docs |
Popover |
Floating surface that positions, dismisses and traps focus for you | docs |
ContextMenu |
Right-click menu anchored to the pointer, with arrow-key navigation | docs |
Nav |
Navigation bar with dropdowns, pinning and active-route styling | docs |
Toc |
Sticky table of contents that finds and tracks its own headings | docs |
Masonry |
Column-balancing masonry grid with SSR support and virtualization | docs |
CopyButton |
Copy-to-clipboard button with pending, success and error states | docs |
ThemeToggle |
Light/dark/system theme cycler that persists the choice | docs |
Toggle |
Accessible switch with a bindable checked |
docs |
CodeExample |
Collapsible source viewer used by the live examples | docs |
FileDetails |
Collapsible <details> viewer for a set of files |
docs |
PrevNext |
Previous/next links for sequential pages | docs |
SubpageGrid |
Card grid linking to child pages | docs |
Icon |
Inline SVG icon from the bundled set | docs |
GitHubCorner |
The classic corner ribbon link | docs |
CircleSpinner |
Minimal loading spinner | docs |
Wiggle |
Spring-animated shake wrapper | docs |
Ten attachments ship alongside them
and work on any element. Nine come from svelte-widgets/attachments: click_outside,
float, focus_trap, hotkey, tooltip, draggable, resizable, sortable and
highlight_matches. The tenth, heading_anchors, has its own
svelte-widgets/heading-anchors subpath.
<script>
import { CommandMenu, MultiSelect, Popover, Toc } from 'svelte-widgets'
</script>- No run-time deps: every component needs only Svelte as a peer dependency
- Keyboard friendly: every interactive component is fully operable without a mouse
- Bindable: component state is exposed through
$bindableprops, so you can both read it and drive it from the outside - Themeable: CSS variables with sensible defaults on every element, plus prop bags to spread arbitrary attributes onto internals
- SSR-safe: nothing touches
windoworlocalStoragebefore mount - Typed: props, snippets and events are inferred from the data you pass
| Statements | Branches | Lines |
|---|---|---|
npm install --dev svelte-widgetsThis package was called svelte-multiselect up to v11. Swap it out:
npm uninstall svelte-multiselect && npm install -D svelte-widgetsThen rewrite the imports. Matching on the opening quote (all three kinds) keeps prose and
GitHub URLs untouched, and covers every subpath (/attachments, /utils, /types,
/heading-anchors, /live-examples) along with the bare import. It skips .md
deliberately: in markdown a backtick-quoted mention is usually prose, not an import.
find src -type f \( -name '*.svelte' -o -name '*.ts' -o -name '*.js' \) -exec perl -pi -e "s{(['\"\`])svelte-multiselect}{\$1svelte-widgets}g" {} +Three things the rewrite cannot do for you: CmdPalette is now CommandMenu,
PagefindPalette is now PageSearch, and click_outside changed shape (it dismisses on
pointerdown, and exclude/include merged into one inside option). See the
changelog for the details.
Coming from svelte-toc or svelte-bricks instead? Those are now Toc and Masonry
here, so the same swap applies with import { Toc } from 'svelte-widgets' and
import { Masonry } from 'svelte-widgets'.
Attachments and utilities are also available as subpath imports:
import {
click_outside, // dismiss a surface when a press lands outside it
draggable,
float, // park an element next to an anchor and keep it there
focus_trap, // keep Tab inside a surface, hand focus back when it closes
highlight_matches,
hotkey, // declarative keybindings, `mod` maps to Cmd or Ctrl
sortable,
tooltip,
} from 'svelte-widgets/attachments'
import { compute_position, fuzzy_match, get_label } from 'svelte-widgets/utils'
import { heading_anchors } from 'svelte-widgets/heading-anchors'Popover and ContextMenu compose these three: a surface positioned by float,
dismissed by click_outside (on the press, so a right-click closes it too) and
keyboard-scoped by focus_trap.
<script lang="ts">
import { ContextMenu, Popover } from 'svelte-widgets'
</script>
<Popover placement="bottom" align="start">
{#snippet trigger(props)}
<button {...props}>Options</button>
{/snippet}
<p>Anything you like in here.</p>
</Popover>
<ContextMenu actions={[{ label: `Reload`, action: () => location.reload() }]}>
<div>Right-click anywhere in this region</div>
</ContextMenu>See src/lib/live-examples/readme.md for optional live-example helpers.
Here are some steps to get you started if you'd like to contribute to this project!