SilicaUI

Ship components, not decisions.

A Base UI behavior layer with CSS-first styling. Bring your own design tokens, keep accessible primitives underneath.

Get started

Every component beside this is real and rendering live — the same markup you’d ship, re-themed by a token swap, never a rebuild.

The first five minutes are always great

Then you need a combobox with real keyboard support. Or your brand color, on a component that never heard of it. Or the same card inside a sidebar, where the breakpoints are suddenly wrong. None of that is in the quickstart, and all of it lands in your codebase.

SilicaUI is what happened after hitting those walls enough times to treat them as one problem. Here are four of them, each with the fix running live on this page.

CSS-only libraries stop right where the hard part starts

A class-based library gives you a beautiful combobox — as styles. The typeahead, the roving focus, the aria-activedescendant bookkeeping and the dismiss behavior are still yours to write, or you bolt on a second headless library and maintain two vocabularies that disagree about everything.

SilicaUI ships the styles and the behavior as one thing. Interaction comes from Base UI — the part you shouldn't have to take our word for — under classes that stay plain CSS. Type in the field beside this and drive it entirely from the keyboard.

Deploy to regionLive
  • Typeahead filtering with roving focus
  • Escape and outside-click to dismiss
  • aria-activedescendant on the live option
  • Selection announced to a screen reader
EnterEscnone of it wired by you

Pick a color. Watch it cascade.

Most systems ship a fixed palette. Adding your own color means a config entry, a rebuild, and then discovering the utility half exists but the component half doesn't — your brand gets a background utility but no button variant, or the reverse. So you hardcode a hex, and it stops responding to dark mode.

Drag the sliders and watch every component in the panel re-tint at once — the button variants, the badge, the ink, the border and the progress fill, all reading one token. No rebuild, no recompile. This isn't a video; it's the library running.

brandoklch(0.58 0.24 320)
oklch(0.58 0.24 320)#b431cf
L
0.58
C
0.24
H
320°
HEX
badge-brandtext-brandborder-brand
Rollout to brand tier

The components you’d otherwise lose a sprint to

Anyone can ship a button. These are the ones that quietly eat a week — month arithmetic, chip editing, drop rejection, paste handling. Every one below is live on this page right now, and every one is keyboard-operable.

Calendarmonth math
July 2026
Multi-selectchips
Next.js
Astro

Backspace removes the last chip; type to filter what’s left.

Dropzonedrag & drop
Drop files here, or click to browsePNG or JPG, up to 2MB
Pin inputpaste-aware

Paste a six-digit code and it distributes across the fields.

"size" should mean the same thing everywhere

You learn that size=“sm” works on the button, so you reach for it on the empty state — and nothing happens. Or the select supports three sizes and the input supports five. These gaps are invisible until you hit one, and they cost you a trip to the source to find out which components opted in.

Every sized component here implements the same five steps, and a probe fails the build if one of them goes missing. Change the size once and watch every component below move together — including the ones that historically wouldn't have.

Density
Live

Breakpoints are the wrong unit inside a sidebar

A card built with viewport breakpoints is only correct in the place you first built it. Drop that same card into a sidebar, a bento cell or a two-column split and it thinks it has the whole window — so you fork it, or thread a size prop through every level to fake what CSS already knows.

SilicaUI components respond to their container instead. The two cards beside this are the exact same markup and the exact same classes, rendered at two widths in one viewport. Nothing was forked and no prop was passed.

One card, two containerssame markup
In a 16rem sidebar
ProductionDeployed 4m ago
Healthy
In a full-width row
ProductionDeployed 4m ago
Healthy

The same components, with no framework at all

React is one output, not the product. The node tree also projects to plain HTML that a zero-dependency runtime hydrates — real keyboard handling and focus management on a static page, with no bundler and no framework on the client.

Authored once
atom("Switch", undefined, {
  color: "accent",
  defaultChecked: true,
})
Emitted by toHtml()
<span role="switch" tabindex="0" aria-checked="true" data-checked data-sui-behavior="switch">
<input class="switch-input" type="checkbox" checked/>
</span>
CSP-cleanNo style attributes and no inline script in the static output — verified by a probe on every build.
113Documented components
34Vanilla behaviors
13Published packages
MITLicensed, open source

113 components across 13 packages

Thirteen packages, but you install four. The core carries no third-party runtime; every heavy dependency lives in an opt-in sibling you add only when you reach for it.

The core — installed together

silicaui

The Tailwind v4 plugin — CSS system, tokens, one design language.

silicaui-react

React components on Base UI primitives.

silicaui-html

Framework-neutral node tree and HTML projection.

silicaui-behaviors

Zero-dependency runtime that hydrates static markup.

Opt-in power — add only what you need

silicaui-chartsECharts
silicaui-tableTanStack Table
silicaui-editorTipTap
silicaui-dnddnd-kit
silicaui-panelsresizable-panels
silicaui-builderthe visual builder

Start with one line.

Install the package, bring your tokens, ship.

Read the docs
MIT licensed — free forever.