npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

svelte-widgets

v1.2.0

Published

Accessible, keyboard-friendly Svelte components and attachments

Readme

Tests GitHub Pages NPM version Needs Svelte version Playground Open in StackBlitz

🧩   Components

Every component is a named export from the package root, and every one also has 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 | | ConfirmDialog | Promise-based dialog queue, so two racing prompts can't share one answer | docs | | DraggablePane | Floating panel you can drag by its header, resize and reset to its anchor | docs | | Sheet | Portalled edge panel with backdrop dismissal and focus restoration | docs | | Tabs | Controlled ARIA tabs with automatic or manual keyboard activation | docs | | Accordion | Single or multi-open disclosure group with snippet-rendered content | docs | | Toast | Notification queue with priorities, dedupe and pause-on-hover | 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 | | Footer | Centered row of icon links, sized and themed with --footer-* | docs | | CopyButton | Copy-to-clipboard button with pending, success and error states | docs | | ButtonGroup | Segmented control over a set of options, single or multi select | docs | | FullscreenButton | Fullscreen toggle scoped to one wrapper, so viewers don't fight over the flag | 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 | | ContributorList | Avatar row of GitHub contributors, grayscale until hover | docs | | LiteYouTubeEmbed | YouTube poster that only loads the player iframe once clicked | docs | | Wiggle | Spring-animated shake wrapper | docs |

Fifteen attachments ship alongside them and work on any element. Fourteen come from svelte-widgets/attachments: backdrop_dismiss, click_outside, contrast_color, draggable, file_drop, float, focus_trap, forward_window_keydown, highlight_matches, hotkey, portal, resizable, sortable and tooltip. The fifteenth, heading_anchors, has its own svelte-widgets/heading-anchors subpath. dismiss_on_outside_press is the lower-level multi-surface primitive behind click_outside.

<script>
  import { CommandMenu, MultiSelect, Popover, Tabs, Toc } from 'svelte-widgets'
</script>

💡   Features

  • 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 $bindable props, 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 window or localStorage before mount
  • Typed: props, snippets and events are inferred from the data you pass

🧪   Coverage

| Statements | Branches | Lines | | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------ | | Statements | Branches | Lines |

🔨   Installation

npm install --dev svelte-widgets

🚚   Migrating from svelte-multiselect

This package was called svelte-multiselect up to v11. Swap it out:

npm uninstall svelte-multiselect && npm install -D svelte-widgets

Then rewrite the imports. Matching on the opening quote (all three kinds) keeps prose and GitHub URLs untouched, and covers every subpath 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'.

📦   Subpath exports

Components have direct .svelte entry points, and headless/build-time APIs have focused subpaths:

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'

| Subpath | API | | ----------------------------------- | ---------------------------------------------------------- | | /attachments | Element attachments and dismissal primitives | | /clipboard | Clipboard feedback state | | /dialogs | Queued choice, confirmation and prompt requests | | /file-drop | Directory expansion and accept filtering | | /fullscreen | Shared fullscreen state | | /heading-anchors | Heading ID preprocessor, slugger and anchor attachment | | /icons | Dynamic icon registry | | /katex | KaTeX before/after preprocessor pair | | /live-examples | mdsvex live-example transform, Vite plugin and highlighter | | /live-examples/create-highlighter | Lightweight custom grammar highlighter factory | | /print | Element printing | | /text-search | Text ranges, highlighting and search-jump helpers | | /theme | Headless light/dark/system state | | /toast-queue | Toast reducer and reactive store | | /types | Shared component/action types | | /utils | Positioning, fuzzy matching, hotkeys and general helpers | | /vite-config | This repository's Vite Plus configuration helper |

For $…$ and $$…$$ math in mdsvex, run katex_preprocess() before and after mdsvex so markdown never sees the rendered HTML, then heading_ids() last:

import { mdsvex } from 'mdsvex'
import { heading_ids } from 'svelte-widgets/heading-anchors'
import { katex_preprocess } from 'svelte-widgets/katex'

const { before: katex_before, after: katex_after } = katex_preprocess()

export default {
  preprocess: [katex_before, mdsvex({ extensions: [`.md`] }), katex_after, heading_ids()],
}

Import katex/dist/katex.min.css once in the app so the generated markup is styled.

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.

🆕   Changelog

View the changelog.

🙏   Contributing

Here are some steps to get you started if you'd like to contribute to this project!