Componentes acessíveis para Preact + htm, distribuídos como ES modules nativos — sem build step, sem JSX e sem bundler.
HTM UI mantém APIs compostas e tokens compatíveis com o ecossistema shadcn/ui, mas possui implementação, catálogo e identidade próprios.
Use diretamente via <script type="importmap"> ou importe de CDNs como esm.sh.
- htm — JSX-like syntax in template literals
- Preact — Fast 3kB alternative to React
- Tailwind CSS v4 — via
@tailwindcss/browser - clsx + tailwind-merge — class merging via
cn() - iconify-icon — Universal icon component
<script type="importmap">
{
"imports": {
"htm-ui": "https://cdn.jsdelivr.net/gh/djalmajr/htm-ui@main/packages/ui/index.js",
"htm-ui/": "https://cdn.jsdelivr.net/gh/djalmajr/htm-ui@main/packages/ui/",
"clsx": "https://esm.sh/clsx@2",
"tailwind-merge": "https://esm.sh/tailwind-merge@3",
"htm/preact": "https://esm.sh/htm@3/preact?external=preact",
"preact": "https://esm.sh/preact@10",
"preact/": "https://esm.sh/preact@10/"
}
}
</script>import { html } from 'htm/preact'
import { Button } from 'htm-ui/button.js'
function App() {
return html`<${Button} variant="outline">Click me<//>`
}import { Button } from 'htm-ui/button.js'The per-file path (htm-ui/<name>.js) is the primary, documented API. A barrel
index.js (export *) also exists for the bare-specifier convenience path:
import { Button, Card, Dialog } from 'htm-ui'Install the project-aware HTM UI skill directly from this repository:
bunx skills add djalmajr/htm-ui --skill htm-uiThe skill lives in skills/htm-ui and provides component-selection, theming, migration, source-inspection, and browser-validation guidance.
packages/ui/ Components library
apps/docs/ Docs: components reference + examples (flagship)
apps/todo/ Todo app example
apps/site/ Legacy docs site
skills/htm-ui/ Project-aware agent skill
bun run dev # → bunx serve . -l 4123 (fixed port avoids collisions)
open http://localhost:4123/apps/docs/ # components reference + examples
open http://localhost:4123/apps/todo/ # todo exampleCustom domain via Portless
Portless maps a stable htm-ui.localhost URL to the dev server (no port to
remember). Run the proxy and the alias on the machine that owns the browser
— e.g. the Windows host for a WSL checkout, since the proxy binds :80/:443
there and the WSL server is reachable on localhost:4123:
# once per machine
portless proxy start # HTTPS proxy daemon
portless trust # trust the local CA
# map the domain to the running dev server (host side)
portless alias htm-ui 4123 # → http://htm-ui.localhost -> localhost:4123Then bun run dev (in WSL) + open http://htm-ui.localhost/apps/docs/.
If the Portless proxy is local to where you run the server (no WSL/host split),
bun run dev:portless (portless htm-ui bunx serve .) starts the server under
Portless directly and Portless assigns the port.
Theming is just CSS custom properties — no config files to recompile. Tokens live in
packages/ui/theme.css (:root for light, .dark for dark) and each app maps them to
Tailwind utilities via a @theme inline block. Any shadcn/ui
or tweakcn theme drops in by replacing the :root/.dark blocks
in theme.css. See THEMING.md for the full guide, including the canonical
Tailwind block and dark-mode toggle.
| Component | Import |
|---|---|
| Accordion | htm-ui/accordion.js |
| Alert | htm-ui/alert.js |
| AlertDialog | htm-ui/alert-dialog.js |
| AspectRatio | htm-ui/aspect-ratio.js |
| Avatar | htm-ui/avatar.js |
| Badge | htm-ui/badge.js |
| Breadcrumb | htm-ui/breadcrumb.js |
| Button | htm-ui/button.js |
| ButtonGroup | htm-ui/button-group.js |
| Calendar | htm-ui/calendar.js |
| Card | htm-ui/card.js |
| Carousel | htm-ui/carousel.js |
| Chart | htm-ui/chart.js |
| Checkbox | htm-ui/checkbox.js |
| Collapsible | htm-ui/collapsible.js |
| Combobox | htm-ui/combobox.js |
| Command | htm-ui/command.js |
| ContextMenu | htm-ui/context-menu.js |
| Dialog | htm-ui/dialog.js |
| Drawer | htm-ui/drawer.js |
| DropdownMenu | htm-ui/dropdown-menu.js |
| Empty | htm-ui/empty.js |
| Field | htm-ui/field.js |
| HoverCard | htm-ui/hover-card.js |
| Icon | htm-ui/icon.js |
| Input | htm-ui/input.js |
| InputGroup | htm-ui/input-group.js |
| InputOTP | htm-ui/input-otp.js |
| Item | htm-ui/item.js |
| Kbd | htm-ui/kbd.js |
| Label | htm-ui/label.js |
| MaskInput | htm-ui/mask-input.js |
| Menubar | htm-ui/menubar.js |
| NativeSelect | htm-ui/native-select.js |
| NavigationMenu | htm-ui/navigation-menu.js |
| Pagination | htm-ui/pagination.js |
| Popover | htm-ui/popover.js |
| Progress | htm-ui/progress.js |
| RadioGroup | htm-ui/radio-group.js |
| Resizable | htm-ui/resizable.js |
| ScrollArea | htm-ui/scroll-area.js |
| Select | htm-ui/select.js |
| Separator | htm-ui/separator.js |
| Sheet | htm-ui/sheet.js |
| Sidebar | htm-ui/sidebar.js |
| Skeleton | htm-ui/skeleton.js |
| Slider | htm-ui/slider.js |
| Sonner | htm-ui/sonner.js |
| Spinner | htm-ui/spinner.js |
| Switch | htm-ui/switch.js |
| Table | htm-ui/table.js |
| Tabs | htm-ui/tabs.js |
| Textarea | htm-ui/textarea.js |
| Toggle | htm-ui/toggle.js |
| ToggleGroup | htm-ui/toggle-group.js |
| Tooltip | htm-ui/tooltip.js |
MIT