Component API
Fuji's components share one set of conventions, so learning one component teaches you most of the rest. This page covers the shared props, the compound-component pattern, and the three layers of customization.
Shared props
Every applicable component accepts the same three props, with the same defaults. tone below is for purely decorative color choices (Button, Badge, Icon); components whose value carries meaning (Alert, Toast, Result, Progress) use a separate variant prop instead, with values default · success · warning · danger · info - see Theming for the full distinction.
appearance, not type
Visual style is controlled by appearance specifically so the native HTML type attribute stays free for its real purpose:
<Button type="submit" tone="forest" appearance="contained">
Approve
</Button>What every applicable component supports
- Native HTML props and ref forwarding
classNameon the root, andclassNamesfor named internal slots where more than one visual part exists- A controlled and uncontrolled pair with a change callback, named for what the component holds:
value/defaultValuefor inputs,open/defaultOpenwithonOpenChangefor overlays, and specific names elsewhere (Paginationpage, StepperactiveStep). Each component page documents its own - Disabled, loading, invalid, read-only, and selected states
- Visible focus (
:focus-visible), accessible labels, and full keyboard operability
Compound components over prop explosion
Components with multiple visual parts (Card, Dialog, Table, Select) expose those parts as compound sub-components rather than a single component with a dozen slot props:
<Card>
<Card.Header>
<Card.Title>Plan</Card.Title>
</Card.Header>
<Card.Content>...</Card.Content>
</Card>The default and contained combination adapts automatically per theme (black on light, warm off-white on dark, frosted high contrast on glass) through semantic tokens; components never branch on the active theme in JavaScript.
Customization
Three layers, in order of how often you reach for them.
1. className
Every component accepts className on its root, merged with tailwind-merge so conflicting utilities (for example your own rounded-full overriding the default control radius) resolve predictably instead of duplicating.
<Button className="w-full rounded-full">Continue</Button>2. classNames (named slots)
Components with more than one visually distinct part expose those parts directly as compound sub-components you can pass className to individually, rather than a single flat classNames map; this keeps the JSX legible for deeply nested overlays.
3. Tokens
For changes that should apply everywhere (a different accent, a tighter shadow), override the --fuji-* custom properties in your own CSS rather than overriding classes per instance. Every component reads the same variables, so a token change is a one-place edit that cascades everywhere.
/* your app stylesheet, loaded after @fujiui/react/styles.css */
:root {
--fuji-default: #1c1b19;
--fuji-radius-control: 10px;
}