One component library. Every framework.
Build your UI once with Lit web components and use it everywhere—React, Vue, Svelte, Angular, or plain HTML. No wrappers, no adapters, no framework lock-in.
Most component libraries force you to pick a framework and stick with it. If your team uses React today but migrates to Vue tomorrow, you rewrite your UI.
LitUI solves this:
- True interoperability — Web components work natively in any framework
- Tailwind CSS v4 — Modern styling with design tokens
- Accessible — ARIA, keyboard navigation, focus management
- TypeScript — Full type definitions included
- Dark mode — Built-in theme support
npm install lit-ui litOr use the CLI:
npx lit-ui init
npx lit-ui add button dialogimport 'lit-ui/button';<ui-button variant="primary">Click me</ui-button>Works the same in React, Vue, Svelte, or vanilla HTML.
<ui-button variant="primary">Primary</ui-button>
<ui-button variant="secondary">Secondary</ui-button>
<ui-button variant="outline">Outline</ui-button>
<ui-button variant="ghost">Ghost</ui-button>
<ui-button variant="destructive">Delete</ui-button><ui-dialog id="my-dialog">
<span slot="title">Confirm</span>
<p>Are you sure?</p>
<div slot="footer">
<ui-button variant="ghost">Cancel</ui-button>
<ui-button variant="primary">Confirm</ui-button>
</div>
</ui-dialog>import 'lit-ui/button';
function App() {
return <ui-button onClick={() => alert('Clicked!')}>Click me</ui-button>;
}<script setup>
import 'lit-ui/button';
</script>
<template>
<ui-button @click="handleClick">Click me</ui-button>
</template><script>
import 'lit-ui/button';
</script>
<ui-button on:click={() => alert('Clicked!')}>Click me</ui-button><script type="module" src="https://unpkg.com/lit-ui/dist/button.js"></script>
<ui-button>Click me</ui-button>CSS custom properties for global theming:
:root {
--color-primary: oklch(0.55 0.2 250);
--radius-md: 0.5rem;
}::part() selectors for targeted styling:
ui-button::part(base) {
font-weight: 600;
}Tailwind class passthrough for one-off customization:
<ui-button class="shadow-lg">Elevated</ui-button>- Input
- Select
- Checkbox / Radio
- Tabs
- Toast
- Tooltip
- Popover
We welcome contributions! Please see our Contributing Guide for details.
Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
pnpm install # Install dependencies
pnpm dev # Start dev server
pnpm build # Build libraryThis project uses Changesets for versioning and npm publishing.
When you make changes that should be released, create a changeset:
pnpm changesetSelect the affected packages, choose a semver bump type (patch/minor/major), and describe the change.
- New features, bug fixes, or breaking changes to public packages
- API changes that consumers need to know about
- Internal tooling or CI fixes
- Documentation-only changes
- Changes to private or example packages
- PRs with changesets are merged to
main - CI automatically creates a "Version Packages" PR that bumps versions and updates changelogs
- Merging the version PR triggers npm publish