control/uialpha

An opinionated, customizable superset of shadcn/ui

Create app
PrimitivesAIUse casesSkills
Guides
  • Overview
  • Get started
  • Create a skin
  • Shadcn compatibility
  • Architecture
  • Agent surface
  • Lock-in
  • Theme accessibility
  • Theme AI builder
  • Control UI vs shadcn/ui
  • Best React component libraries for AI interfaces
Skins
  • Skinning Control UI
Agents
  • Action Bar
  • Activity
  • Audio Recorder
  • Audio VisualizerBetaBeta — the props contract is close to final, but small breaking changes can still land.
  • Chat Composer
  • Chat Composer Attachment
  • Chat Layout
  • Chat Message
  • Code Block Editor
  • ContextBetaBeta — the props contract is close to final, but small breaking changes can still land.
  • Dynamic NotificationExpExperimental — the contract and the rendering can change without notice. Own the installed copy before shipping it.
  • Environment VariablesExpExperimental — the contract and the rendering can change without notice. Own the installed copy before shipping it.
  • Inline AttachmentBetaBeta — the props contract is close to final, but small breaking changes can still land.
  • Inline CitationBetaBeta — the props contract is close to final, but small breaking changes can still land.
  • Markdown Block
  • Source Badge
  • Task List
  • Thread Rail
  • Transcript Divider
  • User Ask
  • GitHub11

by Damien Schneider

Skins

Skinning Control UI

Author complete token-driven Control UI skins with slots, adornments, motion controls, and one shared component source.

Not sure a skin is even the right tool? The customization ladder in the Architecture guide places every "make it different" request on one of eight rungs — with what each rung costs an app that never uses it. This page picks up once the answer is a skin.

Where skin values live

One owner for each visual decision.

theme tokenGlobal semantic color, radius, type, and motion values live in theme.css and feed every recipe.
component knobA component-specific visual is re-valued through its registered --component-* property in scoped skin.css.
custom CSSUse scoped skin.css for pseudo-elements, keyframes, native chrome, relational selectors, and uniform semantic families.
neverDo not repaint a recipe-owned property directly or invent a second variable for a value the component knob contract already exposes.

The token contract

Every custom property a skin may re-value, rendered straight from lib/theme-contract.ts — the same module the coverage test enforces, so this reference can never drift from the CSS.

