Bits ui
Skill BetaHuhn/skills/bits-ui
A collection of skills for use with AI coding tools
npx -y skills add BetaHuhn/skills --skill bits-uiAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Guide for building UI components with Bits UI, the headless Svelte 5 component library. Use this skill whenever the user is working with Bits UI components, importing from "bits-ui", building accessible UI primitives in Svelte, or asking about dialogs, selects, comboboxes, accordions, popovers, tooltips, dropdowns, date pickers, or any other headless component in a Svelte project. Trigger even if the user just mentions "bits-ui" or asks to "add a dialog/select/dropdown" in a Svelte project.
SKILL.md
6.6 KB, as published. Nobody here has run it
Bits UI
Bits UI is a headless component library for Svelte 5. Components ship unstyled — you provide all styling via classes, data attributes, or CSS variables.
Install:
npm install bits-ui
Core patterns
Compound component structure
Every Bits UI component uses a dot-notation compound pattern:
<script lang="ts">
import { Accordion } from "bits-ui";
</script>
<Accordion.Root type="single">
<Accordion.Item value="item-1">
<Accordion.Header>
<Accordion.Trigger>Title</Accordion.Trigger>
</Accordion.Header>
<Accordion.Content>Content here</Accordion.Content>
</Accordion.Item>
</Accordion.Root>
Imports
Import named components from "bits-ui":
import { Dialog, Select, Accordion, Popover, Tooltip } from "bits-ui";
State management
Two-way binding (simple):
let open = $state(false);
let value = $state("");
<Dialog.Root bind:open>
<Select.Root bind:value>
Function binding (full control — lets you intercept or gate updates):
<Select.Root bind:value={
() => currentValue,
(v) => { if (isValid(v)) currentValue = v; }
}>
Each component's API docs indicate which props are bindable.
Accessing DOM elements (refs)
let triggerEl = $state<HTMLButtonElement | null>(null);
<Dialog.Trigger bind:ref={triggerEl}>Open</Dialog.Trigger>
Important: Never set id directly on a child element inside {#snippet child(...)} — pass id to the parent component instead so it's included in the merged props.
Styling
Bits UI ships unstyled. Three approaches:
classprop — apply Tailwind, UnoCSS, or any utility classes directly- Data attributes — each component exposes data attributes for CSS targeting:
- State:
[data-state="open"],[data-disabled],[data-highlighted] - Identity:
[data-accordion-trigger],[data-dialog-content], etc.
- State:
- CSS variables — for dynamic sizing:
--bits-accordion-content-height,--bits-select-anchor-width, etc.
The child snippet — custom elements
Use {#snippet child({ props })} to replace a component's default element with your own, enabling scoped styles, Svelte actions, or custom components:
<Accordion.Trigger>
{#snippet child({ props })}
<button {...props} class="my-trigger">Toggle</button>
{/snippet}
</Accordion.Trigger>
Critical rules:
- Always spread
{...props}— it contains ARIA attributes, event handlers, and internal state - Pass custom
id,onclick, etc. to the parent component, not inside the snippet - Outside children are ignored when
childsnippet is used
Floating content (Popover, Tooltip, Select, etc.)
Floating components require a two-level structure inside child:
<Popover.Content>
{#snippet child({ wrapperProps, props, open })}
{#if open}
<div {...wrapperProps}> <!-- outer: handles positioning, leave unstyled -->
<div {...props} transition:fade> <!-- inner: add styles and transitions here -->
Content
</div>
</div>
{/if}
{/snippet}
</Popover.Content>
Never style the wrapper element (wrapperProps). Styling goes on the inner element only.
Components requiring two-level structure:
Combobox.Content, DatePicker.Content, DateRangePicker.Content, DropdownMenu.Content, LinkPreview.Content, Menubar.Content, Popover.Content, Select.Content, Tooltip.Content
Svelte transitions without child
Use forceMount + child to animate open/close with Svelte transitions on non-floating components:
<Dialog.Content forceMount>
{#snippet child({ props, open })}
{#if open}
<div {...props} transition:scale={{ start: 0.95 }}>
Dialog content
</div>
{/if}
{/snippet}
</Dialog.Content>
Available components
| Category | Components |
|---|---|
| Overlay/Dialog | Dialog, Alert Dialog, Popover, Tooltip, Link Preview |
| Menus | Dropdown Menu, Context Menu, Menubar, Navigation Menu |
| Form inputs | Button, Checkbox, Radio Group, Switch, Toggle, Toggle Group, Slider, Pin Input, Label |
| Select/Search | Select, Combobox, Command |
| Date/Time | Calendar, Range Calendar, Date Field, Date Range Field, Date Picker, Date Range Picker, Time Field, Time Range Field |
| Layout/Display | Accordion, Collapsible, Tabs, Scroll Area, Separator, Aspect Ratio, Avatar |
| Feedback | Progress, Meter, Rating Group, Pagination |
| Navigation | Toolbar |
Utilities
mergeProps(...props)— merge multiple prop objects, concatenating event handlers and classes<Portal>— render content outside the current DOM hierarchyisUsingKeyboard()— reactive boolean for keyboard vs. pointer detection<BitsConfig>— global configuration provideruseId()— generate stable unique IDs
Fetching component documentation
When you need detailed props, full API tables, or advanced examples for a specific component, fetch its docs:
https://bits-ui.com/docs/components/{component-name}/llms.txt
For example:
https://bits-ui.com/docs/components/dialog/llms.txthttps://bits-ui.com/docs/components/select/llms.txthttps://bits-ui.com/docs/components/combobox/llms.txt
General topic docs:
https://bits-ui.com/docs/state-management/llms.txthttps://bits-ui.com/docs/child-snippet/llms.txthttps://bits-ui.com/docs/styling/llms.txthttps://bits-ui.com/docs/transitions/llms.txt
Always fetch the component's llms.txt before writing complex components or when the user asks about specific props. The docs include full prop tables with types, defaults, and descriptions.
Common pitfalls
- Missing
{...props}spread insidechildsnippet — breaks accessibility and event handling - Styling the wrapper in floating components — breaks positioning
- Setting
idon the child element instead of the parent component — breaks ref bindings - Forgetting two-level structure for floating content — breaks Floating UI positioning
- Using Svelte 4 patterns — Bits UI requires Svelte 5 (runes, snippets)