Orbit UI is a lightweight, customizable React component library inspired by shadcn/ui and powered by Tailwind CSS—simple to install, easy to extend, ready for npm.
- Minimal, composable primitives with sensible defaults
- Tailwind-first styling with modern color tokens using OKLCH
- Built with class-variance-authority (CVA) and tailwind-merge for safe, ergonomic variants
- Radix Slot for flexible composition
- Lucide React icons for consistent iconography
- Animations via tw-animate-css
Status: early-stage. The repository already includes a working Button component and a global Tailwind theme. Additional components and exports are being rolled out.
- React 18 or later
- Tailwind CSS v4 (new
@import "tailwindcss"and@theme inlinesyntax) - Node.js 18 or later
- A bundler that can process CSS and TypeScript (e.g., Next.js, Vite)
Note: Orbit’s globals.css uses Tailwind v4 features (custom variant, inline theme). Ensure your app is configured for Tailwind v4.
Once Orbit UI is published to npm:
- pnpm:
pnpm add @ooiai/orbit - npm:
npm install @ooiai/orbit - yarn:
yarn add @ooiai/orbit
Until it is published, you can install locally from a path:
- pnpm:
pnpm add /absolute/path/to/orbit - npm:
npm install /absolute/path/to/orbit
Dependencies used internally (already declared in this package):
@radix-ui/react-slotclass-variance-authorityclsxtailwind-mergelucide-reacttw-animate-css
Your app must have Tailwind v4 configured so it can process Orbit’s CSS and the tw-animate-css import.
- Import Orbit’s global theme once in your app entry:
import '@ooiai/orbit/globals.css'
- Verify Tailwind v4 is active in your app:
- Your app-level CSS should include
@import "tailwindcss";(Tailwind v4) - Ensure your build pipeline handles CSS from node_modules
- Dark mode:
- Orbit uses a custom dark variant bound to the
.darkclass on thehtmlorbodyelement - Toggle dark mode by setting or removing the
darkclass on your root element
Orbit ships composable components that accept variant props. The initial component included is Button.
Import directly from the file (current structure), until index exports are added:
import { Button } from '@ooiai/orbit/components/ui/button'
Then use it in JSX:
<Button>Default</Button><Button variant="secondary">Secondary</Button><Button variant="destructive" size="sm">Delete</Button><Button size="lg" onClick={...}>Click me</Button><Button asChild><a href="/docs">Docs</a></Button>(renders an anchor with Button styles via Radix Slot)
Variants:
variant:default | destructive | outline | secondary | ghost | linksize:default | sm | lg | icon | icon-sm | icon-lgasChild:booleanto render styles onto a child via Slot
Orbit is built to be themed and extended.
- Override color tokens and radius in your app:
- Add CSS variables to
:rootand.darkin your app’s own global CSS - Orbit reads variables like
--background,--foreground,--primary,--secondary,--accent,--destructive,--border,--input,--ring, chart colors, and--radius - Adjust any token to match your branding; Tailwind classes generated by Orbit will reflect these variables
- Extend component variants:
- Import
buttonVariantsandcnto compose new styles in your app - Compose new variants by calling
buttonVariants({ variant, size, className })and merge additional classes withcn(...) - Create wrappers (e.g.
PrimaryButton) that set your preferred defaults while keeping the underlying API
- Icons and animations:
- Use Lucide React icons inside Orbit components; they will be correctly sized and aligned
- Animate with
tw-animate-cssclasses to add motion; Orbit’s global CSS already imports the plugin
components/ui— ready-to-use UI components (currentlybutton.tsx)components/neoui— reserved for experimental/next-gen componentslib/utils.ts— shared utilities (e.g.,cnbased on clsx + tailwind-merge)globals.css— Tailwind v4 setup, theme tokens (OKLCH), and base layerscomponents.json— shadcn-style registry configuration and path aliasespackage.json— package metadata and dependenciestsconfig.json— TypeScript configuration (ensure build outputs are configured before publishing)
Note: Imports inside components use aliases like @/lib/utils. In a published build, ensure your bundler or build step resolves these aliases to relative paths, or add proper exports and build output.
- Add new components under
components/uiand use CVA for variants - Reuse
cnfrom@/lib/utilsto merge classes safely - Prefer Radix Slot for
asChildcomposition - Keep props typed and align with React component conventions
- Update documentation sections (Usage/Customization) when new components land
Development steps:
- Install:
pnpm install - Build: configure a build script (e.g., using tsup, build TypeScript to dist, copy CSS)
- Test locally in a consumer app via a path install or linking
Before publishing to npm:
- Add a proper build pipeline (e.g.,
tsuportsc) that emits ESM and/or CJS - Provide
exportsinpackage.jsonfor stable import paths:- Example:
./dist/index.js,./dist/components/ui/button.js, and./globals.css
- Example:
- Verify CSS is included (either copied or referenced in
files) - Ensure type declarations are emitted
- Bump
versioninpackage.jsonand publish (npm publish)
- Tailwind version? Tailwind CSS v4 is required due to
@import "tailwindcss";,@theme inline, and the custom dark variant. - Can I tree-shake? Yes, once exports are defined and builds emit ESM, bundlers will tree-shake unused components.
- Dark mode strategy? Toggle the
.darkclass on the root; Orbit’s styles respond accordingly.
ISC. See package.json for details.
- Inspired by shadcn/ui’s philosophy of building your own design system from composable primitives
- Uses Radix UI’s Slot for flexible composition
- Lucide React for icons
- Tailwind CSS for utility-first styling