Core — the 26 tokens a skin typically re-values first
--backgroundColorBase surface color (panels, bubbles read it via bg-background).
--foregroundColorDefault text color on --background.
--cardColorElevated card surface.
--card-foregroundColorText color on --card.
--popoverColorFloating surface base (popover / menu / select / dialog).
--popover-foregroundColorText color on --popover.
--primaryColorTHE brand color; primary action surfaces route through it.
--primary-foregroundColorText color on --primary.
--mutedColorSubdued fill for quiet surfaces.
--muted-foregroundColorSecondary / meta text color.
--secondaryColorSecondary action fill (assistant bubble in chat skins).
--secondary-foregroundColorText color on --secondary.
--accentColorHover / selection highlight fill.
--accent-foregroundColorText color on --accent.
--destructiveColorDestructive action color.
--destructive-foregroundColorText color on --destructive.
--borderColorHairline border color (carries --ring-opacity).
--inputColorForm field border color.
--ringColorFocus ring color.
--canvasColorThe page paper the scene/panels float on — a level BELOW --background.
--font-sansTypographyTypeface for the whole UI.
--font-monoTypographyMonospace face (code, kbd).
--radiusRadiusTHE single radius knob; the whole scale multiplies from it.
--duration-fastMotionFast tempo (hover, color).
--duration-baseMotionBase tempo (menus, indicators).
--duration-slowMotionSlow tempo (panel/message entrances).
Derived — optional overrides80 tokens with a core default; re-value one in theme.css only to diverge›
--primary-textColorReadable brand text color on base and card surfaces.
--destructive-textColorReadable destructive text color on base and card surfaces.
--focus-ringColorColor of the keyboard focus indicator; defaults to --ring. Must clear 3:1 against every surface it lands on (WCAG 1.4.11).
--ring-opacityColorAlpha of the border/ring hairlines; 0 = borderless, defaults to 1.
--badge-neutralColorSoft neutral-family badge background; the skin owns the exact hue.
--badge-neutral-foregroundColorText color on the neutral-family badge.
--badge-neutral-borderColorBorder of the outline neutral-family badge variant.
--badge-neutral-hoverColorHover background of filled neutral-family badge links and buttons.
--badge-redColorSoft red-family badge background; the skin owns the exact hue.
--badge-red-foregroundColorText color on the red-family badge.
--badge-red-borderColorBorder of the outline red-family badge variant.
--badge-red-hoverColorHover background of filled red-family badge links and buttons.
--badge-orangeColorSoft orange-family badge background; the skin owns the exact hue.
--badge-orange-foregroundColorText color on the orange-family badge.
--badge-orange-borderColorBorder of the outline orange-family badge variant.
--badge-orange-hoverColorHover background of filled orange-family badge links and buttons.
--badge-yellowColorSoft yellow-family badge background; the skin owns the exact hue.
--badge-yellow-foregroundColorText color on the yellow-family badge.
--badge-yellow-borderColorBorder of the outline yellow-family badge variant.
--badge-yellow-hoverColorHover background of filled yellow-family badge links and buttons.
--badge-greenColorSoft green-family badge background; the skin owns the exact hue.
--badge-green-foregroundColorText color on the green-family badge.
--badge-green-borderColorBorder of the outline green-family badge variant.
--badge-green-hoverColorHover background of filled green-family badge links and buttons.
--badge-blueColorSoft blue-family badge background; the skin owns the exact hue.
--badge-blue-foregroundColorText color on the blue-family badge.
--badge-blue-borderColorBorder of the outline blue-family badge variant.
--badge-blue-hoverColorHover background of filled blue-family badge links and buttons.
--badge-purpleColorSoft purple-family badge background; the skin owns the exact hue.
--badge-purple-foregroundColorText color on the purple-family badge.
--badge-purple-borderColorBorder of the outline purple-family badge variant.
--badge-purple-hoverColorHover background of filled purple-family badge links and buttons.
--badge-pinkColorSoft pink-family badge background; the skin owns the exact hue.
--badge-pink-foregroundColorText color on the pink-family badge.
--badge-pink-borderColorBorder of the outline pink-family badge variant.
--badge-pink-hoverColorHover background of filled pink-family badge links and buttons.
--font-bodyTypographyFont ROLE for body/UI text; defaults to --font-sans.
--font-displayTypographyFont ROLE for headings; defaults to --font-sans.
--text-microTypography10px rung — kbd, badge counters, dense numeric meta.
--text-captionTypography11px rung — overlines, timestamps, group labels.
--text-bodyTypography14px rung — DEFAULT body & control text.
--text-body-lgTypography16px rung — emphasized / larger body.
--text-heading-4TypographySmallest heading rung (15px).
--text-heading-4--line-heightTypographyLine-height paired onto text-heading-4.
--text-heading-4--font-weightTypographyWeight paired onto text-heading-4.
--text-heading-3TypographyHeading rung (18px).
--text-heading-3--line-heightTypographyLine-height paired onto text-heading-3.
--text-heading-3--font-weightTypographyWeight paired onto text-heading-3.
--text-heading-2TypographyHeading rung (22px).
--text-heading-2--line-heightTypographyLine-height paired onto text-heading-2.
--text-heading-2--font-weightTypographyWeight paired onto text-heading-2.
--text-heading-1TypographyLargest content heading (30px — in-page / markdown h1).
--text-heading-1--line-heightTypographyLine-height paired onto text-heading-1.
--text-heading-1--font-weightTypographyWeight paired onto text-heading-1.
--text-heading-1--letter-spacingTypographyTracking paired onto text-heading-1.
--text-displayTypographyDisplay rung above h1 (36px — page titles, heroes).
--text-display--line-heightTypographyLine-height paired onto text-display.
--text-display--font-weightTypographyWeight paired onto text-display.
--text-display--letter-spacingTypographyTracking paired onto text-display.
--radius-smRadiusScale rung: --radius × 0.6.
--radius-mdRadiusScale rung: --radius × 0.8.
--radius-lgRadiusScale rung: --radius × 1.
--radius-xlRadiusScale rung: --radius × 1.4.
--radius-2xlRadiusScale rung: --radius × 1.6.
--corner-shapeRadiusProgressive corner reshape (round | squircle | scoop | …); defaults to round.
--corner-radius-fitRadiusFallback radius shrink where corner-shape: squircle is unsupported.
--radius-popoverRadiusPopup container corner, concentric with the fitted row corner.
--shadow-highlightShadowInner top light painted along raised surfaces' top edge (carries its resting alpha).
--shadow-yShadowVertical bias: 0 = centered, 1 = default bottom cast.
--shadow-control-multiplierShadowElevation tier: controls; defaults to 1.
--shadow-panel-multiplierShadowElevation tier: panels; defaults to 2.
--shadow-popover-multiplierShadowElevation tier: floating popovers; defaults to 4.
--shadow-modal-multiplierShadowElevation tier: dialogs and sheets; defaults to 5.
--shadow-ambient-multiplierShadowElevation tier: ambient scene lift; defaults to 8.
--control-h-xsLayoutDerived control height: xs (×0.78, px-snapped).
--control-h-smLayoutDerived control height: sm (×0.89, px-snapped).
--control-h-lgLayoutDerived control height: lg (×1.11, px-snapped).
--focus-ring-widthLayoutThickness of the keyboard focus indicator; 0 removes it and fails WCAG 2.4.7.
--focus-ring-styleLayoutLine style of the keyboard focus indicator (solid, dotted, dashed); none removes it and fails WCAG 2.4.7.
--focus-ring-offsetLayoutGap between a control edge and its focus indicator; negative draws the indicator inside.
Advanced — Typography1 token›
--text-labelTypography12px rung — form labels + small chrome.
Advanced — Radius5 tokens›
--radius-controlRadiusShared control corner (button, trigger, field, chip); ×2 from --radius.
--radius-fieldRadiusUser bubble / composer shell corner; --radius × 2.2.
--radius-panelRadiusCode / markdown panel corner; --radius × 2.6.
--radius-sceneRadiusScene frame / large media corner; --radius × 2.8.
--radius-popup-itemRadiusSelect/menu row corner; derived from --radius-control.
Advanced — Shadow3 tokens›
--shadow-colorShadowHue every shadow is tinted with.
--shadow-sizeShadowGlobal geometry multiplier: 1 = default depth, 0 = flat.
--shadow-opacityShadowGlobal alpha multiplier: 1 = default density, 0 = invisible.
Advanced — Motion2 tokens›
--ease-standardMotionDefault easing curve for color/text transitions.
--ease-emphasizedMotionEmphasized curve for entrances and larger moves.
Advanced — Surface5 tokens›
--popover-opacitySurfaceFloating-surface translucency; <1 + blur = frosted glass.
--backdrop-blur-popoverSurfaceBackdrop blur behind floating surfaces.
--overlay-opacitySurfaceModal overlay (dialog backdrop) dim strength.
--backdrop-blur-overlaySurfaceBackdrop blur of the modal overlay.
--scroll-fade-sizeSurfaceEdge-fade depth of scrollable surfaces; 0 = hard edges.
Advanced — Layout4 tokens›
--popover-paddingLayoutGap between popup container edge and rows (drives concentric corners).
--padding-xLayoutHorizontal content density of rounded surfaces (bubble, composer).
--padding-yLayoutVertical content density of rounded surfaces.
--control-hLayoutTHE base control height (md); the ramp derives from it.

