naytak-react-ui
v0.2.0
Published
Reusable React UI component library
Readme
naytak-react-ui
Reusable React component library.
Install (workspace/local)
If using npm workspaces, add this package as a dependency in your app:
{
"dependencies": {
"naytak-react-ui": "workspace:*"
}
}Or install via local path:
npm install ./packages/naytak-react-uiBuild
npm run -w packages/naytak-react-ui buildTesting
Run unit tests with Vitest:
npm run -w packages/naytak-react-ui test -- --runStories (Ladle)
Start the interactive stories:
npm run -w packages/naytak-react-ui ladleBuild static stories for preview/deploy:
npm run -w packages/naytak-react-ui ladle:buildUsage
import { Button } from "naytak-react-ui";
export default function Example() {
return (
<div>
<Button>Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
</div>
);
}Icons — thin-stroke outline
The library ships 640 SVG icons (120 each across Navigation, Actions, Status,
Media and Misc, plus 40 brand icons), each a single component rendered in a
thin-stroke outline style. Icons inherit currentColor, so they follow the
active light / dark theme automatically.
import { IconSearch, IconSun, IconBell } from "naytak-react-ui";
export default function Example() {
return (
<div style={{ display: "flex", gap: 12 }}>
<IconSearch size={24} />
<IconBell size={28} aria-label="Notifications" />
</div>
);
}If you only want icons (tree-shakable, no component styles), install the standalone package instead:
npm install naytak-react-ui-iconsimport { IconSun, IconMoon } from "naytak-react-ui-icons";ThemeProvider — dark / light mode manual
ThemeProvider turns on theming for the whole tree: it applies --naytak-*
design tokens on a scoped wrapper (and on <html> by default, so portals like
Modal / Drawer / Toast stay themed) and exposes a useTheme hook. The same
component ships standalone as naytak-react-ui-theme-provider for users who
install only individual component packages.
1. Whole package
Install the full library (already includes the theme provider + all styles):
import { ThemeProvider, useTheme, Button, Card } from "naytak-react-ui";
import "naytak-react-ui/index.css"; // once, in your app entry
function ThemeToggle() {
const { mode, toggleMode } = useTheme();
return (
<Button onClick={toggleMode}>
Switch to {mode === "dark" ? "light" : "dark"}
</Button>
);
}
export default function App() {
return (
<ThemeProvider defaultMode="dark">
<ThemeToggle />
<Card title="Hello">Themed!</Card>
</ThemeProvider>
);
}2. Individual (standalone) packages
Install only the packages you use, plus the theme provider:
npm install naytak-react-ui-theme-provider naytak-react-ui-button naytak-react-ui-cardimport { ThemeProvider, useTheme } from "naytak-react-ui-theme-provider";
import "naytak-react-ui-theme-provider/index.css";
import { Button } from "naytak-react-ui-button";
import "naytak-react-ui-button/index.css";
import { Card } from "naytak-react-ui-card";
import "naytak-react-ui-card/index.css";
function Toggle() {
const { mode, toggleMode } = useTheme();
return (
<Button onClick={toggleMode}>{mode === "dark" ? "Light" : "Dark"}</Button>
);
}
export default function App() {
return (
<ThemeProvider defaultMode="dark">
<Toggle />
<Button variant="primary">Primary</Button>
<Card title="Hello">Themed!</Card>
</ThemeProvider>
);
}How it works: every component package renders the same class names
(.btn-primary, .card, …) and the theme CSS overrides them with higher
specificity ([data-naytak-theme="dark"] .btn-primary > .btn-primary), so the
standalone theme provider themes any combination of component packages.
3. Controlling the mode
- Uncontrolled (simplest): set
defaultMode="light" | "dark"; the provider holds its own state anduseTheme().toggleMode()flips it. - Controlled: pass
mode(and optionallyonModeChange) to drive the theme from your own state — e.g. persist it inlocalStorageor a store:
const [mode, setMode] = useState<ThemeMode>("light");
<ThemeProvider mode={mode} onModeChange={setMode}>
…
</ThemeProvider>;4. Custom primary color
primaryColor re-derives the brand gradients (primary buttons, focus rings,
tabs, pagination, sliders, …):
<ThemeProvider defaultMode="light" primaryColor="#7c3aed">5. Portals & scoping
syncRoot(defaulttrue) also applies tokens +data-naytak-themeonto<html>, so portal-rendered overlays (Modal, Drawer, Toast) are themed too.- Set
syncRoot={false}to scope the theme to only the wrapper subtree — useful for theme previews or multi-theme sections.
6. Props
| Prop | Type | Default | Description |
| --------------------- | ------------------------ | ----------- | ----------------------------------------------------- |
| mode | "light" \| "dark" | – | Controlled color mode. |
| defaultMode | "light" \| "dark" | "light" | Initial mode when mode is omitted (uncontrolled). |
| primaryColor | string | "#2563eb" | Brand color used to derive component gradients. |
| tokens | Record<string, string> | – | Extra CSS custom properties to apply. |
| onModeChange | (mode) => void | – | Called whenever the mode changes. |
| syncRoot | boolean | true | Also apply tokens to <html> so portals stay themed. |
| as | React.ElementType | "div" | Wrapper element used to scope the theme. |
| className / style | – | – | Passed to the wrapper element. |
7. useTheme hook
const { mode, setMode, toggleMode, primaryColor, tokens } = useTheme();Content (with fluid option)
Content wraps page content using the internal Container. Use fluid to span full width, or omit for a centered max-width layout.
import { Content } from "naytak-react-ui";
export default function Page() {
return (
<>
{/* Default: centered content with max-width */}
<Content>
<h1>Page Title</h1>
<p>This area is constrained to a readable max width.</p>
</Content>
{/* Fluid: full-width content */}
<Content fluid>
<h2>Full Width Section</h2>
<p>This section spans the entire viewport width.</p>
</Content>
</>
);
}Container (direct usage)
Use Container to wrap any content. By default it centers content with a max-width; set fluid to span full width.
import { Grid, GridItem } from "naytak-react-ui";
export default function Sections() {
return (
<>
{/* Default: centered with max-width */}
<Grid container>
<GridItem xs={12} md={2} lg={2} spacing={0.5}>
<h2>Constrained Section</h2>
<p>Centered with a readable maximum width.</p>
</GridItem>
</Grid>
{/* Fluid: full-width */}
<Grid container fluid>
<GridItem xs={12} md={2} lg={2} spacing={0.5}>
<h2>Full Width Banner</h2>
<p>Stretches across the entire viewport.</p>
</GridItem>
</Grid>
</>
);
}CSS
Import the library’s bundled styles once in your app. Choose either export:
// Preferred consolidated CSS
import "naytak-react-ui/index.css";
// Compatibility alias (same content)
import "naytak-react-ui/styles.css";Component-level CSS is bundled via the library entry, so a single import is sufficient.
Publish
- Update
versionin the package. - Ensure
peerDependenciesforreactandreact-dommatch your target versions. - Run
npm publish --access publicfrompackages/naytak-react-ui.
