@01.software/ui
v0.3.0
Published
Browser UI primitives and precompiled theme styles for React 19.
Readme
@01.software/ui
Compact React 19 controls, built from the existing Web shadcn/Radix primitives. Web and the package catalogue use the same implementation. Import individual component subpaths and one precompiled stylesheet; there is no root barrel or framework adapter.
import { Button } from '@01.software/ui/button'
import { Checkbox } from '@01.software/ui/checkbox'
import { Label } from '@01.software/ui/label'
import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
} from '@01.software/ui/dialog'
import '@01.software/ui/styles.css'Components
| Subpath | Public components and helpers |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| button | Button, buttonVariants |
| input | Input |
| field | Field, FieldSet, FieldLegend, FieldGroup, FieldContent, FieldLabel, FieldTitle, FieldDescription, FieldSeparator, FieldError |
| select | Select, SelectTrigger, SelectValue, SelectContent, SelectItem, SelectGroup, SelectLabel, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton |
| radio-group | RadioGroup, RadioGroupItem |
| tabs | Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants |
| accordion | Accordion, AccordionItem, AccordionTrigger, AccordionContent |
| alert | Alert, AlertTitle, AlertDescription |
| badge | Badge, badgeVariants |
| checkbox | Checkbox |
| dialog | Dialog, DialogTrigger, DialogClose, DialogPortal, DialogOverlay, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription |
| label | Label |
| popover | Popover, PopoverTrigger, PopoverAnchor, PopoverClose, PopoverContent, PopoverHeader, PopoverTitle, PopoverDescription |
| progress | Progress |
| separator | Separator |
| skeleton | Skeleton |
| slider | Slider |
| switch | Switch |
| textarea | Textarea |
| tooltip | TooltipProvider, Tooltip, TooltipTrigger, TooltipContent |
| command-menu | CommandMenuRoot, CommandMenuTrigger, CommandMenuContent, CommandMenuItem, CommandMenuCheckboxItem, CommandMenuRadioItem, CommandMenuRadioGroup, CommandMenuGroup, CommandMenuLabel, CommandMenuSeparator, CommandMenuSub, CommandMenuSubTrigger, CommandMenuSubContent |
| menubar | Menubar, MenubarMenu, MenubarGroup, MenubarLabel, MenubarRadioGroup, MenubarRadioItem, MenubarSub, MenubarSubTrigger, MenubarSubContent, MenubarShortcut, MenubarTrigger, MenubarContent, MenubarItem, MenubarCheckboxItem, MenubarSeparator |
React and React DOM are peers restricted to major 19. File-by-file TypeScript emit preserves client boundaries. Button, Input, Alert, Badge, Skeleton and Textarea can render in a server page; interactive families are client boundaries. Modules do not import Next, Payload, SDK, private contracts or Web aliases. React is not bundled.
The components supply presentation and Radix interaction, not form state,
validation or authentication. Associate labels with htmlFor, and supporting
copy/errors with aria-describedby and aria-invalid. FieldError deduplicates
messages and announces them with role="alert"; it does not wire those IDs.
Field supports vertical, horizontal and responsive composition. Tabs supports
horizontal/vertical orientation, the default segmented tray, the line variant
and the existing visual="compact" trigger style.
Checkbox supports checked, unchecked and indeterminate states. Slider accepts
thumbLabels for distinct range-thumb names; shared labels remain associated
with each thumb. Progress clamps finite values and treats absent/non-finite
values as indeterminate. Skeleton is decorative. Select is a Radix single
select, and CommandMenu exposes dropdown/context menus rather than a searchable
command palette. Dialog/Popover/Tooltip retain Radix focus and dismissal
behavior. Use their triggers with an accessible name; icon-only controls need
an explicit label. DialogContent accepts closeLabel for the built-in close
button (default 닫기); showCloseButton={false} omits that button while
preserving Escape dismissal. Button has no asChild or built-in loading state.
Links alongside menus
menubarControlClassName from @01.software/ui/menubar shares the menu
trigger's default padding (8px horizontal, 2px vertical), 28px minimum height,
and keyboard focus treatment with ordinary navigation links. The precompiled
stylesheet includes these styles; consumers do not need to scan package source.
Keep links as siblings of Menubar in a wrapping navigation row with a 2px gap:
links retain native Tab/Enter navigation, while menus retain arrow-key navigation.
import { Menubar, menubarControlClassName } from '@01.software/ui/menubar'
function SiteNavigation() {
return (
<nav
className="flex flex-wrap items-center gap-0.5"
aria-label="Site navigation"
>
<a href="/pricing" className={menubarControlClassName}>
Pricing
</a>
<Menubar className="bg-transparent p-0">{/* menu children */}</Menubar>
</nav>
)
}Dashboard and SaaS composition
Start with Getting started and Recipes in the package catalogue on port 6008. Copy the desired AppShell, DataList or SettingsForm source and
recipes.css from apps/design-system/recipes
into your application. These are copyable compositions, not additional package
exports. They use React, public UI subpaths and explicit CSS, without Next,
Web aliases, Tailwind generation, authentication or a data-provider framework.
The application supplies navigation, data and async persistence.
Web's Pages / Proposals folders on port 6007 retain the broader local
settings, list/detail, account and plan explorations. They are Web examples;
use the 6008 recipes as the portable starting point.
Keep visible labels and connect descriptions/errors with htmlFor,
aria-describedby and aria-invalid. Field supplies layout, not form state
or validation. Supporting text has no automatic relationship to a control.
The copyable recipe stylesheet explicitly adds field/content spacing; the
catalogue's private presentation helper is not part of the package. Use RadioGroup for a single choice, Checkbox for independent
choices, and Switch for an immediate on/off setting. Default Input, Select
and Button heights align at 32px; compact Button/Select sizes are 28px. Let
long labels wrap and use responsive Field layout where labels need more room.
Tabs use a compact segmented tray by default; variant="line" and vertical
orientation support denser settings/navigation. Both default and
visual="compact" triggers have a 28px minimum height; longer labels may wrap
and grow instead of overflowing. The compact inner highlight stays within its
trigger. All interactive primitives keep visible keyboard focus: a muted 1px outline
with a 2px outer offset. Menu/list items use a -1px inset so the indicator
stays inside the popup. Invalid fields, including checked controls, use the
destructive focus color. Forced colors use a system-colored 2px outline.
Typography remains inherited from the consumer. The package does not install
global input listeners; applications may choose their own modality policy.
Informational cards do not need tabIndex. Use a native link or button when the
whole card is an action, with no nested interactive controls. When a card has
inner actions, only those controls participate in Tab navigation. TabsContent
remains focusable by default for text-only content; use tabIndex={-1} on a
panel whose content already provides an appropriate first focus target.
Styles, themes and overrides
Import @01.software/ui/styles.css once from your application stylesheet or
layout. No Tailwind setup, package-source scan, global reset or font download
is required. The application owns document typography and root size. Set
data-theme="dark" on the document root for dark mode so portalled surfaces
inherit it. A theme only on a subtree does not reach body portals.
The stylesheet supplies the implementations' utility classes, scoped control
and heading defaults, and Radix enter/exit motion. Reduced motion removes
scale/height travel while preserving opacity feedback. The --ui-surface token gives portalled menus and dialogs a raised neutral
surface in dark mode; consumers can override it alongside the existing palette.
Public theme tokens are
--foreground, --background, --muted-foreground, --border,
--destructive, --paper, --ink, --ink-muted, plus
--focus-ring-width, --focus-ring-color, --focus-ring-offset and
--focus-ring-inset-offset. The default color mixes ink 65% with paper in both
themes. Primitives read the public --ui-focus color and checked/indeterminate
Checkbox and checked Switch read --ui-focus-on-solid. Both default to
--focus-ring-color, so existing overrides on the root, a theme or a control
continue to work. Invalid fields retain --destructive instead of the solid
customization. Set the canonical default color on the root/theme alongside its
aliases, or override the public color variables directly for a subtree. Token names and default states are subject to semver.
This is a global stylesheet with unprefixed utility/token names; coexistence
with another system defining the same names is outside the support boundary.
Its layer order is theme, base, components, utilities (Tailwind may also
emit a properties initialization layer). Web loads the distribution CSS
before its own utilities and excludes package source from its Tailwind scan.
className uses clsx and tailwind-merge. Classes absent from the implementations
need consumer-owned CSS; an arbitrary new Tailwind class string does not
produce a utility. State-selector conflicts are governed by the CSS cascade.
Load overrides later in the same layer, in a later declared layer, or use
unlayered CSS targeting the component data-slot/state. The catalogue builds
its example-only layout utilities separately from the shipped stylesheet.
Verification and publication
corepack pnpm --filter @01.software/ui test builds JS, declarations and CSS,
checks all subpaths and import closure, client boundaries, SSR semantics and
the reset/font/layer boundary. The catalogue at loopback port 6008 adds state,
responsive, theme and keyboard examples. These checks do not establish full
accessibility, authenticated workflows or publication.
A packed external Next consumer without Tailwind/global reset verifies the actual distribution, including portal styles and interaction. Evidence is bound to its tarball and source inputs; supported peers do not claim a broader framework/browser matrix.
Consult package.json for the repository package version and .changeset/ for
pending release intent. Prepare production versions through the ordinary
Changesets process. Registration, preparation and registry availability are
separate states; repository metadata alone does not establish npm publication. The
final trusted Actions artifact needs its own fresh consumer check before
publication, as required by the release guide.
Historical 0.0.0 extraction evidence does not replace that gate.
LICENSE and THIRD_PARTY_NOTICES.md contain the existing MIT distribution and shadcn/Tailwind attribution. Consumer-installed peers/dependencies retain their licenses. Web fonts are not distributed. Source/tag evidence is not an npm provenance attestation for this private repository.
Submenus constrain both their minimum and maximum width to the space Radix reports as available, so nested menus remain inside narrow viewports.