The anatomy contract

Generated from canonical component DOM. Family is the selector key; slot names the part; scope identifies the component.

Copy a selector as [data-skin="brand"] [data-slot="shell"][data-control-family="chat-composer"]. Optional adornment anchors are listed separately in the full machine-readable contract, so they cannot be mistaken for DOM parts.

accordion (5)
rooticonitempaneltrigger
action-bar (1)
root
activity (13)
rootannouncementchevroncontentcontent-viewportdetaildetail-contentdetail-labeliconrowstatustitletrigger
alert (3)
rootdescriptiontitle
alert-dialog (7)
backdropcontentdescriptionfooterheadertitletrigger
aspect-ratio (1)
root
audio-recorder (9)
rootactionscancelcontentdurationstatussubmittriggervisualizer
audio-visualizer (5)
rootbarbar-trackbaselinetrack
audio-visualizer-line (1)
waveform
autocomplete (10)
rootclearcontentemptygroupgroup-labelinputitemlistpositioner
avatar (4)
rootfallbackgroupimage
badge (1)
root
breadcrumb (7)
rootellipsisitemlinklistpageseparator
button (2)
rootcontent
button-group (3)
rootseparatortext
calendar (11)
rootcaption-labeldayday-cellmonthmonth-captionmonth-gridmonthsnavnav-buttonweekday
card (7)
rootactioncontentdescriptionfooterheadertitle
chat-composer (12)
rootaccentfootermentionmention-descriptionmention-iconmention-labelshellsubmittextareatoolbartools
chat-composer-attachment (10)
rootcontentdescriptionpreviewpreview-labelprogressprogress-indicatorremovestatustitle
chat-composer-attachments (3)
rootlistscroll
chat-composer-editor (4)
rooteditorfallbackplaceholder
chat-layout (1)
root
chat-message (7)
rootactionsavatarbodycontentheaderrow
chat-thought (5)
rootchevrondetailstitletrigger
chat-thread (1)
root
chat-turn (1)
turn
checkbox (2)
rootindicator
checkbox-group (1)
root
code (9)
rootaccessible-sourceactionscontentgridgutterheaderlinetitle
code-block-editor (6)
rootactionscontenteditorheadertitle
code-diff (21)
rootaccessible-sourceactionsbodyemphasisempty-halfexpand-buttonexpanderexpander-labelfilefile-headerfile-titlegutterheaderlinemarkerrowstatstat-additionsstat-deletionstitle
collapsible (3)
rootcontenttrigger
color-picker (40)
alphaalpha-thumbalpha-trackareaarea-brightnessarea-saturationarea-thumbchannelchannel-labelchannelscontentcontrastcontrast-fixcontrast-levelcontrast-ratioeye-dropperformathuehue-thumbhue-trackinputoutputoutput-checkeroutput-coloroutput-swatchoutput-valuepanelpositionerswatchswatch-addswatch-checkerswatch-colorswatchesswatches-groupswatches-labeltriggertrigger-checkertrigger-colorwheelwheel-thumb
combobox (12)
rootcontentemptygroupgroup-labeliconinputitemitem-indicatorlistpositionertrigger
command (11)
rootdialog-rootemptygroupinputinput-iconinput-wrapperitemlistseparatorshortcut
context (23)
rootcontentdescriptiongraphheaderlegendlegend-descriptionlegend-indicatorlegend-itemlegend-labellegend-valuelimit-markeroveragesegmentsummarysummary-valuetitletracktriggertrigger-indicatortrigger-labeltrigger-tracktrigger-value
context-menu (14)
checkbox-itemcontentgroupitemlabelradio-groupradio-indicatorradio-itemseparatorshortcutsub-contentsub-triggersub-trigger-indicatortrigger
dialog (7)
backdropcontentdescriptionfooterheadertitletrigger
dockable-panel (7)
rootactionscontentdrag-handledrop-zoneheadertitle
drawer (10)
backdropclosecontentdescriptionfooterhandleheadertitletriggerviewport
dropdown-menu (5)
contentitemlabelseparatortrigger
dropzone (14)
rootareafeedbackfeedback-iconfeedback-messagefeedback-spinnerfilefile-listinputoverlayrejectionrejection-liststatustrigger
dynamic-notification (14)
rootclosecontentglassindicatorislandliquidmessagepillreplyreply-inputreply-submittitleword
empty (6)
rootcontentdescriptionheadermediatitle
environment-variables (22)
rootactionscolumn-labelsdescriptionemptyfield-errorfield-labelheaderhinthint-codekey-inputmessagereadonly-itemreadonly-keyreadonly-listreadonly-valuerowrowstitletoolbarvalue-groupvalue-input
field (13)
rootcontentcontroldescriptionerrorgroupitemlabellegendseparatorseparator-contentsettitle
form (1)
root
gradient-editor (5)
rootpreviewstopstop-addtrack
hover-card (3)
contentpositionertrigger
infinite-canvas (3)
rootcontentcontrols
inline-attachment (14)
rootactionactionscontentdescriptiondocumentdocument-headingdocument-linedocument-sheetdocument-stampimagemedia-imageplaceholdertitle
inline-citation (18)
rootcontentfaviconfaviconslabelnavigationnextpositionprevioussourcesource-descriptionsource-external-iconsource-faviconsource-headersource-hostnamesource-quotesource-titletrigger
input (1)
root
input-group (3)
rootaddoninput
input-otp (3)
rootseparatorslot
item (10)
rootactionscontentdescriptionfootergroupheadermediaseparatortitle
kbd (2)
rootgroup
label (1)
root
markdown (18)
rootblockquoteemphasish1h2h3inline-codelinklist-itemordered-listparagraphseparatorstrongtabletable-celltable-headertable-scrollunordered-list
markdown-block (5)
rootcontentheadertitletitle-icon
menubar (11)
rootcontentgroupitemlabelseparatorshortcutsub-contentsub-triggersub-trigger-indicatortrigger
meter (5)
rootindicatorlabeltrackvalue
model-switcher (4)
roothintindicatorvalue
morphing-panel (3)
rootcontenttrigger
native-select (2)
rooticon
navigation-menu (10)
rootcontenticonitemlinklistpopuppositionertriggerviewport
number-field (7)
decrementdrag-icongroupincrementinputscrub-areascrub-cursor
pagination (5)
rootcontentellipsisitemlink
phone-input (6)
checkchevroncountry-codecountry-triggerflagmetadata
popover (6)
closecontentdescriptionheadertitletrigger
progress (5)
rootindicatorlabeltrackvalue
radio-group (3)
rootindicatoritem
resizable (4)
handlehandle-grippanelpanel-group
rich-tooltip (14)
arrowclosecontentdescriptiondotfooterheadermedianextpositionerpreviousprogresstitletrigger
scroll-area (6)
rootcontentcornerscrollbarthumbviewport
select (5)
contenticonitemitem-indicatortrigger
separator (1)
root
sheet (6)
backdropclosecontentdescriptionheadertitle
sidebar (17)
rootcontainercontentfootergapgroupgroup-labelheaderinnerinsetmenumenu-buttonmenu-itemmenu-trackrailtriggerwrapper
sidebar-layout (1)
content
skeleton (1)
root
slider (8)
rootcontrolindicatorlabelthumbticktrackvalue
source-badge (2)
rootlabel
spinner (2)
rootindicator
stepper (9)
rootcontentdescriptionindicatoritemlistseparatortitletrigger
switch (3)
rootthumbthumb-icon
table (9)
rootbodycaptioncellcontainerfooterheadheaderrow
table-of-contents (7)
rootitemlabellistrailtracktrail
tabs (5)
rootindicatorlistpaneltab
task-list (8)
rootchevronitemitem-indicatoritemslabelprogresstrigger
textarea (1)
root
thread-rail (11)
rootfilefile-iconfooteritemlinemorepopoverpopover-layersummarytitle
timeline (8)
rootcontentdescriptionindicatoritemmetaseparatortitle
toast (8)
rootactionclosecontentdescriptionindicatortitleviewport
toggle (4)
rootcheckcontentgroup
toolbar (6)
rootbuttongroupinputlinkseparator
tooltip (4)
arrowarrow-shapecontentpositioner
track-highlight (2)
roothover
transcript-divider (2)
rootlabel
tree (8)
rootitemitem-contentitem-groupitem-indicatoritem-labelitem-triggertrack
trigger-menu (8)
rootemptygroupgroup-labeliconitemlistpositioner
user-ask (16)
rootdismissfooterfreeform-labelheaderoptionoption-descriptionoption-indicatoroption-inputoption-labelpaginationpagination-countquestionrecommendedsubmittitle

