Fixtures

Provide concrete values for component-type props — icons, badges, or any React element.

What are fixtures

Some props accept React components rather than primitive values. A prop typed as icon?: LucideIcon can't be controlled with a text input. Fixtures give jc a set of named values to offer in a visual picker.

Create a fixture plugin

tsx
import { defineFixtures } from 'jc'
import { Star, Heart, Zap, Download, Trash2 } from 'lucide-react'
import { createElement } from 'react'

function icon(Comp: typeof Star, size = 20) {
  return {
    render: () => createElement(Comp, { size }),
    renderPreview: () => createElement(Comp, { size: 14 }),
    component: Comp,
  }
}

export const lucideFixtures = defineFixtures({
  name: 'lucide',
  fixtures: [
    { key: 'star', label: 'Star', category: 'icons', ...icon(Star) },
    { key: 'heart', label: 'Heart', category: 'icons', ...icon(Heart) },
    { key: 'zap', label: 'Zap', category: 'icons', ...icon(Zap) },
    { key: 'download', label: 'Download', category: 'icons', ...icon(Download) },
    { key: 'trash', label: 'Trash', category: 'icons', ...icon(Trash2) },
  ],
})

Fields reference

FieldTypeDescription
keystringUnique identifier within the plugin
labelstringDisplay name shown in the picker UI
categorystringGroup label — determines which prop kinds use this fixture
render() => ReactNodeFull-size preview rendered in the picker grid
renderPreview() => ReactNodeCompact preview for the selected-value thumbnail
componentComponentTypeThe actual value passed as the prop at runtime

How matching works

jc detects the kind of each prop from its TypeScript type. A prop typed as LucideIcon gets kind: "icon". The showcase then looks for fixtures in the matching category:

Prop KindFixture Category
iconicons
elementelements
nodenodes
The kind detection uses a layered heuristic: type pattern matching first (e.g. LucideIcon → icon), then prop name heuristics (e.g. leadingIcon → icon), with source regex as a tiebreaker.

Multiple plugins

Pass an array of plugins. All fixtures are merged and available in the controls:

tsx
<ShowcaseApp
  meta={meta}
  registry={registry}
  fixtures={[lucideFixtures, heroiconFixtures, customFixtures]}
/>

When multiple plugins define values in the same category, keys are qualified with the plugin name to avoid collisions: lucide:star vs heroicon:star.