SakaniUI
An open-source, token-driven React component library for SaaS products — 1,500+ accessible components and variants, built 1:1 from a Figma design system, across light and dark modes, with built-in glass and Apple-style liquid glass surfaces.
Live Storybook → · Figma file →
Why SakaniUI
Most component libraries start in code and retrofit the design. SakaniUI was built the other way: every component is designed first in Figma with a strict three-layer token architecture, then implemented 1:1 in React — same variants, same states, same tokens. The Figma file has grown into a 1,500+ component-and-variant system across light and dark mode; the React library mirrors it component by component, with new ones landing as they're built out.
- Token-driven — components bind only to semantic tokens (
bg/surface,fg/muted,accent/default…), so the entire library re-themes from one place - Light & dark mode — add the
.darkclass to any container; every component re-themes automatically, no per-component dark styles - Glass & liquid glass — a third theme axis, Surface (Solid · Glass · Liquid): frosted glassmorphism and Apple-style liquid glass with real lens refraction, switched per area with one attribute — see Glass & liquid glass
- Accessible by default — WCAG AA contrast audited, global focus-ring system,
prefers-reduced-motionsupport, full ARIA semantics (combobox active-descendant, calendar date labels, live-region toasts, focus-return popovers) - Typed & composable — strict TypeScript, generic
Table<T>, slot-based composition, controlled + uncontrolled patterns - Geist typography and Tabler Icons (5,184 outline + 1,054 filled), matching the Figma source exactly
Icons
The icon set is Tabler Icons: 5,184 outline icons and 1,054 filled ones, the same as the Figma ↳ Icons (Tabler) page. One component per icon, tree-shaken individually:
import { IconHome, IconBell, IconHeartFilled } from '@sakaniui/react/icons'; <IconHome /> {/* 24px, 1.5 stroke, currentColor */} <IconBell size={20} /> <IconHeartFilled color="#e11d48" />
Names follow Tabler (IconName / IconNameFilled), so tabler.io/icons is the search. Props follow
lucide-react (size, color, strokeWidth), and every component prop that takes an icon still
accepts Lucide or Tabler React icons. See THIRD_PARTY_NOTICES.md for the MIT licence.
Install
npm install @sakaniui/react
Then import the tokens once at your app's entry point, and any component from the package root:
import '@sakaniui/react/tokens.css';
Building with AI?
AGENTS.md(shipped in this package) explains why components behave as they do and what to do when nothing fits. Index for agents: https://www.sakaniui.com/llms.txt
Quick start (contributing / browsing the source)
git clone https://github.com/samzydd/Sakaniui.git
cd Sakaniui
npm install
npm run storybookStorybook opens at http://localhost:6006 with every component, all variants, and dark-mode stories.
Usage
Import the tokens once, then use any component from @sakaniui/react:
import '@sakaniui/react/tokens.css'; import { Button, StatCard } from '@sakaniui/react'; import { IconCurrencyDollar } from '@sakaniui/react/icons'; export const Dashboard = () => ( <> <StatCard variant="icon" icon={IconCurrencyDollar} title="Revenue" value="$48,120" delta="+12.5%" trend="up" sparkline={[12, 18, 14, 22, 19, 28]} /> <Button variant="primary" size="md">Get started</Button> </> );
Dark mode
<div className="dark"> {/* everything inside re-themes automatically */} </div>
Glass & liquid glass
Glass is built into the theme system, not added component by component. Next to light/dark, SakaniUI has a second axis — Surface — with three modes: Solid (the default), Glass (frosted translucency) and Liquid (Apple-style liquid glass: the backdrop bends at the edges like a lens, with a faint color fringe, rim light and depth). Components read a small set of --surface-* tokens, so switching an area from Solid to Glass or Liquid re-themes everything inside it at once — in the Figma file (variable modes and effect styles) and in code. Solid stays pixel-identical to before.
// Frosted glass: one attribute on any ancestor (works in light and dark) <div data-surface="glass"> <Sidebar /> <Card>…</Card> </div> // Liquid glass: a lens-refracting sheet over a photo, UI on top import { LiquidBackdrop, LiquidGlass } from '@sakaniui/react'; <LiquidBackdrop src="photo.jpg" style={{ position: 'relative' }}> {/* every lens refracts this photo */} <LiquidGlass variant="regular" tint="subtle" radius={0} style={{ position: 'absolute', inset: 0 }} /> <div data-surface="liquid" style={{ position: 'relative' }}> <Sidebar /> {/* transparent: sits on the glass */} <div data-surface="solid"><Card>…</Card></div> {/* data stays solid and crisp */} </div> </LiquidBackdrop>
The recipe is always the same three layers: photo → one glass overlay → components. Inside a LiquidBackdrop, every lens refracts the sharp photo itself (as Figma's glass does), so glass on glass still bends real detail with visible color fringing. See the full Liquid Glass Dashboard block (@sakaniui/react/blocks) for a complete example: lenses that spring between sidebar items and stretch like a droplet, a collapsible rail with tooltips, frosted menus, solid data cards on a glass panel, and a layout that reflows to its container.
Liquid Glass in 5 minutes
1. Install and import the styles once (see Install): @sakaniui/react/tokens.css and @sakaniui/react/style.css.
2. Put your photo in a LiquidBackdrop. Give it a size; the photo is cover-fitted. Pick imagery with color and detail, since glass has nothing to bend over a flat color.
3. Add glass on top. Anything inside the backdrop can be a lens:
import { LiquidBackdrop, LiquidGlass, Button } from '@sakaniui/react'; export function Hero() { return ( <LiquidBackdrop src="/photo.jpg" style={{ position: 'relative', height: 480 }}> {/* a card of glass: clear = see-through, regular = carries text */} <LiquidGlass variant="regular" radius={28} style={{ position: 'absolute', left: 48, top: 48, width: 340, padding: 24 }}> <h2>Glass that bends light</h2> <p>Components inside sit on the glass with no fills of their own.</p> <Button>Get started</Button> </LiquidGlass> {/* a floating pill that squishes when pressed */} <LiquidGlass variant="clear" radius={999} interactive style={{ position: 'absolute', right: 48, bottom: 48, padding: '12px 20px', color: '#fff' }}> Explore </LiquidGlass> </LiquidBackdrop> ); }
4. Tune it with Figma's own properties. The defaults are Figma's liquid/regular and liquid/clear effect styles. Change any of them for one element:
<LiquidGlass variant="clear" effect={{ refraction: 1, depth: 40, dispersion: 0.7, frost: 0 }} radius={999} />
5. Check it in dark mode and Safari. Wrap a container in .dark to see the dark tint. In Safari and Firefox you'll see the frosted fallback; add refraction="off" to preview it in Chrome. Browse every property live in Storybook: Foundations → Liquid Glass → Playground.
- Browsers — refraction renders in Chromium (Chrome, Edge, Arc); Safari and Firefox get a frosted fallback with the same rim.
- Fast — big static lenses (overlays, panels) render their glass once into a canvas and stay at 60fps; small moving lenses stay live (
bake={false}keeps a big moving lens live). - Accessible —
prefers-reduced-transparencyturns glass into an opaque surface,prefers-reduced-motionstops the glare and glide; secondary text has its own stronger color token on glass, and the docs list measured contrast for every tint. - Figma's Glass properties, 1:1 — refraction, depth, dispersion, frost and light are tokens in Figma's own units (
--liquid-refraction-clear: 0.8,--liquid-depth-clear: 20, …), matching the liquid/regular and liquid/clear effect styles, or per element:<LiquidGlass effect={{ refraction: 0.8, depth: 20 }}>.tint="subtle"is Figma's 5% overlay fill, anddata-on-photoswitches a subtree to light text.
Docs: sakaniui.com/docs/glass · Storybook: Foundations → Liquid Glass (Showcase, Dark, Playground with Figma's Glass properties as controls) and Foundations → Glass.
Token architecture
Three layers, defined in Figma and exported to tokens.css:
- Primitives — raw scales (
neutral/50–950,primary/…, spacing, radii) - Semantic — purpose-named aliases that flip between light and dark (
bg/surface,fg/default,border/subtle,accent/default,chart/1–5) - Components — bind only to semantic tokens, never to primitives
Change a semantic token and every component follows — in both the design file and the code.
Components (114+, syncing toward Figma's 1,500+)
Core — Button · Icon Button · Badge · Label · Divider · Link · Kbd · Spinner · Skeleton · Progress · Tooltip · Avatar · Avatar Group
Forms — Input · Textarea · Select · Checkbox · Radio · Switch · Slider · Combobox (single/multi, async loading) · File Upload
Composite — Card · Alert · Toast · Accordion · Tabs · Breadcrumb · Table (generic, selectable) · Stat Card (sparklines) · Stepper · Calendar (single + range, dropdown navigation) · Pagination · Popover · Segmented Control · List Item
Sidebar kit — Sidebar · Header · Search · Item · Sub Item · Group Label · Divider · Promo · Footer — nine standalone parts that compose into full navigation
Navigation — Top Bar · Top Bar (mobile)
Overlays — Menu · Menu Item
Glass — Liquid Glass (LiquidGlass, LiquidBackdrop, useLiquidGlass) · Surface modes (data-surface="glass" | "liquid" | "solid")
Data — Empty State · Filter Chip
Charts — Area · Bar · Donut · Funnel · Heatmap · Line · Pie · Radar · Radial — Recharts wrappers styled entirely with the chart/1–6 tokens
Chat — Chat Composer · Conversation Item · Message Bubble
Application — Activity Feed · Announcement · Avatar Upload · Balance · Code Snippet · Expenses · Inline Hint · Modal · Notification Item · Progress Item · Progress Stat · Rich Separator · Spending Balance · Stock Market · Tags · Ticker · Transactions
E-commerce — Cart Item · Checkout Steps · Color Swatch · Price Display · Product Card · Product Gallery · Quantity Selector · Size Selector · Star Rating · Stock Status · Wishlist Button
Marketing — Blog Blockquote · Blog Feature Text · Blog Image · Blog Listing Card · Blog Listing Featured Card · Featured Icon · First Page Heading · Job Listing · List · Location Dot · Marquee · Metric · Mobile Navigation Menu · Placeholder Logo · Profile Card · Rich Text Heading · Rich Text Paragraph · Section Heading · Sub Feature · Team Card
Blocks (42)
Blocks are full sections assembled from SakaniUI components — composition examples, not fully-configurable components like the ones above. Most ship with realistic sample data and manage their own demo state internally (a state prop just switches between the states each one ships with — loading, empty, error, and so on). They're meant as a working starting point you customize, not a drop-in you configure entirely through props.
They live in src/blocks, and are also published separately from the main package at @sakaniui/react/blocks — kept out of the main entry point on purpose, so importing them is a deliberate choice:
npm install @sakaniui/react
import { DataTableBlock } from '@sakaniui/react/blocks'; <DataTableBlock />
To actually customize one, copy its source file straight from GitHub instead and edit it directly — that's still the intended workflow for anything beyond the states it ships with:
// src/blocks/DataTableBlock/DataTableBlock.tsx, copied into your project import { DataTableBlock } from './DataTableBlock'; // Swap the sample data for your own, edit the columns. <DataTableBlock />
Application (14) — Account Overview · Activity Log · App Header · CRM Dashboard · Liquid Glass Dashboard · Data Table + Toolbar · File Upload Panel · Form Modal · Inline CTA · Multistep Modal · Notification Panel · Onboarding Progress · Profile Settings · Section Footer
Authentication (6) — Email Verification · Forgot Password · Login · Reset Password · Sign Up · Two-Factor Authentication
Billing (5) — Add Card Form · Billing Address · Billing History · Current Plan · Payment Method
E-commerce (5) — Checkout Flow · Order Confirmation · Product Detail · Product Grid · Shopping Cart
Marketing (10) — Blog Listing · Careers · CTA Banner · FAQ · Feature Grid · Hero · Logo Cloud · Pricing Table · Team Section · Testimonial
Chat (1) — Desktop Chat Interface
Data & Content (1) — Kanban Board
Browse every block and state in the live Storybook under Blocks.
Accessibility
The library ships with an audited AA baseline: contrast-checked token pairs in both modes, a global token-driven focus ring on every interactive element, reduced-motion support, Escape-dismissible tooltips, screen-reader-tracked combobox options, full-date calendar labels, assertive error toasts, and focus-returning popovers. See the Storybook docs tab on each component for its ARIA contract.
Roadmap
- npm package (
@sakaniui/react) - Figma Community publication
- Theming CLI (custom brand token generation)
- Vue port
Support
If SakaniUI is useful to you, you can tip the creator. It funds the time that keeps the system maintained and growing.
Author
Sam Okpere — senior UI/UX & design systems designer
Portfolio · Dribbble · LinkedIn · GitHub
License
MIT — free for personal and commercial use. If SakaniUI saves you time, a star ⭐ helps others find it.