Skin requirements — the do-not list

What a pack must and must not do. Every rule is enforced by a test, so a violating pack fails the build before it ships.

contract only in theme.csstheme.css declares every contract name and nothing else; an invented var belongs in skin.css. Enforced by theme-contract-coverage.test.ts against lib/theme-contract.ts.
no @theme in a pack@theme merges globally across co-compiled packs, so a pack can never own bindings — scale intent is authored as raw scoped tokens; the @theme block belongs to Control UI core alone. Enforced per pack.
complete in both modesEvery contract token resolves in light and dark, either from one shared declaration or explicit mode declarations. A skin never inherits a missing value from Refined or core. Enforced per pack.
no component CSS in theme.css@layer components, @utility, @keyframes, and anatomy selectors live in skin.css — theme.css stays a pure token block. Enforced per pack.
skin.css never redeclares the contractA contract name re-valued in skin.css hides the change from the theme editor and this token reference; contract names are theme.css territory. Enforced per pack.
scope anatomy, never host elementsComponent selectors in skin.css key the generated [data-slot="part"][data-control-family="family"] pair, narrowed by [data-<family>-kind] when several components share a family; never skin bare host elements (code, button, input) under [data-skin]. Enforced per pack.
declared intents, mirroredcolorScheme locks the page mode to a fixed-scheme skin and motion: "reduced" collapses --duration-* through data-motion — never animation: none on finite animations. Both flags are mirrored in components/theme.ts for the pre-paint script; theme-color-scheme-lock.test.ts fails on drift.
extensions attach by anatomyA root runtime discovers interactive parts through data-control, gates its observers on the active skin, and tears down cleanly. Root runtimes stay out of skin.config and mount once in the app layout. Anchored adornment extensions are different: skin.config may import their component and render it through a typed adornment anchor while the config itself remains RSC-pure.

