Skip to main content

Using the Component Library

@invent/wl-ui-kit-next is the shared UI component library for the Invent platform — a single source of truth for buttons, dialogs, inputs, typography, and widget shell infrastructure across every micro-app.

Related

This page is about using the current library in your widget. For UI-Kit design-system background and the component testing reference, see the Manual: UI-Kit and UI-Kit Testing.

Stack

  • React 18+ — peer dependency.
  • Tailwind CSS 4 — utility-first styling. Components use semantic color tokens (bg-primary, text-foreground, etc.), never hardcoded colors.
  • shadcn/ui — canonical pattern; primitives compose from Radix UI for accessibility and behavior.
  • Radix UI — unstyled accessible primitives (Dialog, Popover, Select, etc.) under the hood.
  • class-variance-authority (CVA) — typed variant systems for component appearance.
  • tailwind-merge + clsxcn() helper to merge class names without conflict.
  • lucide-react — icon set.
  • Tiptap — editor engine for the rich text editor (shipped on its own subpath).
  • @invent/tailwind-integration — peer dependency that provides the CSS foundation, theme tokens, Shadow DOM helpers, and WidgetRoot.

The package ships four entry points so widgets can import only what they need:

PathContents
@invent/wl-ui-kit-nextEverything (re-export barrel)
@invent/wl-ui-kit-next/ui35 shadcn-style primitives (Button, Dialog, Input, Select, etc.)
@invent/wl-ui-kit-next/typographyHeading1–4, Body1–2, Subtitle1–2, Caption, Overline
@invent/wl-ui-kit-next/widgetWidgetRootWrapper, WidgetLayout, WidgetHeader, WidgetFooter

RichTextEditor lives at @invent/wl-ui-kit-next/ui/rich-text-editor so Tiptap stays out of the main /ui bundle.

What's in the library

UI primitives (/ui): Alert, AlertDialog, Avatar, Badge, Button, Calendar, Card, Checkbox, CheckboxGroup, Collapsible, Combobox, Command, DatePicker, Dialog, DropdownMenu, Field, Form, Input, Label, MultiSelect, Popover, Progress, ScrollArea, Select, Separator, Sheet, SimpleFormField, Skeleton, Sonner, Switch, Table, Tabs, Textarea, Toast, Tooltip.

Typography (/typography): semantic React components with a polymorphic as prop, plus matching Tailwind utility classes (text-heading2, text-body1, etc.) that you can apply to any element.

Widget infrastructure (/widget): the structural shell every micro-app uses — WidgetRootWrapper for Shadow DOM isolation and FOUC prevention, WidgetLayout for header/content/footer skeleton, WidgetHeader and WidgetFooter.

Rich text editor (/ui/rich-text-editor): a Tiptap-based editor with a pluggable toolbar.

Utilities: cn() for class merging, usePortalStack() for z-index management of nested overlays.

Installation

npm install @invent/wl-ui-kit-next
npm install react react-dom @invent/tailwind-integration # peer deps

Import the CSS once in your widget's global.css:

@import 'tailwindcss' source('../../');
@import 'tw-animate-css';
@import '@invent/tailwind-integration/css/theme.css';
@import '@invent/wl-ui-kit-next/styles.full.css';

(The dashboard loads a deduplicated styles.css globally; widgets import styles.full.css so every class is available during local builds.)

Composition example

Widgets assemble independent components — each piece is small and explicit:

import {
WidgetRootWrapper,
WidgetLayout,
WidgetHeader,
WidgetFooter,
Button,
Heading3,
Body2,
} from '@invent/wl-ui-kit-next';

function MyWidget({ title, date }) {
return (
<WidgetRootWrapper widgetName="my-widget" shadow={true} loadStyles={...}>
<WidgetLayout
header={<WidgetHeader title={title} subtitle="Overview" />}
footer={<WidgetFooter dateString={date} />}
>
<Heading3>Section Title</Heading3>
<Body2>Content goes here</Body2>
<Button variant="outline">Action</Button>
</WidgetLayout>
</WidgetRootWrapper>
);
}

Design philosophy: primitives, not features

Each component is a visual primitive, not a feature. It owns styling, accessibility, variants, and composition contracts — but not data fetching, business state, or workflow logic. A <Button> is a styled button. A <Dialog> opens and closes. A <Table> renders rows. The wiring is yours. (Form is the one carve-out — it ships a thin react-hook-form integration.)

This is deliberate. "Smart" components that bundle behavior (e.g. a <DataTable> with built-in sorting, pagination, fetching) feel productive at first but become brittle: every widget has slightly different needs and ends up fighting the abstraction. Keeping the library to primitives means widgets compose exactly what they need, the library stays stable, and there's no shared abstraction layer to break across consumers.

Why this fits AI-assisted development

The case for bundled "smart" components used to be "I don't want to write all that wiring." With Claude, that wiring is cheap to generate — and tailored to the specific widget. So the calculus flips: primitives + AI > monolithic components.

It also plays to what AI does well:

  • Small, typed primitives are stable contracts Claude can compose against confidently.
  • Explicit, local code is easier for an AI to reason about than behavior hidden inside a fluent config API.
  • Library primitives stay untouched during widget edits, so AI-driven changes have a small blast radius.

You get platform-wide consistency from the shared primitives, and widget-specific behavior — where teams actually differentiate — stays in code that's easy for both humans and AI to read and change.