Skip to Content
Introduction

Wire UI

A headless, unstyled React 19 component library. Components ship with zero CSS — style them entirely with your own classes and CSS by targeting data-* attributes that reflect interactive state.

Why Wire UI?

Most component libraries bundle design decisions you can’t escape. Wire UI takes the opposite approach: every component is a behaviour primitive. You get the logic, accessibility, and state tracking — nothing else.

// Wire UI ships no styles. This is all you get: <Button onClick={handleClick}>Save</Button> // Style it however you want using data-* attributes: <Button className=" px-4 py-2 rounded bg-blue-600 text-white [data-hover]:bg-blue-700 [data-active]:scale-95 [data-focus-visible]:ring-2 [data-disabled]:opacity-50 "> Save </Button>

Core principles

Unstyled by default. No CSS shipped. No design opinions. You own the design system.

State via data-* attributes. Every interactive state (hover, focus, active, disabled, open/closed) is exposed as a data attribute — empty string when active, absent when not. Style with CSS attribute selectors.

Compound components. Complex widgets follow the Component.Part pattern. You compose the markup, control the order, and add whatever wrapper elements you need.

Consumer-owned validation. Form components expose invalidType and errorMessage props but perform no validation internally. Set invalidType when your validation logic decides it’s invalid — the component renders the error state.

asChild for polymorphism. Pass asChild to Button to merge all props onto your own child element — great for router links and icon buttons.

Components

Last updated on

MIT License © 2026 wire-ui