Extras

The small components that ship alongside the headline ones. Each is a named export from the package root:

<script>
  import { CircleSpinner, Icon, ThemeToggle, Toggle } from 'svelte-widgets'
</script>

Toggle

A checkbox styled as a switch. checked is bindable and the children snippet receives it, so the label can react to the state. Everything else spreads onto the wrapping <label>.

svelte<script lang="ts">
  import { Toggle } from 'svelte-widgets'

  let [notifications, telemetry] = $state([true, false])
</script>

<div style="display: flex; flex-direction: column; gap: 8pt">
  <Toggle bind:checked={notifications} style="gap: 8pt">
    {#snippet children({ checked })}
      Notifications <em>({checked ? `on` : `off`})</em>
    {/snippet}
  </Toggle>

  <Toggle
    bind:checked={telemetry}
    style="gap: 8pt"
    --toggle-background="forestgreen"
    --toggle-knob-width="4em"
  >
    Telemetry (custom CSS vars)
  </Toggle>
</div>

ThemeToggle

Cycles light → system → dark → light, writes the choice to localStorage.theme, and sets colorScheme plus data-theme on <html>. The button stays hidden until mounted so SSR cannot flash a stale icon, and mounted toggles synchronize changes across tabs. Headless consumers can call watch_theme() to initialize the theme and follow both system preference and cross-tab changes, then call its returned cleanup function on teardown; flash-free first paint still requires equivalent synchronous logic in the HTML shell because hydration is too late.

svelte<script lang="ts">
  import { ThemeToggle } from 'svelte-widgets'
</script>

<ThemeToggle
  style="font-size: 2em"
  tooltip={{ placement: `right` }}
  icon_props={{ style: `color: var(--accent)` }}
/>

Icon

Renders one glyph from the bundled icon set at 1em square, inheriting currentColor. Pass the glyph value (<Icon icon={Info} />), not a name.

2040 matching icons