Adornments

JSX at named anchors — decorative chrome, or behavioral fx layers.

Additive, render zero DOM when absent, never gate library behavior. Decorative anchors (window titlebars, window controls) take plain aria-hidden JSX. Behavioral anchors (like chat-composer:send-layer) take a (ctx) => JSX render prop whose ctx carries plain render-time values — this is how a pack activates an anchored extension (send-aurora). Adornments are nested by scope and part in skin.config. Interactive values live in a separate "use client" file the pack ships, so skin.config itself stays RSC-pure.

Motion flag

One boolean, zero JavaScript.

motion: "reduced" stamps data-motion="reduced", which collapses --duration-fast/base/slow to 0 — every cva transition, Base UI enter/exit and the shimmer/ripple keyframes flatten at once. The theme editor also exposes a manual "Reduce motion" toggle.

Component knobs and the cascade

Tokens theme the whole app from :root. Knobs theme one family and live on its root element — every slot inherits.

css
/* app-wide: a token, on :root */
:root { --radius-field: 0.75rem; }
/* one family, everywhere: a knob, on the family root */
[data-control-family="chat-composer"] { --cui-chat-composer-shell-radius: 0; }
/* one instance, on the root element:
className="[--cui-chat-composer-shell-radius:0]" or style={{ "--cui-chat-composer-shell-radius": "0" }} */

The recipe declares each knob's default on the family root at zero specificity, so a value set on that element always wins: style beats a skin, a skin beats the recipe, a utility class beats both. Setting a knob on :root does nothing — the family root re-declares it; re-value the token it derives from instead. Portaled surfaces are their own root: set --popup-* on the popup content, not on the trigger. Each component page lists its knobs with type and default.

Skins

Each pack's tokens, skin.css and config, ready to read and install.

RefinedCompact, calm starting skin with a complete Control UI token contract.ThemeWindows XPWindows XP-inspired Luna tokens, bevels, and titlebar details.AdvancedLiquid metalPolished metal skin with a WebGL shader control surface.AdvancedRigBrutalist skin with coral accents, squared corners, and dense typography.ThemeFlatNeutral reset skin with square corners, no shadows, and the stock motion tempo.ThemeModern AppleApple-inspired Liquid Glass skin: WebGL-refraction on floating surfaces, precise directional rims, transparent inputs, and continuous corners.AdvancedCuicuiCuicui-inspired shell skin with fixed grain, a docked w-80 sidebar, a neutral main container, and the send-aurora anchored extension on ChatComposer (skin.config fills the chat-composer:send-layer anchor).AdvancedLinearLinear-inspired skin: indigo brand on a cool neutral ramp, a flat 13px chrome band, 4px radius, hairline borders instead of elevation, and pill-shaped filled actions.Advanced

On this page

  • Slot vs skin.css
  • Token contract
  • Requirements
  • Generate from a seed
  • Adornments
  • Motion flag
  • Gotcha
  • Skins
