- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Hover Card
- Input
- Input OTP
- Kbd
- Label
- Menubar
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
Introduction
shadcn/ui components, restyled with StyleX on top of Base UI primitives.
shadcn-cssinjs is an open shadcn registry where every component is styled with StyleX — atomic, build-time CSS-in-JS — instead of Tailwind, and built on Base UI primitives instead of Radix.
The distribution model is exactly the same as shadcn/ui: you install a component with the
shadcn CLI and the source code lands in your project. You own it, you read it, you edit
it. There is no runtime library to wrestle with.
Why StyleX + Base UI?
- StyleX styling — Styles are colocated, type-safe, and compiled to atomic CSS at build time. No utility-class strings, no runtime style injection, no specificity wars.
- Base UI primitives — Accessible, unstyled primitives from the team behind Radix and Floating UI. Modern API, great defaults.
- Token-driven theming — Styles reference your existing CSS variables (
--background,--primary, …), so light/dark theming via a.darkclass keeps working out of the box. - You own the code — Installed with
npx shadcn add; you get real source files, not an npm dependency.
How It Works
Each component lives in its own folder with two files:
components/ui/
└── button/
├── button.tsx # the Base UI + StyleX component
└── button.stylex.ts # its StyleX rules (stylex.create)Styles are authored in the .stylex.ts file and applied in the component with a small
x() helper (a thin wrapper over stylex.props). Shared design tokens live in
components/ui/tokens.stylex.ts and are referenced by every component.
import { styles } from "./button.stylex";
import { x } from "@/lib/utils";
export function Button({ className, ...props }) {
const p = x(styles.base, styles.default);
return <button className={p.className} style={p.style} {...props} />;
}StyleX cannot target a component's own data-state attributes or peer/group
selectors the way Tailwind can. State-based styling (open, highlighted,
pressed, …) is handled with Base UI's className-as-function API, which
receives the current state.
Tech Stack
Next.js 16+ App Router andReact 19@stylexjs/stylexfor styling (Babel transform + PostCSS plugin)@base-ui/reactfor primitivesFumadocsfor these docsTailwind CSS 4for the docs site itself