0 dependencies · 32 components · 25 blocks · 6 palettes

Components you own, not components you install.

Every PresetUI component is one JavaScript file with nothing foreign in it. You copy it in and it stops being ours — nothing to update, nothing to override. And when a project would rather have a dependency, the same files ship as @presetui/ui.

Change a token. Everything follows.

try a theme →

surface
#ffffff
fg
#0a0a0a
muted
#737373
border
#e5e5e5
accent
#0a0a0a
accent-fg
#ffffff
danger
#dc2626
danger-fg
#ffffff

optional

success
#16a34a
success-fg
#03190b
warning
#d97706
warning-fg
#241503
overlay
rgb(0 0 0 / 0.5)
NewDraft

Invite a teammate

They'll get access to every project in this workspace.

Nothing above was restyled. Each theme rewrites the same custom properties, and every component reads only those — which is why rebranding the kit is a stylesheet edit, not a refactor. All 6 palettes.

Blocks, not just parts

all 25 blocks →

Whole sections assembled from the components — headers, heroes, features, pricing, FAQs, auth screens, an app shell. A starting point you rewrite, rather than something you configure.

Three steps, then you're on your own

  1. 01

    Paste one @theme block

    A handful of CSS variables in your global stylesheet. This is the only code PresetUI components share.

  2. 02

    Copy one file

    Open a component, switch to the Source tab, paste it into components/ui/. It imports nothing but React, so nothing else comes with it.

  3. 03

    Change whatever you want

    It's an ordinary file in your repo now. Rename it, delete a variant, rewrite the markup. Nothing upstream can disagree.

32 components so far

see them all on one page →

Each page has three tabs: the live component, how you'd use it, and the file you copy.

Accordionaccordion.js

Collapsible sections built on native details elements.

Alertalert.js

Short message set apart from the surrounding text.

Avataravatar.js

Circular user image with a text fallback behind it.

Badgebadge.js

Compact label for status and metadata.

Breadcrumbbreadcrumb.js

Trail of links back up the hierarchy.

Buttonbutton.js

Clickable action element with four variants and three sizes.

Cardcard.js

Composable surface with header, content, and footer slots.

Checkboxcheckbox.js

Native checkbox with the box painted over.

Comboboxcombobox.js

Searchable select built on the combobox primitive.

Dialogdialog.js

Modal built on the native dialog element.

Dropdown Menudropdown-menu.js

Action menu with keyboard navigation, built on the menu primitive.

Inputinput.js

Single-line text field with an invalid state.

Kbdkbd.js

A keyboard key, for shortcuts written into prose.

Labellabel.js

Form label with an optional required marker.

Paginationpagination.js

Page navigation that collapses the middle to an ellipsis.

Popoverpopover.js

Floating panel anchored to a trigger, built on the popover primitive.

Progressprogress.js

Determinate progress bar in three sizes.

Radioradio.js

Native radio with the dot painted over.

Selectselect.js

Native dropdown with the platform arrow replaced.

Select Menuselect-menu.js

Custom select with styled options, built on the listbox primitive.

Separatorseparator.js

Dividing line, horizontal or vertical.

Sheetsheet.js

Edge panel built on the dialog primitive.

Skeletonskeleton.js

Placeholder block for content that hasn't arrived.

Sliderslider.js

Native range input with the track and thumb restyled.

Spinnerspinner.js

Indeterminate loading indicator in three sizes.

Switchswitch.js

On/off control built on a hidden checkbox.

Tabletable.js

Data table composed from the real table elements.

Tabstabs.js

Tabbed panels with arrow-key navigation.

Textareatextarea.js

Multi-line text field with an invalid state.

Toasttoast.js

Notification queue built on the toast primitive.

Tooltiptooltip.js

Hover and focus label, positioned with CSS alone.

Tooltip (JS)tooltip-js.js

Viewport-aware, Escape-dismissable tooltip on the tooltip primitive.

Built to be readable by an agent

The whole kit — theme and every component — is served as one plain text document. An agent fetches it once and writes the files. No registry format to parse, no CLI to install.

/llms.txtopen →
# PresetUI — zero-dependency
# React + Tailwind components
#
# Default mode: do NOT install
# from npm — write the files.

## Setup — @theme block
## Accordion— /r/accordion.txt
## Alert   — /r/alert.txt
## Avatar  — /r/avatar.txt
## Badge   — /r/badge.txt
## …and 28 more
say this to your agent

Read https://presetui.com/llms.txt and write the components into components/ui/ as .js files. Do not install any packages.

Copying against installing

Copying has real costs. Here they are next to the benefits — and since the kit is published as @presetui/ui, the right-hand column is also PresetUI. Pick per project.

PresetUIA component package
To start using itCopy a filenpm install
Where the code livesYour reponode_modules
Changing a variantEdit the fileOverride, fork, or file an issue
Breaking changesNone — nothing updatesWhenever you upgrade
What you shipThe lines you keptThe whole package
Class conflictsResolved by stylesheet orderResolved by tailwind-merge

The last row is the one that bites. Without tailwind-merge, a className that collides with one the component already sets is decided by stylesheet order, not by you. It's the price of the file carrying no dependencies.