No results found.
Guides
Create app
Scaffold a Next.js app with every Control UI component installed as source you own, or hand the whole install to the coding agent already open in your project.
Guide
Overview
An owned-source registry of primitives, agent surfaces, complete blocks, and swappable skins.
Guide
Get started
Choose a skin, install a component or complete block, wire its CSS, and compose your application runtime.
Guide
Create a skin
Re-value the token contract over an installed pack, or own a full pack of three files, then reach the component knobs beneath.
Guide
shadcn compatibility
shadcn registry, token, and ownership conventions without writing to components/ui.
Guide
Architecture
Runtime ownership, skin layering, customization paths, and registry derivation.
Guide
Agent surface
Inspect and install registry items through HTTP, shadcn manifests, static metadata, and machine-readable docs.
Guide
Lock-in
What you own at each layer, what stays proprietary, and what leaving costs — measured, not promised.
Guide
Theme accessibility
Audit canonical theme colors plus rendered popup, badge, and active-tab states, then run the same checks from the CLI.
Guide
Theme AI builder
Create a Control UI theme with Claude Code, Codex, or Mastra Code, then import and test it live.
Guide
Control UI vs shadcn/ui
Both ship open-source React source through the shadcn CLI. The difference starts after install: a typed knob contract, skins that re-value it wholesale, and 16 skin modes audited against WCAG AA on every commit.
Guide
Best React component libraries for AI interfaces
Six production options compared by ownership model, theming system, and agent-specific surfaces — from shadcn/ui to MUI to Control UI.
Guide
Skins
Skinning Control UI
Author complete token-driven Control UI skins with slots, adornments, motion controls, and one shared component source.
Skin
Refined
Compact, calm starting skin with a complete Control UI token contract.
Skin
Windows XP
Windows XP-inspired Luna tokens, bevels, and titlebar details.
Skin
Liquid metal
Polished metal skin with a WebGL shader control surface.
Skin
Rig
Brutalist skin with coral accents, squared corners, and dense typography.
Skin
Flat
Neutral reset skin with square corners, no shadows, and the stock motion tempo.
Skin
Modern Apple
Apple-inspired Liquid Glass skin: WebGL-refraction on floating surfaces, precise directional rims, transparent inputs, and continuous corners.
Skin
Cuicui
Cuicui-inspired shell skin with fixed grain, a docked w-80 sidebar, a neutral main container, and the send-aurora anchored extension on ChatComposer (skin.config fills the chat-composer:send-layer anchor).
Skin
Linear
Linear-inspired skin: indigo brand on a cool neutral ramp, a flat 13px chrome band, 4px radius, hairline borders instead of elevation, and pill-shaped filled actions.
Skin
Skills
CSS-first interactivity
Model UI reactions with relational selectors, container/style queries, and native platform elements before adding React state, effects, or event handlers.
Skill
CSS-first motion & sizing
Drive sizing, enter/exit motion, and scroll effects from CSS and native attributes — token-driven and progressively enhanced — instead of measuring and animating values in JavaScript.
Skill
Derive, do not duplicate
Avoid second sources of truth in component props, hook parameters, and local state.
Skill
Remount state boundaries
Reset state by changing component identity or loading boundaries, not by syncing with effects.
Skill
Explicit names instead of comments
Encode intent in identifiers and extracted units so the code needs no explanatory comments, and keep the rare justified one telegraphic.
Skill
One responsibility per file
Split domain components and hooks before fetching, filtering, selection, and form state become entangled.
Skill
Keep input and output APIs narrow
Split oversized prop, argument, and return-value APIs into cohesive responsibilities.
Skill
Keep context necessary, narrow, and stable
Use context only across real composition boundaries, with the smallest stable semantic value consumers need.
Skill
Do not query the DOM in React
Keep element identity and collections in React instead of searching rendered markup.
Skill
Real stack tests
Prefer tests that drive production hooks, clients, routing, and cache behavior with only the network mocked.
Skill
Test rendered output, not class names
Prove visual behavior through computed styles, geometry, or browser output instead of Tailwind class strings.
Skill
Cohesive folders
Keep every folder a short, readable table of contents by grouping loose files into named responsibilities.
Skill
Single source of truth
Prevent shared facts from drifting by assigning each one a canonical owner.
Skill
Use existing components first
Start from the local design system or registry primitive before creating a new styled element.
Skill
Token discipline
Use established design tokens and local CSS variables before reaching for one-off values.
Skill
ClassName boundaries
Use component APIs for intended variation instead of overriding design-system internals with className.
Skill
Tailwind v4 CSS configuration
Configure Tailwind through CSS directives and tokens instead of adding new JavaScript config.
Skill
Tailwind v4 migration syntax
Use v4 names and modifiers when replacing or reviewing v3-era Tailwind classes.
Skill
First-class utilities before custom CSS
Prefer Tailwind v4's first-class utility families before arbitrary properties or handwritten CSS.
Skill
Variant-first styling
Check Tailwind variants before adding handwritten selectors, style props, or React state for styling.
Skill
Tailwind v4 capabilities
Reach for new v4 utilities before layout hacks, user-agent checks, or JavaScript measurement.
Skill
Tailwind v4 behavior & motion
Account for v4 behavior changes around transforms, hover, default colors, variant order, spacing, and motion.
Skill
State continuity
Show loading, empty, partial, success, and failure states in the same product language.
Skill
Provenance without noise
Surface source, runtime, and ownership cues only where they help the user trust or act.
Skill
Dense but scannable
Favor compact surfaces that support repeated work without flattening hierarchy.
Skill
Say it once
Cut redundant AI-slop copy so labels, controls, and state carry the obvious meaning.
Skill
Skin authoring
Author a skin as three files with strict roles — theme.css owns shared tokens, skin.css re-values registered component knobs, and skin.config declares behavior and adornments.
Skill
Extension authoring
Author an extension as an optional installable layered on the library — root-mounted for cross-cutting anatomy-attached behavior, anchored for component-scoped fx activated from skin.config.
Skill
Registry-first DX
Keep the registry manifest and installed source as the contract users can inspect.
Skill
Skin completeness
Treat a skin as a complete source recipe, not a partial class override layer.
Skill
Control UI composition
Keep blocks readable by composing public agent components, hooks, and slots explicitly.
Skill
Runtime-agnostic UI
Keep core visual surfaces independent from model runners, stores, and transport lifecycles.
Skill
Compound components DX
Expose named anatomy parts when users need to customize layout or actions.
Skill
Context vs props
Reach for a compound-component context only when props cannot reach the part, and store intent in it, not styling.
Skill
AI
AI components
Explore composable surfaces for messages, input, activity, media, and agent workflows.
Agent
ChatMessage
Composable chat message with typed role, density, and lifecycle state.
Agent
ChatComposer
Prompt composer with controlled text, submit state, and trigger-menu support.
Agent
ChatComposerAttachment
Composer attachment rail with file previews, upload progress, and removal.
Agent
UserAsk
Keyboard-first agent question panel that temporarily replaces the chat composer inside its container.
Agent
TaskList
Floating agent task progress pill above the composer that expands into the full task list.
Agent
AudioRecorder
Voice recorder with realtime waveform, duration, cancel, and submit controls.
Agent
AudioVisualizer
Levels-driven realtime audio visualizer offered in two usage versions - bars and line - sharing one export and one props contract.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Agent
DynamicNotification
Dynamic Island-style AI notification pill with a thinking state that morphs into a reply bubble — token-driven surface, WebGL-enhanced backdrop blur, or real refractive liquid glass.
ExpExperimental — the contract and the rendering can change without notice. Own the installed copy before shipping it.Agent
EnvironmentVariables
Composable environment variable editor with .env upload, bulk paste, reveal controls, and submit helpers.
ExpExperimental — the contract and the rendering can change without notice. Own the installed copy before shipping it.Agent
Activity
Shared static and collapsible activity anatomy with bounded, scrollable detail content.
Agent
TranscriptDivider
Toned run-boundary separator for transcripts: steering, interruptions, and condensed context.
Agent
Context
Compact context-window usage with an automatically derived token graph and anchored detail inspector.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Agent
InlineCitation
Inline multi-source citation with a keyboard-accessible preview and source navigation.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Agent
SourceBadge
Linked source badge with an automatic same-origin favicon, derived hostname, and resilient fallback.
Agent
ActionBar
Reusable hover actions for message and response controls.
Agent
InlineAttachment
Inline file and media previews for chat turns.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Agent
MarkdownBlock
Assistant markdown output rendered to prose, with a header and copy-source action.
Agent
CodeBlockEditor
Editable code surface with Shiki highlighting and token-based light/dark themes.
Agent
ChatLayout
Layout primitives for full chat threads, turns, and thoughts.
Agent
ThreadRail
Conversation minimap for scanning and jumping between chat turns.
Agent
Primitives
Primitives
Browse every Control UI primitive through the same live examples used in its documentation.
Primitive
Button
Accessible action button with size, variant, and semantic tone support.
Primitive
Collapsible
Accessible disclosure primitive with measured open and close motion.
Primitive
Tabs
Segmented and browser-style navigation with a stable active indicator.
Primitive
Sidebar
Responsive app sidebar with collapse, mobile sheet, and keyboard toggle support.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Scroll area
Scroll container with overlay scrollbars and edge fades.
Primitive
Table of contents
Sticky in-page navigation with scroll-spy range highlighting.
Primitive
Timeline
Static chronological events with independent status, connectors, descriptions, and metadata.
Primitive
Stepper
Static and interactive workflow steps with horizontal and vertical layouts.
Primitive
Skeleton
Loading placeholder with a token-driven shimmer.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Slider
Single-value range control with branded and plain treatments.
Primitive
Select
Single-choice picker with a token-matched trigger and floating list.
Primitive
DropdownMenu
Dropdown menu for actions, resources, labels, separators, and submenus.
Primitive
Context Menu
Pointer-positioned right-click and long-press menu with nested actions and selection controls.
Primitive
Toggle
Pressed-state button and toggle group built on the Button surface.
Primitive
Switch
On/off control with token-driven track, thumb, and press motion.
Primitive
Dialog
Modal dialog for focused tasks, confirmations, and custom panels.
Primitive
Popover
Anchored floating panel for inline settings and contextual content.
Primitive
Tooltip
Hover or focus hint popup with Base UI positioning and Control UI tokens.
Primitive
Rich tooltip
Persistent anchored tip for onboarding tours, walkthroughs, and new-feature announcements — dismissible, with optional media and step counter.
Primitive
Drawer
Swipeable edge panel for mobile sheets and off-canvas surfaces.
Primitive
Responsive dialog
Modal dialog on desktop that becomes a swipeable bottom drawer on mobile.
Primitive
Toast
Transient notifications with a callable toast API and single Toaster mount.
Primitive
Input
Text field primitive sized and styled to match other controls.
Primitive
Input group
Joined input wrapper for addons, icons, and focus-within rings.
Primitive
Dropzone
Composable file intake with validation, managed selection, and drag-activated overlays.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Phone input
International phone field with country search, E.164 values, and Zod validation helpers.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Command
Command palette with token-matched dialog, input, and result rows.
Primitive
Kbd
Keyboard shortcut chip and chord group.
Primitive
Checkbox
Single checkbox control with checked and indeterminate states.
Primitive
Radio group
Single-choice radio set for plans, filters, and option lists.
Primitive
Accordion
Stacked disclosure rows with measured panel animation.
Primitive
Avatar
Profile image with initials fallback and composable overlapping groups.
Primitive
Progress
Determinate task progress with optional label and value rows.
Primitive
Hover card
Hover or focus preview panel for profiles, links, and contextual details.
Primitive
Alert dialog
Modal confirmation dialog for destructive or blocking decisions.
Primitive
Menubar
Desktop command bar with nested menus, shortcuts, and separators.
Primitive
Navigation menu
Site navigation menu with a shared animated viewport.
Primitive
Field
Form field wrapper for labels, descriptions, errors, and validity state.
Primitive
Form
Form wrapper that coordinates field validation and returned errors.
Primitive
Native select
Native select control styled to match the Control UI control family.
Primitive
Textarea
Multiline text field with CSS-first auto-growth.
Primitive
Input OTP
One-time-code field with grouped, focus-aware slots.
Primitive
Combobox
Searchable single-select with input and floating option list.
Primitive
Alert
Inline status panel for callouts, errors, and notices.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Badge
Compact status, label, or count chip.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Card
Content surface for panels, tiles, and settings groups.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Table
Responsive data table for lists, comparisons, and structured records.
Primitive
Aspect ratio
CSS aspect-ratio wrapper for media and previews.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Button group
Joined button group for toolbars, split actions, and segmented controls.
Primitive
Empty
Empty-state layout for blank lists, zero results, and new workspaces.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Item
List row with media, content, and trailing actions.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Pagination
Page navigation for long lists and result sets.
Primitive
Spinner
Accessible loading indicator for pending buttons, panels, and inline waits.
Primitive
Meter
Static range meter for quota, storage, score, or usage values.
Primitive
Tree
Accessible tree view with roving keyboard navigation, single/multi selection, and animated disclosure.
Primitive
Checkbox Group
Multi-select checkbox set with shared state and select-all support.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Autocomplete
Free-text input with search-as-you-type suggestions.
Primitive
Number Field
Numeric input with stepper buttons and optional drag-to-change behavior.
Primitive
Trigger Menu
Caret-anchored command or mention menu for text editors.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Toolbar
Roving-focus toolbar for editor controls and compact actions.
Primitive
Dockable Panel
Non-modal workspace panel that moves between two explicit edge slots with a mobile Drawer fallback.
ExpExperimental — the contract and the rendering can change without notice. Own the installed copy before shipping it.Primitive
Infinite Canvas
Pan-and-zoom spatial workspace for arranging content without fixed bounds.
ExpExperimental — the contract and the rendering can change without notice. Own the installed copy before shipping it.Primitive
Morphing Panel
Accessible disclosure surface that morphs between explicit collapsed and expanded dimensions.
ExpExperimental — the contract and the rendering can change without notice. Own the installed copy before shipping it.Primitive
Color Picker
Color input with picker UI, formats, presets, and contrast helpers.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Gradient Editor
CSS gradient editor with draggable stops and live preview.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Resizable
Accessible resizable panel groups and split layouts with keyboard support.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Calendar
Date selection grid built on react-day-picker and themed through tokens.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Primitive
Typography
The token-driven type scale — one --text-* rung per size, named by role. Publish the utilities, not a component.
Primitive
Code
Shared code surface: Shiki-highlighted lines, gutter, clean copy, and virtualization for large files.
Primitive
Code Diff
Unified or split diff from a git patch or a before/after pair, with word-level intra-line highlighting.
Primitive
Markdown
Rendered agent markdown (GFM) whose code fences compose Code, and diff fences compose CodeDiff.
Primitive
Support files
useChatMessage
Typed role, density, and lifecycle state for ChatMessage.
Hook
useChatComposer
Controlled composer text and submit state.
Hook
useUserAsk
Question/option registration, selection, freeform text, and keyboard flow for UserAsk.
Hook
useAudioRecorder
Browser microphone recording state, waveform levels, and Blob completion.
Hook
useEnvironmentVariables
Editable environment variable rows with .env parsing, upload, duplicate detection, and submit helpers.
Hook
useCopyToClipboard
Copy-to-clipboard behavior with success state and fallback support.
Hook
cn
Tailwind class-name merge helper.
Util
skin
Skin slot and adornment resolvers for the Control UI library.
Util
serialize
Bridge a rich editor doc to plain text (and structured mentions) and back — independent of any one component.
Util
Use cases
Use cases
Start from complete workspace templates or focused interaction patterns, then own and adapt the installed source.
Use case
Chat
Controlled chat shell that composes rendered turns and a provider-owned composer.
Use case
Theme toggle
Controlled theme controls with a three-value switch, binary switch, cycle button, and dropdown.
Use case
Coding agent
Desktop coding workspace with project tasks, a focused conversation, and a persistent controlled composer.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Use case
Settings
Searchable multi-page settings shell with responsive navigation and accessible control groups.
Use case
File explorer
Finder-inspired file browser with locations, search, resizable columns, breadcrumbs, and an item preview.
BetaBeta — the props contract is close to final, but small breaking changes can still land.Use case