# @arkite-ui/core v0.23.1 > React components for multi-tenant SaaS admin panels. Tailwind CSS v4 + > Radix UI + TypeScript. Pure UI only: no business logic, auth, stores, or > routing — data comes in via props, events go out via callbacks. > > Arkite UI is an open-source project by Foson (https://foson.co), a Taiwan-based > software company. Docs: https://ui.foson.co · Repo: https://github.com/foson-co/arkite-ui > Not affiliated with Arkite NV (arkite.com, industrial operator guidance). ## Setup ```bash pnpm add @arkite-ui/core # peer deps: react react-dom tailwindcss zustand lucide-react # optional: framer-motion (Animated* variants) ``` ```css /* app.css — Tailwind v4, tokens included */ @import "tailwindcss"; @import "@arkite-ui/core/styles.css"; ``` ## Rules for generated code 1. Import UI from `@arkite-ui/core` — never rebuild primitives that exist (see inventory below). 2. Use semantic token utilities only (`bg-card`, `text-muted-foreground`, `border-border`) — never raw palette classes (`bg-red-50`), never `dark:` color overrides (tokens handle dark mode), never arbitrary values (`text-[13px]`). 3. Components follow the controlled/uncontrolled React convention: `value`+`onChange` controls, `defaultValue` doesn't. 4. Keep API calls, routes, and business models in the app layer. 5. Building a whole page? Match it against the recipes below **before** assembling one from scratch, then **install it instead of writing it**: `npx arkite-ui add ` writes the tested composition into the project (`--out`, `--name`, `--force`), leaving you only the sample data and API calls to replace. Generating the wiring by hand is the step that introduces bugs the recipe already solved. Full design rules (color/spacing/typography/layout recipes): DESIGN.md, shipped inside this package — also embedded in llms-full.txt. ## Core patterns ### Server-paginated table `useServerTable` owns the six controlled props server mode needs; you supply `data` + `totalRows` and fetch on `queryKey`: ```tsx import { DataTable, useServerTable, type Column } from '@arkite-ui/core' const table = useServerTable({ initialPageSize: 20 }) const [page, setPage] = useState({ items: [], total: 0 }) useEffect(() => { fetchUsers(table.query).then(setPage) // query = { page, pageSize, sort, filters } }, [table.queryKey]) r.id} {...table.props} /> ``` Client-side tables need none of that: pass `data` and the table filters, sorts, and paginates itself. ### Toasts ```tsx import { useToast, ToastContainer } from '@arkite-ui/core' // once, near the app root: const toast = useToast() toast.success('Saved', { description: 'Changes are live.' }) // error handling in catch blocks — wire the app's parser once at startup: toast.configure({ formatError: getErrorMessage }) // then every call site is one line (title = prefix, description = parsed message): catch (err) { toast.fromError(err, { prefix: 'Failed to save' }) } ``` ### Theming ```tsx import { createTheme, applyTheme } from '@arkite-ui/core' applyTheme(createTheme({ primary: '#7c3aed' })) // HSL tokens from one hex ``` A project's brand belongs in a committed `arkite.theme.json` (`{ name, primary, accent, radius }`) rather than hand-copied CSS variables. Generate the CSS from it with `npx arkite-ui theme apply`, or in-process via `themeFileToCSS(parseThemeFile(json))` from `@arkite-ui/core/theme` — a server-safe entry that loads no components. `parseThemeFile` rejects malformed hex and unknown keys, which `createTheme` alone would pass through as `NaN` tokens. ## Recipes — page-level compositions Whole pages assembled from the library, each one rendered and tested in CI. Machine-readable index: registry.json (ships in the package). Install one with `npx arkite-ui add ` — do not retype it. ### crud-list-page — CRUD List Page Search + filters over a sortable, selectable, paginated table, with bulk actions and a guarded destructive path. - Use when: A list page whose rows are already in memory and the page needs filtering, sorting, multi-select, bulk actions, or a delete confirmation. - Not when: The server does the filtering/sorting/slicing — use `server-side-table`. A read-only handful of rows with no interaction — use `Table` directly, no recipe needed. - Composes: Badge, BulkActionBar, Button, DataTable, DeleteConfirmDialog, FilterBar, FilterBarActions, FilterBarFilters, FilterBarSearch, FilterSelect, PageHeader, ToastContainer, toast - Source (ships in the package, copy it): src/stories/recipes/CrudListPage.demo.tsx — docs: https://ui.foson.co/?path=/docs/recipes-crud-list-page--docs ### server-side-table — Server-Side Table A table whose sorting and pagination round-trip to the server: the page owns the query state, the API returns one slice plus a total. - Use when: The API returns one pre-sorted page plus a total count, so the table can never know the full ordering — sorting and pagination must be controlled. - Not when: All rows fit in memory — leave the table uncontrolled and use `crud-list-page`. - Composes: Badge, DataTable, PageHeader, useServerTable - Source (ships in the package, copy it): src/stories/recipes/ServerSideTable.demo.tsx — docs: https://ui.foson.co/?path=/docs/recipes-server-side-table--docs ### dashboard-page — Dashboard A KPI row over compact widget cards — sparkline trends and a recent-activity table in one responsive grid. - Use when: An overview page that answers 'is everything okay?' at a glance and links out for detail. - Not when: The page IS the detail view, or the numbers need drill-down in place — build a list or detail page instead. Full charting belongs in a dedicated chart library, not `Sparkline`. - Composes: Badge, Card, CardContent, CardHeader, DataTable, PageHeader, Sparkline, StatCard, StatGroup - Source (ships in the package, copy it): src/stories/recipes/DashboardPage.demo.tsx — docs: https://ui.foson.co/?path=/docs/recipes-dashboard--docs ### detail-drawer-page — Detail + Drawer Edit A record's read view with an edit drawer, a dirty-close guard, and a confirmed destructive action. - Use when: Editing a record while the user still needs the record on screen for reference. - Not when: The edit should interrupt and take over (short one-shot forms, confirmations) — use `Modal`. A full create/edit page with many sections — use `form-page`. - Composes: Badge, Button, Card, ConfirmDialog, DescriptionItem, DescriptionList, Drawer, Form, FormActions, FormControl, FormField, FormLabel, FormMessage, Input, PageHeader, Textarea, ToastContainer, toast - Source (ships in the package, copy it): src/stories/recipes/DetailDrawerPage.demo.tsx — docs: https://ui.foson.co/?path=/docs/recipes-detail-drawer-edit--docs ### form-page — Form Page A sectioned create/edit page: grouped fields, mixed control types, submit-time validation, and a guarded submit. - Use when: A create or edit page big enough to need sections, help text, and inline validation messages. - Not when: The form is short enough to live in a drawer next to a read view — use `detail-drawer-page`. - Composes: Button, Form, FormActions, FormControl, FormDescription, FormField, FormLabel, FormMessage, FormSection, Input, PageHeader, Select, Switch, Textarea, ToastContainer, toast - Source (ships in the package, copy it): src/stories/recipes/FormPage.demo.tsx — docs: https://ui.foson.co/?path=/docs/recipes-form-page--docs ### tenant-admin-shell — Tenant Admin Shell The app frame: localized AdminLayout with permission-aware navigation, the signed-in user, and a tenant switcher. - Use when: Starting a multi-tenant admin app — this is the outermost shell every page renders inside. - Not when: A single-tenant app with no tenant scope — use `AdminLayout` without `TenantSwitcher`. - Composes: AdminLayout, Card, CardContent, CardHeader, DescriptionItem, DescriptionList, LocaleProvider, SegmentedControl, TenantSwitcher, toast, zhTW - Source (ships in the package, copy it): src/stories/recipes/TenantAdminShell.demo.tsx — docs: https://ui.foson.co/?path=/docs/recipes-tenant-admin-shell--docs ## Export inventory Components: ActionButtons, AdminLayout, Alert, Avatar, AvatarGroup, Badge, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbItemComponent, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbRoot, BreadcrumbSeparator, BulkActionBar, Button, Calendar, Card, CardContent, CardField, CardFooter, CardGrid, CardHeader, CardSurfaceContext, Checkbox, CheckboxCard, CircularProgress, CollapsibleSection, ColorPicker, Combobox, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ConfirmDialog, Container, CopyButton, CopyInput, DataTable, DatePicker, DateRangePicker, DeleteConfirmDialog, DescriptionItem, DescriptionList, Divider, Drawer, DrawerBody, DrawerFooter, DrawerHeader, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorBoundary, ErrorState, FileTrigger, FileUpload, FileUploadButton, FilterBar, FilterBarActions, FilterBarFilters, FilterBarGroup, FilterBarSearch, FilterSelect, FilterToolbarContext, Form, FormActions, FormControl, FormDescription, FormField, FormLabel, FormMessage, FormSection, HStack, ImageUpload, ImperativeToastContainer, InfiniteScroll, InlineCode, Input, Kbd, Label, LoadingOverlay, LocaleProvider, Modal, ModalBody, ModalFooter, ModalHeader, Navbar, NavbarBrand, NavbarContent, NavbarDivider, NavbarItem, NavbarLink, NavbarSpacer, NoData, NoResults, NumberInput, PageHeader, Pagination, PasswordInput, PinInput, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverTrigger, Progress, Radio, RadioGroup, ScrollFade, SearchInput, SegmentedControl, Select, SheetSelect, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarHeader, SidebarItem, SidebarToggle, SimpleTooltip, Skeleton, SkeletonAvatar, SkeletonCard, SkeletonTable, SkeletonText, Sparkline, Spinner, Stack, Stat, StatCard, StatGroup, StatusDot, Steps, Switch, Table, TableBody, TableCaption, TableCell, TableEmpty, TableFooter, TableHead, TableHeader, TableLoading, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TagInput, TenantSwitcher, Textarea, ThemeFileError, Timeline, Toast, ToastContainer, Toggle, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Tree, VStack, ViewToggle, VirtualList Hooks: useCommandPalette, useFormContext, useFormFieldContext, useLocale, useServerTable, useSidebar, useToast, useToastStore Utilities: applyDarkTheme, applyTheme, chartColorList, chartColors, cn, createTheme, defaultTheme, enUS, forestTheme, neutralTheme, oceanTheme, parseThemeFile, themeFileToCSS, themePresets, themeToCSS, toast, zhTW Full typed signatures for every export: llms-full.txt (or api-report.txt in the repo).