shadcn-html / introduction
A UI component system
that scales with AI.
Themeable components built on semantic HTML, modern CSS, and vanilla JavaScript.
No framework. No build step. No abstraction layers to get wrong.
The simplest possible foundation for AI-driven prototyping.
Built on five layers.
Tokens. Component skill. CSS. HTML. JavaScript (if needed). That's the whole system.
1 — semantic tokens
/* default-semantic-tokens.css — the design system */
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0.005 285);
--primary: oklch(0.205 0.005 285);
--primary-foreground: oklch(0.985 0.002 247);
--border: oklch(0.88 0.004 247);
--radius: 0.625rem;
/* ...all color pairs, shadows, spacing */
}
.dark { /* same keys, dark values */ }
2 — component-skill.md file
# Pattern: Button
## Native basis
`<button>` element. Also works on `<a>` for link-style buttons.
## Native Web APIs
- `<button>` — native clickable element with built-in keyboard and form support
- `:focus-visible` — keyboard-only focus ring
- `commandfor` / `command` — declarative button→dialog/popover triggers without JS
# ...prefers-reduced-motion, prefers-contrast, forced-colors
## Structure
<button class="btn" data-variant="default">Click me</button>
## Variants
| data-variant | Surface | Text | Hover |
|---------------|----------------------|--------------------------|-----------------|
| default | --primary | --primary-foreground | opacity: 0.88 |
| secondary | --secondary | --secondary-foreground | opacity: 0.8 |
| outline | --background + border | --foreground | --accent bg |
| ghost | transparent | --foreground | --accent bg |
| destructive | --destructive | --destructive-foreground | opacity: 0.88 |
| link | transparent | --primary | underline |
# ...sizes, accessibility, notes
3 — component CSS
/* button.css — styled with tokens */
@layer components {
.btn {
display: inline-flex;
align-items: center;
border-radius: var(--radius-md);
font-weight: 500;
}
.btn[data-variant="default"] {
background: var(--primary);
color: var(--primary-foreground);
}
/* ...secondary, destructive, outline, ghost, link */
}
4 — semantic HTML
<button class="btn" data-variant="default"
data-dialog-trigger="confirm">
Open Dialog
</button>
<dialog id="confirm" class="dialog">
<div class="dialog-content">...</div>
</dialog>
5 — vanilla JavaScript (if needed)
// dialog.js — wire interactivity
function init() {
document.querySelectorAll('[data-dialog-trigger]:not([data-init])').forEach((trigger) => {
trigger.dataset.init = '';
const dialog = document.getElementById(trigger.dataset.dialogTrigger);
if (!dialog) return;
trigger.addEventListener('click', () => dialog.showModal());
});
/* ...close-on-backdrop, [data-dialog-close] buttons, focus restore */
}
init();
new MutationObserver(init).observe(document, { childList: true, subtree: true });