Rokkit
style density

Data Binding

Rokkit is built around one principle: your data should drive your UI, not the other way around. Every selection component — List, Select, Tree, Tabs, Menu, Table, Grid — works with your data as-is via a fields mapping, not by forcing you to reshape it.

The problem with rigid contracts

Most component libraries require your data to match a specific shape. A Select needs { label, value }, a Tree needs { name, children }. Every component has its own convention, so you write adapter functions everywhere:

const selectOptions = users.map(u => ({ label: u.name, value: u.id }))
const treeNodes    = folders.map(f => ({ name: f.title, children: f.items }))

That's noise. It's two transforms per component, plus a tax every time a field rename happens upstream.

The Rokkit approach

Every Rokkit component accepts a fields prop that maps your keys to the component's semantic fields. Your { name, id, nested } data works directly — no transformation, no adapter layer.

<List
  items={users}
  fields={{ label: 'name', value: 'id' }}
  bind:value
/>

Default field names

If you don't pass fields, every component falls back to a sensible default set: label, value, icon, children, disabled, description. Match those keys in your data and fields becomes optional.

const items = [
  { label: 'Home', value: '/', icon: 'i-mdi:home' },
  { label: 'Docs', value: '/docs', icon: 'i-mdi:book' }
]

Primitives work too

For simple cases, an array of strings or numbers is a valid items value. The component treats each entry as both label and value:

<List items={['Small', 'Medium', 'Large']} bind:value />

Nested fields with dot notation

If your data has nested objects, point fields at them with dot paths:

<List
  items={people}
  fields={{ label: 'profile.fullName', value: 'meta.uid' }}
/>

The semantic field vocabulary

Field Used by What it does
label most The text shown to the user
value selection components The bindable identifier
icon most CSS class for an inline icon
description List / Menu Secondary line under the label
children Tree / Menu Nested items recursion
disabled most Greys out + skips keyboard nav
badge List / Tree Right-aligned badge text
shortcut Menu Keyboard hint text on the right
href BreadCrumbs / FloatingNav Renders as a link

Bindable values

Selection components expose value as a $bindable() prop. bind:value round-trips it without any onchange plumbing, the same way <input bind:value> works in vanilla Svelte.

Multi-select components (MultiSelect, Swatch[multiple]) bind an array of values instead of a single one — same prop name, different shape.