π neba.cdget.com
Live previews and full props for every component. This README is just the quick start.
Neba UI is a React component library for building application interfaces. It gives you the pieces a real product needs β buttons and form fields, menus and dialogs, tables and tabs, progress and notifications β already styled, already accessible, and already agreeing with each other.
You install one package, add two lines to your CSS, and import components. There is nothing to configure, no theme object to assemble, and no per-component styling decisions to make before you can ship a screen.
- A broad component set, still growing β enough to build a whole screen without reaching elsewhere.
- One shared vocabulary β
size,color,variant,density,elevation. Anmdis the same height on every control;primaryis the same colour everywhere. - Accessible by construction β real roles, labels, focus management and keyboard support, not
divs with click handlers. - Dark mode with no work β follows the system, and can be forced either way per subtree.
- A design language, not a theme file β a translucent acrylic surface with a hairline edge, one deliberate motion signature, and shadows that are opt-in.
- ESM only, TypeScript declarations included, tree-shakeable β every component compiles to its own module.
- One runtime dependency. React 19, Node.js 18 or later.
Everything is documented at neba.cdget.com, where the previews are not screenshots β they are the components, running in the page.
| Page | What you will find |
|---|---|
| Getting started | Install and setup, end to end. |
| All components | Every component, one page each: live previews and the full props table. |
| Examples | A whole sample screen, explained block by block. |
| Design language | Why a Neba surface looks and behaves the way it does. |
| Prop conventions | The shared vocabulary every component draws from. |
| Color | The token families, and how to theme them. |
Also available in Korean / νκ΅μ΄ λ¬Έμ: neba.cdget.com/ko/
npm install nebapnpm add nebaNeba expects react and react-dom to be available in your project.
Add two lines to your app's CSS entry point:
@import 'tailwindcss';
@import 'neba/styles.css';neba/styles.css carries the design tokens and registers the package as a style source itself β so there is no @source line for you to write, and no path that depends on where your CSS file happens to sit. Utility classes come from Tailwind CSS v4, which is the only build-side requirement Neba has.
That is the whole setup. No provider is required at the root, no theme object, no config file.
Import components from the package root:
import { Button, Card, TextField } from 'neba';
export default function SignIn() {
return (
<Card>
<TextField label="Email" type="email" />
<Button onClick={submit}>Sign in</Button>
</Card>
);
}A few components provide context and are mounted once, near the root, only if you use them β ToastProvider (paired with the useToast() hook) and TooltipProvider.
The reason a Neba screen looks composed rather than assembled is that the props mean one thing across the library. They live in src/types.ts and every component draws from the same list:
| Prop | Values | What it changes |
|---|---|---|
size |
xs sm md lg xl |
The control's scale. md is the desktop default. |
color |
primary secondary success warning danger info |
The semantic colour family. |
variant |
solid outline text |
How much visual weight the surface carries. |
density |
default compact |
Padding only β never the height, never the type scale, so a compact control still lines up with a default one. |
elevation |
0 1 2 3 |
How far a surface floats off the page. 0 is the default and means no shadow at all. |
Placement props are logical, not physical β start/end rather than left/right β so layouts flip correctly under RTL. The full rules are in Prop conventions.
<Button size="sm" color="danger" variant="outline">Delete</Button>
<Chip size="sm" color="danger" variant="outline">Overdue</Chip>Inputs β Button, ButtonGroup, TextField, NumberField, Select, Combobox, Checkbox, RadioGroup, Switch, Slider, Menu (with submenus, checkbox and radio items), ContextMenu, FilePicker, Pagination
Surfaces β Box, Card, Accordion, Tabs
Display β Typography, Divider, Chip, Badge, List, Table
Feedback β Alert, Dialog, Toast, Tooltip, Overlay, ProgressLinear, ProgressCircular, ProgressBox
Recent additions: Combobox (a select you can type into and filter, single or multiple), NumberField (a numeric input with steppers, min/max clamping and a step), and Overlay (a sheet that takes the page β dim, frosted, opaque, or invisible but still blocking).
Each one has its own page β live previews, every prop, and the variations worth seeing β under All components.
Colours, radii, and surface strengths are CSS custom properties declared in the stylesheet you imported. Override any of them in your own CSS and the whole library follows:
:root {
--neba-primary-fill: oklch(0.62 0.19 265);
}Dark mode responds to prefers-color-scheme on its own. To force it, put .dark or [data-theme='dark'] (or 'light') on any ancestor β it applies to that subtree, so a dark panel on a light page is one attribute.
Adding a whole new colour family is two edits: an entry in NebaColor and five tokens; everything else derives from them.
Clone the repository and install dependencies, then:
| Command | What it does |
|---|---|
npm run docs:dev |
Starts the documentation site (docs/) locally β every component, rendered live, with HMR. |
npm test |
Runs the test suite once. |
npm run test:watch |
Runs the test suite in watch mode. |
npm run typecheck |
Type-checks the library, the tests, and the docs. |
npm run build |
Formats, compiles, and minifies the library into dist/. |
npm run lint:fix |
Runs ESLint with autofix. |
npm run format:fix |
Runs Prettier over the repository. |
All commands are run from the repository root.
src/β the library source. Each component lives insrc/components/{name}/and is re-exported fromsrc/index.ts.src/internal/β what the library shares with itself: the size and spacing tables, the surface and focus-ring generators, the icons more than one component draws. Shipped, but not part of the public API.test/β the test suite, mirroring thesrc/tree.docs/β the VitePress documentation site, in English and Korean. It renders the real components fromsrc/, so it is also where components are developed and eyeballed.
There is no separate demo app: npm run docs:dev is the develop-and-eyeball loop.
Tests run with Vitest in browser mode, against a real headless browser driven by Playwright β the components depend on browser APIs (ResizeObserver, the popover API, dialog.showModal()) that jsdom does not implement. Install the browser once before your first run:
npx playwright install chromiumnpm test uses Chromium. To run against another engine, set VITEST_BROWSER to chromium, firefox, or webkit (or a comma-separated list), having installed those browsers first:
VITEST_BROWSER=firefox npm testCI runs the suite across Linux, Windows, and macOS in all three browser engines.
Tests ship with the component they cover, in the same commit. Add a test at the path mirroring its source β src/components/button/Button.tsx is covered by test/components/button/Button.test.tsx.
Anyone can contribute to the project by reporting new issues or submitting a pull request. For more information, please see CONTRIBUTING.md.
Please see the LICENSE file for more information about project owners, usage rights, and more.