Web standards first
Real <button>, real aria-pressed, real focus management. No reinventing what the platform already ships.
A web-standards component library for htmx v4 + Tailwind v4. One source of truth — five flavours: Hono JSX, Jinja2, Go templates, Phoenix, and raw HTML. Copy what you need, ship in any stack.
Real <button>, real aria-pressed, real focus management. No reinventing what the platform already ships.
Hono JSX, Jinja2, Go templates, Phoenix function components, and a raw HTML snippet — all generated from the same source of truth.
Install via npx shadcn add, curl the source file straight into your templates folder, or copy-paste the snippet. Your code, your style.
CSS-first config with @theme, @utility, and the Oxide engine. No legacy tailwind.config.js.
Each component follows the WAI-ARIA Authoring Practices contract — keyboard interaction, focus management, ARIA roles, all checked against the spec source.
All components type the v4 attribute set — hx-disable, the renamed swap modifiers, the new request lifecycle hooks.
Sponsors
shadcn-htmx is open source and free to use. Sponsorship pays for maintenance time, new components, and keeping the docs current with htmx and Tailwind upstream releases.
Thank you to everyone supporting the project. Tiers are sized by sponsorship amount.
github.com/sponsors/productdevbook →Sponsors updated 2026-06-03.
Components
Each ships with the same install, live examples, and source view across all five frameworks — Hono JSX, Jinja2, Go templates, Phoenix, and raw HTML.
Native typeahead — datalist suggestions, htmx-streamed.
Live result region for a calculation or server action — native <output> with an implicit aria-live so htmx swaps announce themselves.
{ label: "Segmented Control", href: "/docs/segmented-control", blurb: "Joined radio bar — pick a value, not a panel." },
{ label: "Rating", href: "/docs/rating", blurb: "Star rating as a native radio group — per-star labels, CSS hover preview, submits a real value. Zero JS." },
Color Picker — native <input type="color"> styled as a shadcn swatch with an optional live hex readout. The browser owns the whole picker UI and validates the CSS color.
Autosize Textarea — a <textarea> that grows and shrinks to fit its content between min/max bounds using one CSS line (field-sizing: content) instead of the classic scrollHeight JS loop. Zero JavaScript; degrades to a plain fixed field where unsupported.
Cascading Select — a pair of dependent native selects where picking the parent reloads the child's options (and an optional detail card) from the server in one request, using htmx's default change trigger plus an hx-swap-oob fragment. No JavaScript.
Field-row wrapper composing label, control, description, and error — auto-wiring aria-describedby and a native :user-invalid styling hook. Plus a fieldset/legend group variant. Zero JS.
Drag-and-drop or click to pick files — a native file input with previews and a multipart upload bar.
Native date, time, datetime-local, month and week fields with min/max/step constraints and normalized values — a web-standards date/time picker with no JS calendar library.
Debounced live-search box that filters a results list as you type — inline spinner, stale-request cancellation, and a no-JS Enter fallback.
Read-only record that swaps to a pre-filled form; Save PUTs, Cancel re-fetches.
Six variants, four sizes, toggle + htmx hooks.
Native types, ARIA-invalid, htmx live search.
Auto-resize via field-sizing, htmx autosave.
Click-to-focus, peer-disabled aware.
Indeterminate support, peer-checked indicator.
Native datalist + htmx-filtered listbox.
role=switch pill, save-on-toggle pattern.
Arrow-key cycle straight from the platform.
Native dropdown, cascading htmx demo.
Native range, full keyboard contract.
Native number spinbutton with −/+ steppers
Two-thumb range from native range inputs
Scrollable single/multi-select list (APG listbox)
Native details/summary, exclusive via shared name — zero JS.
Constrained-overflow region with a themed native scrollbar and CSS-only fade masks that hint at more content — zero JavaScript.
The bare scroll-snapping rail — gallery strip, chip row, media shelf, date rail. Pure CSS scroll-snap, zero JavaScript.
Container Card — a card that adapts to its own width, not the viewport. The same markup stacks in a sidebar and goes side-by-side in a wide column, using CSS container queries. No JavaScript.
Header that pins on scroll and reacts the instant it sticks — shadow + solid background via @container scroll-state(stuck), no sentinel, zero JS.
Lock images, videos, and embeds to a fixed ratio that resizes fluidly — native CSS aspect-ratio, no layout shift, no JavaScript.
Responsive grid that wraps into as many equal columns as fit — no breakpoints.
Header / Content / Footer slots.
Semantic table, sortable via aria-sort.
Native single show/hide disclosure
Group controls in one arrow-navigable tab stop
Interactive data grid with 2-D arrow-key cell navigation
Expandable hierarchical grid (role=treegrid)
Resizable two-pane split with a draggable divider
Accessible landmark page-shell, native elements
Kbd — an inline keyboard-key badge. Renders a native <kbd> for a single key or nests one per key for shortcuts like Ctrl + Shift + R, the way command menus, docs, and tooltips show keystrokes. Phrasing content with no implicit role, so it ships zero JavaScript.
Highlight — wrap the words that matched a search query in a native <mark>. Server-rendered, theme-token styled, zero JS; rides along in the fragment htmx swaps into your results list.
{ label: "Relative Time", href: "/docs/relative-time", blurb: "Semantic <time> timestamp — server renders a machine-readable datetime plus a human label; a tiny script re-localises to the visitor's locale and degrades to the server value with no JS." }
Captioned, self-contained content — image, diagram, code, or quote — in a native <figure> whose <figcaption> is its accessible name. No JS.
Responsive Image — art-directed, format-switching image on native <picture> + <source>. Light/dark, AVIF/WebP/JPEG, per-viewport crops, all selected by the browser. Zero JS.
Style a native HTML5 video or audio player — multiple source formats, WebVTT caption tracks, poster, and aspect-ratio framing. The browser provides the full accessible playback UI (play, scrub, volume, captions, fullscreen, PiP). Zero JavaScript.
Data table with row checkboxes, select-all, and a bulk-action bar revealed by CSS :has(:checked). Bulk actions hx-post the checked rows.
Confirm, DELETE, fade out — in place. One inherited declaration covers every row.
Click-to-copy button built on the Async Clipboard API with a progressive-enhancement fallback. Flips to a transient aria-live "Copied" state. The docs code-block is a consumer.
Image with text/icon fallback on 404.
Six variants; renders span or anchor.
Decorative or semantic divider.
Native scroll-snap slideshow with APG carousel roles
Reading-position bar that fills as you scroll — pure animation-timeline: scroll(), zero JS.
Instant like/follow/pin toggle — flips optimistically, reconciles with the server, rolls back on error.
{ label: "Status", href: "/docs/status", blurb: "Polite live region for non-urgent updates — role=status/log, htmx swap-in." }
Defer slow content past first paint — the container fetches its own body after render and swaps it in, with reserved space so the page never jumps.
Five variants + live-region politeness.
role=progressbar, htmx polling demo.
role=status placeholder, outerHTML swap.
Server-driven via htmx beforeend swap.
Native <meter> gauge, low/high/optimum zones.
Infinite-scroll list of articles, APG feed pattern
Edge-anchored drawer on native <dialog> — focus trap, ESC, light dismiss.
Rich preview card on hover/focus — interactive content, zero JS, native interest invokers.
Native <dialog>: focus trap, ESC, backdrop.
Popover API + APG menu keyboard contract.
Native Popover API, light dismiss + ESC.
CSS hover/focus reveal, ESC to dismiss.
Confirm consequential actions, no backdrop dismiss
Primary action welded to a disclosure toggle — one click for the default, the chevron for the rest.
Responsive app-nav sidebar — a fixed rail on desktop, an off-canvas drawer behind a labelled hamburger on mobile. Real anchors, CSS grid + :target, opens and closes with zero JavaScript.
Self-replacing pagination — button or scroll sentinel, zero JS.
Skip Link — a visually-hidden-until-focused "Skip to main content" link, the first focusable element on the page, jumping keyboard focus to the main landmark. Native <a href="#main"> + CSS focus reveal, zero JS.
Theme Toggle — light / dark / system colour-scheme switcher. Honours prefers-color-scheme by default, persists an explicit override in a cookie for a no-flash server render, and ships as a native radiogroup with full keyboard support.
Native details/summary, exclusive via name.
nav landmark, aria-current on active page.
role=tab, arrow / Home / End contract.
Path-to-page trail: native nav + ol of links
Native anchor; underlined/muted/hover + external.
App-style menubar of native popover menus
Hierarchical role=tree with APG keyboard nav