Shadcn/ui

Build extension UI with accessible, composable components using the same shadcn/ui workflow used in web apps. This is useful when your team wants reusable design primitives instead of custom ad-hoc UI per surface.

Extension.js supports shadcn/ui best through a Tailwind-enabled React setup.

When shadcn/ui is a good fit

  • You need reusable UI primitives across sidebar, popup, and options surfaces.
  • You already use React + Tailwind in product code.
  • You want source-owned components that your team can fully customize.

shadcn/ui capabilities

Capability What it gives you
Source-owned UI components Keep generated components/ui/* files versioned in your project
React + Tailwind alignment Use the same authoring model as modern web app stacks
Extension-surface reuse Share component primitives across sidebar, popup, and options pages
Gradual adoption Start from a template, then scale component coverage over time

Template examples

Use the sidebar-shadcn template as the default starting point:

sidebar-shadcn screenshot

npm
pnpm
yarn
npx extension@latest create my-extension --template=sidebar-shadcn

This template includes a working React sidebar UI with Tailwind + shadcn-style component structure.

Repository: examples/sidebar-shadcn

Stack assumptions

  • React + TypeScript
  • Tailwind CSS
  • PostCSS (@tailwindcss/postcss)
  • Local components/ui/* component files (shadcn-style structure)

Manual setup in an existing project

  1. Set up Tailwind and PostCSS (see Tailwind CSS).
  2. Initialize shadcn in your project and generate components.
  3. Keep generated UI components inside your extension source (for example src/components/ui/).
  4. Import your Tailwind stylesheet in the extension entry where UI renders.

PostCSS example (Tailwind v4)

export default {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};

Example components.json

{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "tsx": true,
  "tailwind": {
    "css": "sidebar/styles.css",
    "cssVariables": true
  }
}

Usage

Use generated components from local imports:

import { Button } from "@/components/ui/button";
import "./styles.css";

export default function MyComponent() {
  return <Button className="text-lg font-semibold">Click Me</Button>;
}

Video demo soon: shadcn component workflow

Content script notes

  • Extension pages (popup/options/sidebar/new tab) are the easiest place to start with shadcn/ui.
  • For content scripts, ensure your style entry is imported in the content-script entrypoint.
  • Content-script styles are emitted through Extension.js content-script CSS pipeline and can still conflict with host page styles.

If you need stronger isolation for content scripts, prefer mounting inside an isolated root strategy and keep class scopes intentional.

Best practices

  • Treat shadcn/ui as source-owned components, not a runtime UI package import.
  • Keep Tailwind config/content paths aligned with your extension folders (pages, scripts, src).
  • Start with one surface (like sidebar or popup) before adding content-script rendering complexity.
  • Keep shared tokens and utility helpers in dedicated files (lib/utils, design tokens, theme variables).

Next steps