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
- success
- #16a34a
- success-fg
- #03190b
- warning
- #d97706
- warning-fg
- #241503
- overlay
- rgb(0 0 0 / 0.5)
optional
Invite a teammate
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.
Header2
Hero3
Features3
Stats2
Logo cloud1
Testimonials2
Pricing2
FAQ2
Call to action2
Auth2
App shell2
Footer2
Three steps, then you're on your own
- 01
Paste one @theme block
A handful of CSS variables in your global stylesheet. This is the only code PresetUI components share.
- 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.
- 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
Alertalert.js
Avataravatar.js
Badgebadge.js
Breadcrumbbreadcrumb.js
Buttonbutton.js
Cardcard.js
Checkboxcheckbox.js
Comboboxcombobox.js
Dialogdialog.js
Dropdown Menudropdown-menu.js
Inputinput.js
Kbdkbd.js
Labellabel.js
Paginationpagination.js
Popoverpopover.js
Progressprogress.js
Radioradio.js
Selectselect.js
Select Menuselect-menu.js
Separatorseparator.js
Sheetsheet.js
Skeletonskeleton.js
Sliderslider.js
Spinnerspinner.js
Switchswitch.js
Tabletable.js
Tabstabs.js
Textareatextarea.js
Toasttoast.js
Tooltiptooltip.js
Tooltip (JS)tooltip-js.js
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.
# 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
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.
| PresetUI | A component package | |
|---|---|---|
| To start using it | Copy a file | npm install |
| Where the code lives | Your repo | node_modules |
| Changing a variant | Edit the file | Override, fork, or file an issue |
| Breaking changes | None — nothing updates | Whenever you upgrade |
| What you ship | The lines you kept | The whole package |
| Class conflicts | Resolved by stylesheet order | Resolved 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.