Skip to content

Bits UI

Use Bits UI primitives to draw GistUI components in Svelte 5, with form validation and bind:$var still working.

Updated View as Markdown

For Svelte 5 apps that use Bits UI primitives directly. If you use shadcn-svelte, which is built on Bits UI, start with shadcn-svelte.

npm i @gistui/svelte @gistui/styles @gistui/catalog bits-ui

A switch

Bits UI form primitives render a hidden native input when given name, so the GistUI Form around them can read the value.

GistSwitch.sveltesvelte
<script lang="ts">
  import { Switch } from "bits-ui";
  import { gistField, type GistUIComponentProps } from "@gistui/svelte";

  let p: GistUIComponentProps = $props();
  const id = $props.id();
  const field = gistField(() => p.ctx, "bool"); // one on/off value
</script>

<div class="switch-row">
  <Switch.Root
    {id}
    name={field.current.name}
    disabled={field.current.locked}
    checked={field.current.bound ? field.current.value === true : p.props.checked === true}
    onCheckedChange={(on) => field.current.bound && field.current.setValue(on)}
    class="switch"
  >
    <Switch.Thumb class="switch-thumb" />
  </Switch.Root>
  <label for={id}>{field.current.label}</label>
</div>

A card

GistCard.sveltesvelte
<script lang="ts">
  import { GistChildren, type GistUIComponentProps } from "@gistui/svelte";
  let {}: GistUIComponentProps = $props();
</script>

<section class="my-card" data-gistui="Card"><GistChildren /></section>

Register them

<script lang="ts">
  import { GistUI } from "@gistui/svelte";
  import GistCard from "./GistCard.svelte";
  import GistSwitch from "./GistSwitch.svelte";
</script>

<GistUI source={answer} streaming={loading} components={{ Switch: GistSwitch, Card: GistCard }} onaction={onAction} />

Notes

  • Call gistField while the component initialises, and read it through field.current.
  • Keep GistUI’s built-in Button and style it with tokens: actions, form submits and dialogs then keep working.
  • Bits UI ships no styles. Use tokens so the GistUI components you did not replace match yours.
Navigation

Type to search…

↑↓ navigate↵ selectEsc close