@owodesign/owoui
v0.1.12
Published
Reusable React UI foundation components and theme presets.
Maintainers
Readme
owoui
Reusable UI foundation components and default style preset.
Usage
import '@owodesign/owoui/style.css';
import { Button, Dialog, Select } from '@owodesign/owoui';Example advanced primitives:
import {
NavRail,
Popover,
RadioGroup,
Table,
Tree,
} from '@owodesign/owoui';style.css is a compiled, publish-ready CSS asset. Consumers do not need Tailwind or a Tailwind PostCSS plugin to resolve it. It ships the component bundle together with theme-light + preset-default, so the full ref -> sys -> cmp token chain is present even when consumers only import one file.
To opt into another combination:
import '@owodesign/owoui/style.css';
import '@owodesign/owoui/theme-dark.css';
import '@owodesign/owoui/preset-glass.css';Override order is intentional:
style.cssestablishes the default baseline (theme-light + preset-default)- later theme imports replace the theme layer
- later preset imports replace the preset layer
This package ships:
- reusable React UI primitives
- form primitives including
Checkbox,Radio/RadioGroup,Select,SegmentedControl,Switch,Input, andTextarea - structural primitives including
Tree,NavRail,Table,Panel,Drawer, andSidePanel - floating / feedback primitives including
Popover,Tooltip,Dialog, andToast - a default style preset
- a standalone token stylesheet via
@owodesign/owoui/tokens.css - token metadata via
@owodesign/owoui/tokens - data-state hooks on complex components
- component-level customization surfaces for complex widgets
- a packaged storybook registry consumable via
@owodesign/owoui/storybook - a static storybook catalog consumable via
@owodesign/owoui/storybook/catalog
Component Notes
Checkboxexposes a stable three-state visual contract viadata-state="unchecked" | "checked" | "indeterminate"on the root and control nodes.RadioGroupshares theChoiceOption<T>model used bySelectandSegmentedControl, supportsorientation="vertical" | "horizontal"plustextValuefor non-string labels, and exposes stableradio/radio-grouppart selectors.Popoveruses a compound API:Popover.Root,Popover.Trigger, andPopover.Content.Popover.Contentsupportsside,align,alignOffset,matchTriggerWidth,closeOnInteractOutside,closeOnEscape,closeOnPointerDownOutside,restoreFocus,initialFocusRef,onInteractOutside,onPointerDownOutside, andonEscapeKeyDown.Collapsibleis the neutral disclosure primitive.Collapsible.Contentdefaults tounmountOnExit={true}, removes closed content from the tab order during collapse, and restores focus to the trigger if closing happens while a descendant is focused.CollapsiblePanelis the public styled layer and uses a compoundHeader / Title / Actions / Chevron / ContentAPI. Settings / FAQ variants remain package-owned recipe patterns in Storybook rather than stable public exports.SidePanelis a layout component for left/right docked workbench panels rather than an overlay drawer. It supports controlled or uncontrolled collapse viacollapsed,defaultCollapsed, andonCollapsedChange, built-in handle variants viahandleVariant="tab" | "rail"withtabas the default, optional width resizing viaresizable,width,defaultWidth,minWidth,maxWidth, andonWidthChange, opt-in width persistence viapersistenceKey+persistenceMode="opt-in", viewport responsive behavior viaresponsiveMode+collapseBreakpoint, resize accessibility text viagetResizeValueText, and workbench coordination hooks vialayoutId,panelId,onResizeStart,onResizeEnd,onCollapseStart, andonCollapseEnd. It keeps a built-in collapse handle plus an optional dedicated resize handle, and exposes stablehandle | resize-handle | panel | header | contentpart selectors.Treenow renders semantic nestedtreeitem -> groupstructure, uses dedicated expand controls instead of coupling row click with expansion, supportsselectionMode="single" | "multiple" | "none", controlledselectedKeys, controlledexpandedKeys,searchQueryfiltering, andtextValuefor search on non-string labels.Treeexposes stableitem | row | expander | expanderPlaceholder | content | label | description | meta | actions | grouppart selectors instead of the previous button-centric contract.NavRailprovidesNavRail.Item,NavRail.Section, andNavRail.Spacerfor grouped icon-only navigation, plusorientation="vertical" | "horizontal"and arrow-key roving focus.TablesupportsselectionMode, controlled or uncontrolled sorting, sticky headers, fixed-row-height virtualization viavirtualized,renderHeader,renderCell,compare,isRowSelectable,loading,loadingState,skeletonRows,classNames.row | rowSelected | headerCell | headerSortButton | headerLabel | cell | selectionCell | selectionControl | loadingState | skeletonCell,sortCycle,getSortButtonAriaLabel,getRowPropsfor safe row-level attribute/style/event injection with defensive merging, androwComponentfor constrained shell replacement (animation, drag-and-drop) with mandatorydomProps/innerReftransparency.Selectsupports controlled value plus controlled popup state viaopen,defaultOpen, andonOpenChange.Tabledefaults to a documented binary sorting cycle on sortable columns:none -> asc -> desc -> asc. SetsortCycle="ternary"to enablenone -> asc -> desc -> none.TableexposesonSortChange(sort)for explicit sort-state synchronization, including ternary clear-to-none transitions. Only sortable headers render an interactive button; static headers stay non-focusable.Tableselection can be labeled explicitly throughselectionColumnAriaLabel,getSelectAllAriaLabel, andgetRowSelectionAriaLabelso standalone selection columns do not rely on implicit fallback copy.
Token Exports
For CSS-only token consumption:
import '@owodesign/owoui/tokens.css';For programmatic token metadata:
import { tokenGroups, semanticTokenKeys, themeNames, presetNames } from '@owodesign/owoui/tokens';Themes
@owodesign/owoui/theme-light.css@owodesign/owoui/theme-dark.css
If you import theme-light.css after style.css, it is effectively a no-op because style.css already includes the same theme baseline.
Presets
@owodesign/owoui/preset-default.css: Signature Look based on qblog's current default preset qualities@owodesign/owoui/preset-flat.css: low-depth preset with minimal shadows@owodesign/owoui/preset-elevated.css: stronger depth and larger radii@owodesign/owoui/preset-glass.css: translucent surfaces with blur
If you import preset-default.css after style.css, it is effectively a no-op because style.css already includes the default preset baseline.
There is no backward-compat alias layer for the previous dark.css / flat.css / elevated.css / glass.css entrypoints.
Storybook Artifact
owoui also ships a packaged storybook registry entry:
import { storybookStoryPaths, getStoriesByGroupAndComponent } from '@owodesign/owoui/storybook';This is intended for host apps that want to mount the package stories under their own route shell.
For host apps that prefer a static navigation/catalog artifact, owoui also ships:
import storybookCatalog from '@owodesign/owoui/storybook/catalog';It also builds a standalone static storybook site into dist/storybook-static/, which can be deployed directly or mounted by a host app as static files.
For package-local development with HMR, run:
npm run dev:storybookThe dev host lives inside this package itself (vite.config.ts, postcss.config.mjs, index.html) and does not depend on qblog's app shell.
Specs
- collapsible-layering-and-patterns.md: layering rules and official pattern boundaries for
Collapsible,CollapsiblePanel, and package-owned settings / FAQ recipes - form-control-boundaries.md: design and architecture boundaries for
Field,Input,Textarea, andSelect - side-panel-layout-boundaries.md: long-term boundaries and public contract for the
SidePanellayout component - token-layering-and-naming.md: raw / alias / semantic token layering and naming rules
- token-naming-upgrade-plan.md:
--owo-ref-*/--owo-sys-*/--owo-cmp-*naming migration plan
Pitches
- future-data-density-plan.md: phased proposal for control height tokens and future
data-densitysupport - side-panel-handle-placement-implemented-2026-04.md: archived delivery record for the formal
SidePanelhandle placement contract - virtual-list-industrial-design.md: proposal for introducing
VirtualListas a dedicated primitive instead of merging virtualization intoSidePanel - side-panel-layout-component.md: implemented layout-side-panel design and delivery baseline
- side-panel-resizable-phase2.md: phase-2 review for whether
SidePanelshould gain a resizable width contract - 03-side-panel-phase3-industrialization-implemented-2026-04.md: archived phase-3 delivery record for persistence, responsive behavior, advanced accessibility, and workbench-grade layout coordination
Release Checks
From the package root:
npm run release:checkAfter npm install, this repo also installs a local pre-push hook that runs the same verification chain before git push.
If you need to bypass it for a one-off emergency push, use OWOUI_SKIP_PREPUSH=1 git push.
Publishing notes live in:
