fdb/docs

[§] /docs/how-to/own-your-components

How to own your components

Install components as source from registries, restyle them, and build the simple ones yourself.

TL;DR

  • Registries give you source files, not a package. You own and restyle them.
  • Add the registries to components.json, then npx shadcn add @ns/name.
  • One "wow" component per view. Design all six button states.

Goal: components that look like your site, not like the library's demo page.

You need

  • The shadcn CLI (or the shadcn MCP for your agent).
  • Your tokens, so you can restyle what you install.
 registry ─► shadcn CLI ─► components/ui ─► restyle
 @magicui    npx shadcn    your repo        your type,
 @react-bits add @ns/name  owns the code    colour, radius

Steps

1. Add the registries

"registries": {
  "@react-bits": "https://reactbits.dev/r/{name}.json",
  "@magicui":    "https://magicui.design/r/{name}.json",
  "@cult-ui":    "https://cult-ui.com/r/{name}.json",
  "@bklit":      "https://ui.bklit.com/r/{name}.json"
}

This repo ships that components.json.

2. Install from any of them

npx shadcn@latest add @magicui/marquee
npx shadcn@latest add @react-bits/SplitText-TS-TW
npx shadcn@latest add @bklit/line-chart

3. Pick the right library

LibraryBest forWatch out for
shadcn/uiButtons, dialogs, formsIt is a neutral start. Restyle it
React BitsText effects, backgrounds, cursor toysOne or two per page, not ten
Magic UIMarquee, bento, number ticker, beamsDefaults are recognisable. Change colour and type
Cult UICharacterful interactive piecesCheck keyboard access
21st.devMany authors' patternsQuality varies
Bklit UICharts and dashboardsKeep chart colours to your palette

4. Restyle until it matches

Swap every colour, radius and font for your tokens. Check keyboard and screen-reader behaviour of anything animated or custom.

5. Build the simple ones yourself

The marquee is one keyframe:

  • Linear
  • Stripe
  • Lusion
  • Igloo
  • Rauno
  • darkroom
  • Emil Kowalski
  • Bruno Simon
Two copies of the list, one translateX keyframe, a mask for soft edges. Hover pauses it; reduced motion stops it.
<div className="group flex overflow-hidden [mask-image:linear-gradient(90deg,transparent,#000_12%,#000_88%,transparent)]">
  {[0, 1].map((k) => (
    <ul key={k} aria-hidden={k === 1}
        className="flex shrink-0 gap-10 pr-10 motion-safe:animate-[marquee_28s_linear_infinite] group-hover:[animation-play-state:paused]">
      {items.map((i) => <li key={i}>{i}</li>)}
    </ul>
  ))}
</div>
Move over the cards, or Tab to them. JavaScript only writes --x and --y; CSS paints both gradients. No re-render per frame.

The spotlight card writes the pointer position into two CSS variables. A radial gradient does the rest, and focus can light it for keyboard users too.

6. Design every button state

Defaultresting
Hover150ms in
Pressed80ms, scale .97
Focus-visible0ms, keyboard only
Disabledno hover, not-allowed
Loadingwidth locked

Press Tab to reach it: the ring only appears for keyboard focus, never on click.

Six states every button needs. Hover and press should be quick (under 200ms); focus should be instant. Drag the slider to 600ms and feel how sluggish the live one gets.

Default, hover, pressed, focus, disabled and loading. Hover and press under 200ms, focus instant, and lock the width while loading so nothing jumps. The full list is in Components and states.

Why it works

Owning the source is what lets a site look like itself. Libraries are starting points. The design is in what you change.

See it live

[ex] in the wild · 19

Sources

On this page