Project Awesome project awesome

Kamod UI

Lightweight Preact and Tailwind UI components (shadcn-style approach) (demo).

Package 2 stars GitHub

Kamod UI Kamod UI

Kamod UI

Lightweight UI components for Preact and Tailwind: composable primitives you can customize, extend, and ship without a heavy runtime. Open source; source is meant to be read and adapted.

hero

Why Kamod UI?

Many UI kits are heavier than necessary, overly opinionated, or tied to React. Kamod UI targets a smaller stack instead:

  • Preact-first — tiny runtime and familiar patterns if you already use React-like APIs.
  • Tailwind-native — style with utilities instead of a separate theme layer.
  • Composable — build UIs from small pieces without extra abstraction.
  • Practical — ship only what you need; the codebase stays easy to follow.

Comparison

Feature Kamod UI Radix UI shadcn/ui
Preact support
Tailwind-first ⚠️
Lightweight ⚠️ ⚠️

Live demo (GitHub Pages)

The deployed kitchen sink and docs live at the repository root URL of GitHub Pages, not under apps/demo (that path exists only in this monorepo):

https://kamod-ch.github.io/kamod-ui/

Documentation

Run the demo app from the repo root:

pnpm install
pnpm dev

Then open the local URL printed in the terminal to browse the kitchen sink and component docs.

Using Kamod UI

Install the component package in a Preact app:

pnpm add @kamod-ui/core preact

Kamod UI components ship JSX and Tailwind utility classes. Import the default theme once so Tailwind can compile the component classes and the components can read their semantic CSS tokens.

For Tailwind CSS v4, add this to the CSS file where you import Tailwind:

@import "tailwindcss";
@import "@kamod-ui/core/theme.css";

The theme import includes the required Tailwind source scan, dark variant and default semantic tokens.

Customize The Theme

Override the semantic tokens after importing the default theme:

@import "tailwindcss";
@import "@kamod-ui/core/theme.css";

:root {
  --primary: var(--color-fuchsia-700);
  --primary-foreground: var(--color-white);
  --radius: 0.75rem;
}

.dark {
  --primary: var(--color-fuchsia-400);
  --primary-foreground: var(--color-neutral-950);
}

If you want full control instead of the default theme, define the Tailwind mapping and token blocks yourself:

@import "tailwindcss";
@source "../node_modules/@kamod-ui/core/dist/**/*.{js,mjs}";

@custom-variant dark (&:where(.dark, .dark *));

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-secondary: var(--secondary);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-accent: var(--accent);
  --color-accent-foreground: var(--accent-foreground);
  --color-destructive: var(--destructive);
  --color-destructive-foreground: var(--destructive-foreground);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-ring: var(--ring);
  --color-outline: var(--outline);
}

:root {
  --background: var(--color-white);
  --foreground: var(--color-neutral-950);
  --card: var(--color-white);
  --card-foreground: var(--color-neutral-950);
  --popover: var(--color-white);
  --popover-foreground: var(--color-neutral-950);
  --primary: var(--color-neutral-950);
  --primary-foreground: var(--color-neutral-50);
  --secondary: var(--color-neutral-100);
  --secondary-foreground: var(--color-neutral-950);
  --muted: var(--color-neutral-100);
  --muted-foreground: var(--color-neutral-600);
  --accent: var(--color-neutral-100);
  --accent-foreground: var(--color-neutral-900);
  --destructive: var(--color-red-700);
  --destructive-foreground: var(--color-neutral-50);
  --border: var(--color-neutral-200);
  --input: var(--color-neutral-200);
  --ring: var(--color-neutral-400);
  --outline: var(--color-neutral-400);
  --radius: 0.625rem;
}

.dark {
  --background: var(--color-neutral-950);
  --foreground: var(--color-neutral-50);
  --card: var(--color-neutral-900);
  --card-foreground: var(--color-neutral-50);
  --popover: var(--color-neutral-800);
  --popover-foreground: var(--color-neutral-50);
  --primary: var(--color-neutral-50);
  --primary-foreground: var(--color-neutral-950);
  --secondary: var(--color-neutral-800);
  --secondary-foreground: var(--color-neutral-50);
  --muted: var(--color-neutral-800);
  --muted-foreground: var(--color-neutral-400);
  --accent: var(--color-neutral-800);
  --accent-foreground: var(--color-neutral-50);
  --destructive: var(--color-red-800);
  --destructive-foreground: var(--color-neutral-50);
  --border: --alpha(var(--color-neutral-50) / 10%);
  --input: --alpha(var(--color-neutral-50) / 15%);
  --ring: var(--color-neutral-500);
  --outline: var(--color-neutral-500);
}

The demo app keeps its extended token setup in apps/demo/src/styles/foundation.css and theme presets in apps/demo/src/styles/themes.css.

Contributing

  • Open issues for bugs and ideas.
  • Suggest new components or patterns.
  • Improve docs and examples.

Support

If you find Kamod UI useful:

  • Star the repository.
  • Share the project with others who use Preact or Tailwind.
Back to Preact