@void-web-dev/kit
v0.3.1
Published
Accessible, themeable UI components built with native Web Components.
Maintainers
Readme
Voidkit UI
Accessible, themeable UI primitives built with native Web Components. Voidkit has no runtime framework and works in plain HTML, React, Vue, Svelte, Astro, or any environment that supports Custom Elements.
Highlights
- Native Custom Elements, Shadow DOM,
<dialog>andElementInternals - Keyboard navigation and ARIA behavior built into interactive patterns
- Light and dark themes through semantic CSS custom properties
- TypeScript declarations and ESM distribution
- Framework-agnostic, composed custom events
- Interactive documentation site included in the repository
Install
npm install @void-web-dev/kitimport "@void-web-dev/kit";
import "@void-web-dev/kit/tokens.css";Every component also has an independent entry-point. It registers only the source module required by that component instead of loading the complete library:
import "@void-web-dev/kit/button";
import "@void-web-dev/kit/dialog";
import "@void-web-dev/kit/live-search";
import "@void-web-dev/kit/tokens.css";<void-button variant="outline">Deploy</void-button>
<void-input
label="Email"
type="email"
placeholder="[email protected]"
description="We'll only use this for account notifications."
></void-input>Input Group
<void-input-group>
<void-input-group-input placeholder="Search..." aria-label="Search"></void-input-group-input>
<void-input-group-addon align="inline-start" id="search-icon"></void-input-group-addon>
<void-input-group-addon align="inline-end">
<void-input-group-button aria-label="Clear" size="icon-xs" id="clear-icon"></void-input-group-button>
</void-input-group-addon>
</void-input-group>
<script type="module">
import { lucideIcon, Search, X } from "@void-web-dev/kit/icons";
document.querySelector("#search-icon").innerHTML = lucideIcon(Search);
document.querySelector("#clear-icon").innerHTML = lucideIcon(X);
</script>Addon alignment accepts inline-start, inline-end, block-start, and block-end. Native or third-party inputs can opt in with data-slot="input-group-control".
Semantic variants
Buttons, alerts, and toast notifications support info, warning, and success in addition to the existing default and destructive variants. Attribute and JavaScript values are case-insensitive.
<void-button variant="INFO">Details</void-button>
<void-button variant="WARNING">Review</void-button>
<void-button variant="SUCCESS">Published</void-button>
<void-alert variant="SUCCESS">
<strong slot="title">Deployment complete</strong>
Production is now up to date.
</void-alert>toast({ title: "Saved", variant: "SUCCESS" });
toast({ title: "Storage limit", variant: "WARNING" });Resizable panels
<void-resizable direction="horizontal" aria-label="Workspace layout">
<void-resizable-panel default-size="30" min-size="20">Sidebar</void-resizable-panel>
<void-resizable-handle with-handle></void-resizable-handle>
<void-resizable-panel default-size="70" min-size="30">Content</void-resizable-panel>
</void-resizable>Use direction="horizontal" for panels arranged from left to right and direction="vertical" for stacked panels. Horizontal is the default when the attribute is omitted. The current orientation is also available through the direction property. Each panel accepts default-size, size, min-size, and max-size as percentages. Handles support pointer dragging, arrow keys, Home, and End. Set all sizes programmatically with element.setSizes([30, 70]) and read the current percentages from element.sizes.
Components
Voidkit currently provides 104 registered custom elements covering shadcn-style primitives plus advanced form, data, navigation, and display patterns.
| Category | Elements |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Actions | void-button, void-button-group, void-toggle, void-toggle-group, void-toolbar |
| Forms | void-input, void-number-input, void-textarea, void-input-group, void-input-otp, void-tags-input, void-file-upload, void-dropzone, void-checkbox, void-switch, void-radio-group, void-rating, void-slider, void-select, void-native-select, void-combobox, void-live-search, void-color-picker, void-calendar, void-date-picker, void-date-range-picker, void-time-picker, void-field, void-fieldset, void-label |
| Display | void-card, void-badge, void-tag, void-alert, void-avatar, void-separator, void-skeleton, void-progress, void-progress-circle, void-stat, void-timeline, void-descriptions |
| Data | void-table, void-data-table, void-chart, void-item, void-empty, void-typography, void-kbd |
| Navigation | void-tabs, void-accordion, void-breadcrumb, void-pagination, void-navigation-menu, void-sidebar, void-stepper, void-tree-view |
| Menus | void-command, void-dropdown-menu, void-context-menu, void-menubar |
| Overlays | void-dialog, void-alert-dialog, void-sheet, void-drawer, void-popover, void-hover-card, void-tooltip |
| Layout | void-aspect-ratio, void-collapsible, void-carousel, void-resizable, void-scroll-area, void-direction |
| Chat | void-message-scroller, void-message, void-bubble, void-attachment, void-marker |
| Feedback | void-toaster, void-sonner, void-spinner, toast() |
Advanced form controls
<void-number-input label="Seats" value="3" min="1" max="20"></void-number-input>
<void-tags-input label="Technologies" value="Web Components,TypeScript"></void-tags-input>
<void-file-upload label="Assets" accept="image/*" multiple max-files="5" max-size="5242880"></void-file-upload>
<void-live-search label="City" placeholder="Start typing…" min-length="1">
<void-option value="paris" keywords="france">Paris</void-option>
<void-option value="porto" keywords="portugal">Porto</void-option>
</void-live-search>
<void-date-range-picker label="Reporting period" start="2026-07-01" end="2026-07-31"></void-date-range-picker>Form-associated controls submit through ElementInternals. Their public values remain available through properties such as value, values, files, and selectedValues.
Keyboard-first navigation
<void-toolbar label="Text formatting">
<void-toggle>Bold</void-toggle>
<void-toggle>Italic</void-toggle>
</void-toolbar>
<void-stepper value="account" linear>
<void-step value="account" label="Account"></void-step>
<void-step value="profile" label="Profile"></void-step>
<void-step value="complete" label="Complete"></void-step>
</void-stepper>
<void-tree-view label="Project files">
<void-tree-item value="src" label="src" expanded>
<void-tree-item value="index" label="index.ts"></void-tree-item>
</void-tree-item>
</void-tree-view>Toolbar, Stepper, Tree View, Combobox, menus, and listboxes provide roving focus and the appropriate arrow-key behavior.
Data Table
<void-data-table
search
selectable
row-key="id"
page-size="10"
columns='[{"key":"name","label":"Name","sortable":true},{"key":"status","label":"Status"}]'
data='[{"id":"a","name":"Atlas","status":"Live"}]'
></void-data-table>Data Table supports client-side search, sorting, pagination, row selection, column visibility, loading skeletons, and empty states.
Events
Components emit bubbling, composed events so they cross shadow boundaries:
document.querySelector("void-select").addEventListener("void-change", event => {
console.log(event.detail.value);
});The shared events are void-input, void-change, void-toggle, void-close, void-dismiss, and void-resize.
Theming
Set data-theme="dark" on any ancestor or override semantic tokens:
:root {
--void-primary: oklch(0.55 0.2 260);
--void-radius: 0.8rem;
--void-font-sans: "Geist", sans-serif;
}Component internals remain encapsulated. Stable surfaces such as the button control are exposed through part attributes where targeted customization is useful.
Development
npm install
npm run dev
npm test
npm run buildThe test suite includes a synchronized registry test for every void-* custom element. Adding a new component without adding its fixture causes the suite to fail, so component coverage cannot silently drift.
The project outputs the documentation site to site/ and the publishable library to dist/.
Browser support
Voidkit targets current evergreen browsers. It relies on Custom Elements, Shadow DOM, CSS custom properties, and form-associated custom elements.
License
MIT
