ui-web
Web design-system primitives on Base UI, consumed by web and admin — including the Radix-to-Base-UI prop translation every wrapper performs.
@statshub/ui-web holds the web primitives shared out of apps/statshub-web. The React
Native counterpart is ui-native, and the two
cannot merge — see why.
Components are published from TypeScript source through an exports map, so
Turbopack, tsc and the editor all read the same files:
import { Button } from "@statshub/ui-web/components/button";
import { cn } from "@statshub/ui-web/lib/utils";Base UI, not Radix
These are built on Base UI. shadcn serves a Base UI
variant of its registry under the base-vega style, which apps/statshub-web's
components.json is pinned to — so shadcn add <name> run from apps/statshub-web
writes a Base UI component straight into this package.
Base UI renamed or dropped a number of Radix props. Rather than rewrite hundreds of call sites, the wrappers accept the Radix spelling and translate it:
| Radix | Base UI | Handled by |
|---|---|---|
asChild | render prop | lib/as-child.tsx, applied in every wrapper |
<Accordion type collapsible> | multiple, array value | components/accordion.tsx |
onValueChange(value) | (value, eventDetails), string | null | components/select.tsx |
delayDuration, skipDelayDuration | delay on the Provider | components/tooltip.tsx |
openDelay / closeDelay | delay / closeDelay | components/hover-card.tsx |
avoidCollisions | collisionAvoidance | popup wrappers |
onOpenAutoFocus and friends | handled on the Root | accepted, not forwarded |
delayMs on avatar fallback | no equivalent | accepted, not forwarded |
Check this table before adding a primitive
A new wrapper that forwards asChild straight through will render nothing and
raise no error.
lib/slot.tsx is the one piece of @radix-ui/react-slot that survived, as a
local implementation — plain DOM wrappers (sidebar, breadcrumb) still want an
asChild escape hatch, and Base UI's render only exists on its own
primitives.
What else is in here
Beyond the Base UI wrappers, the package carries the pieces web and admin
share that are not primitives: @silk-hq/components sheets (bottom-sheet,
long-sheet), Embla carousels, react-day-picker calendars, cmdk command
menus, and a handful of motion components on Framer Motion. See
Silk components for the sheet conventions.