Installation
Install the package, import the stylesheet once, and wrap your app in FujiProvider. That is the whole setup; the guides below cover framework-specific entry points and styling details.
1. Install
npm install @fujiui/react2. Import styles and wrap your app
Import the stylesheet once at the top of your tree, then render everything inside one provider.
// app entry (layout, main, or root component)
import "@fujiui/react/styles.css";
import { FujiProvider, Button } from "@fujiui/react";
export default function App() {
return (
<FujiProvider defaultTheme="light" defaultRadius="cornered">
<Button tone="forest">Save changes</Button>
</FujiProvider>
);
}Guides
Peer dependencies and browser support
No other runtime dependencies - Base UI, class-variance-authority, clsx, and tailwind-merge are bundled, not peer dependencies you need to install yourself.
SSR, hydration, and Server Components
Every component renders identically on the server and client, so plain SSR/SSG works with no special setup. A Server Component may render a client compound as JSX (<Dialog>...</Dialog>) but must not access a static property on it (Dialog.Content) - import the named sub-export instead, or move that section behind a "use client" boundary. See Troubleshooting below for the exact error this produces.
Form validation with React Hook Form
Fuji form controls are plain controlled components (value / onChange), so they wire into React Hook Form's Controller the same way any custom input does.
Testing
Fuji doesn't ship a dedicated testing package. Components use real semantic HTML and standard ARIA roles/labels (buttons, dialogs, listboxes, etc.), so they work directly with role- and label-based queries in Testing Library (getByRole, getByLabelText) without needing custom test IDs.
Troubleshooting
Components render with no styling at all.
Cause: The stylesheet import (`import "@fujiui/react/styles.css"`) is missing or loaded after component CSS.
Fix: Import the stylesheet once, as early as possible in your entry file - before any of your own global CSS that might otherwise win the cascade.
The page flashes the wrong theme for a moment on load or refresh.
Cause: The provider mounted with its default theme before your persisted/preferred value was read.
Fix: Pass `persist` on the root `FujiProvider` so it reads the saved preference before first paint. For a Next.js app-shell, apply the persisted value with a small pre-hydration script in `<head>` (see this site's own `layout.tsx` for the pattern).
Build error: "Element type is invalid" when accessing e.g. `Dialog.Content` from a Server Component.
Cause: A Server Component did a static property access (Dialog.Content) on a client-compound import - Next.js replaces "use client" module exports with opaque client references that don't carry extra static properties.
Fix: Import the named sub-export directly (`import { DialogContent } from "@fujiui/react"`) or move that section behind a `"use client"` boundary.
React hydration mismatch warning involving a component that shows a date or "today".
Cause: Passing a raw `new Date()` computed during server render, which differs from the client's local time zone.
Fix: Compute a UTC-normalized date for the initial render (see the Calendar docs for the exact pattern) and correct to the visitor's local date in an effect after mount.
A Fuji class you added dynamically (e.g. building a className string at runtime) has no effect.
Cause: Tailwind's static scanner can't see class names that only exist at runtime as a concatenated string.
Fix: Use complete, literal class name strings (or the cn() helper with literal branches) so Tailwind's scanner can find them at build time.
