npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

shadcn-theme-kit

v1.0.1

Published

Easy theme configuration for React + shadcn with light/dark mode, preset themes, and CSS variables

Readme

shadcn-theme-kit

Easy theme configuration for React + shadcn with light/dark mode, preset themes, and CSS variables.

npm version License: MIT

Features

  • 🎨 7 Preset Themes - blue, rose, emerald, orange, violet, slate, default
  • 🌙 Dark/Light/System Mode - Each theme has both light AND dark colors
  • 💾 Persistence - localStorage saves user preference
  • 🔒 Zero Dependencies - Core has no runtime dependencies
  • 📦 TypeScript First - Full strict mode support

Why Use shadcn-theme-kit?

| Problem | Solution | | ------------------------------------------------- | -------------------------------------- | | ❌ Manually editing globals.css for every color | ✅ Just pick a preset or define once | | ❌ Writing separate dark mode CSS | ✅ Light + Dark built into every theme | | ❌ No persistence - user has to choose every time | ✅ Auto-saved to localStorage | | ❌ Complex setup with CSS variables | ✅ 3 lines of code to get started | | ❌ Theme switching requires page reload | ✅ Instant switch, no reload |

Before (Manual Way) 😫

/* globals.css - You had to write ALL this manually */
:root {
  --background: #ffffff;
  --foreground: #0a0a0a;
  --primary: #2563eb;
  /* ... 15+ more variables */
}

.dark {
  --background: #0a0a0a;
  --foreground: #fafafa;
  --primary: #3b82f6;
  /* ... 15+ more variables AGAIN */
}

After (With shadcn-theme-kit) 😎

// Just 3 lines!
<ThemeProvider theme={presets.blue}>
  <App />
</ThemeProvider>

How CSS Classes Work

Available CSS Classes

These classes work automatically once you wrap your app:

| Class | Description | Light Mode | Dark Mode | | ----------------------- | ------------------- | ---------- | ------------ | | bg-background | Main background | White | Dark | | bg-foreground | Inverted background | Dark | White | | bg-primary | Primary brand color | Blue | Lighter blue | | bg-secondary | Secondary color | Light gray | Dark gray | | bg-muted | Muted sections | Light gray | Dark gray | | bg-accent | Accent areas | Light gray | Dark gray | | bg-destructive | Error/danger | Red | Red | | bg-card | Card background | White | Dark | | text-foreground | Main text | Dark | White | | text-primary | Primary text | Blue | Blue | | text-muted-foreground | Muted text | Gray | Lighter gray | | border-border | Borders | Light gray | Dark gray |

Example: Same Class, Different Modes

┌─────────────────────────────────────────────────────────────┐
│  className="bg-primary text-primary-foreground"            │
│                                                             │
│  ┌─────────────────────┐    ┌─────────────────────┐        │
│  │   🌞 LIGHT MODE     │    │   🌙 DARK MODE      │        │
│  │                     │    │                     │        │
│  │   bg: #2563eb       │    │   bg: #3b82f6       │        │
│  │   text: #ffffff     │    │   text: #ffffff     │        │
│  │                     │    │                     │        │
│  │   ┌─────────────┐   │    │   ┌─────────────┐   │        │
│  │   │   Button    │   │    │   │   Button    │   │        │
│  │   └─────────────┘   │    │   └─────────────┘   │        │
│  └─────────────────────┘    └─────────────────────┘        │
│                                                             │
│  SAME CLASS → DIFFERENT COLORS based on mode!              │
└─────────────────────────────────────────────────────────────┘

Code Example

// This button looks different in light vs dark mode automatically!
<button className="bg-primary text-primary-foreground px-4 py-2 rounded">
  Click Me
</button>

// Light mode: Blue background (#2563eb) + White text
// Dark mode:  Lighter blue (#3b82f6) + White text

Adding Custom CSS Classes

Want to add your own classes that respect light/dark mode? Easy!

Method 1: Use CSS Variables in Your CSS

/* styles/custom.css */

.my-custom-button {
  /* Uses theme colors automatically! */
  background-color: var(--primary);
  color: var(--primary-foreground);
  border: 1px solid var(--border);
}

.my-custom-button:hover {
  background-color: var(--accent);
  color: var(--accent-foreground);
}

.my-custom-card {
  background-color: var(--card);
  color: var(--card-foreground);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

Method 2: Tailwind with Theme Variables

// If using Tailwind, these work automatically:
<div className="bg-[var(--primary)] text-[var(--primary-foreground)]">
  Custom styled div
</div>

All Available CSS Variables

/* These are injected into :root by ThemeProvider */
:root {
  --background: ...;
  --foreground: ...;
  --card: ...;
  --card-foreground: ...;
  --popover: ...;
  --popover-foreground: ...;
  --primary: ...;
  --primary-foreground: ...;
  --secondary: ...;
  --secondary-foreground: ...;
  --muted: ...;
  --muted-foreground: ...;
  --accent: ...;
  --accent-foreground: ...;
  --destructive: ...;
  --destructive-foreground: ...;
  --border: ...;
  --input: ...;
  --ring: ...;
  --radius: ...;
}

How It Works

┌─────────────────────────────────────────────────────────────┐
│                      Your React App                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌───────────────────────────────────────────────────────┐  │
│  │              <ThemeProvider>                          │  │
│  │                                                       │  │
│  │   theme={presets.blue}  ──► Blue Theme               │  │
│  │         │                    ├── light mode colors    │  │
│  │         │                    └── dark mode colors     │  │
│  │         │                                             │  │
│  │   defaultMode="system" ──► Auto detect               │  │
│  │         │                    ├── 🌞 Light            │  │
│  │         │                    └── 🌙 Dark             │  │
│  │         ▼                                             │  │
│  │   ┌─────────────────────────────────────────────────┐ │  │
│  │   │  CSS Variables Injected to :root                │ │  │
│  │   │  --background, --primary, --foreground, etc.    │ │  │
│  │   └─────────────────────────────────────────────────┘ │  │
│  │                                                       │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Installation

npm install shadcn-theme-kit

Quick Start (3 Steps)

Step 1: Wrap Your App

// app/layout.tsx (Next.js) or App.tsx (Vite/CRA)
import { ThemeProvider, presets } from "shadcn-theme-kit";

export default function App() {
  return (
    <ThemeProvider theme={presets.blue} defaultMode="system">
      <YourApp />
    </ThemeProvider>
  );
}

Step 2: Add Theme Toggle

import { useTheme } from "shadcn-theme-kit";

function ThemeToggle() {
  const { mode, toggleMode } = useTheme();

  return (
    <button onClick={toggleMode}>
      {mode === "dark" ? "☀️ Light" : "🌙 Dark"}
    </button>
  );
}

Step 3: Use CSS Classes (Works Automatically!)

// These shadcn classes work automatically!
<div className="bg-background text-foreground">
  <button className="bg-primary text-primary-foreground">Click me</button>
</div>

Available Preset Themes

Each preset has BOTH light mode AND dark mode colors built-in!

| Preset | Primary Color | Light Mode | Dark Mode | | ----------------- | ------------- | ---------- | --------- | | presets.default | Neutral gray | ✅ | ✅ | | presets.blue | 💙 Blue | ✅ | ✅ | | presets.rose | 💗 Pink/Rose | ✅ | ✅ | | presets.emerald | 💚 Green | ✅ | ✅ | | presets.orange | 🧡 Orange | ✅ | ✅ | | presets.violet | 💜 Purple | ✅ | ✅ | | presets.slate | 🩶 Slate gray | ✅ | ✅ |

Example: Blue Theme

import { ThemeProvider, presets } from "shadcn-theme-kit";

<ThemeProvider theme={presets.blue}>
  <App />
</ThemeProvider>;

// When user is in LIGHT mode: #2563eb (bright blue)
// When user is in DARK mode:  #3b82f6 (lighter blue)

Multiple Theme Switcher (Blue/Pink/Green)

Let users switch between different color themes!

┌────────────────────────────────────────────────────────────┐
│  User Interface                                            │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  Theme: [Blue ▼]    Mode: [🌙 Dark]                  │  │
│  │         │                 │                          │  │
│  │         ▼                 ▼                          │  │
│  │    ┌─────────┐      toggleMode()                     │  │
│  │    │ Blue    │                                       │  │
│  │    │ Pink    │  ──► setTheme("rose")                 │  │
│  │    │ Green   │                                       │  │
│  │    └─────────┘                                       │  │
│  └──────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────┘

Code Example

import { ThemeProvider, presets, useTheme } from "shadcn-theme-kit";

function App() {
  return (
    <ThemeProvider
      themes={[presets.blue, presets.rose, presets.emerald]}
      defaultTheme="blue"
    >
      <Header />
      <YourApp />
    </ThemeProvider>
  );
}

function Header() {
  const { theme, setTheme, mode, toggleMode } = useTheme();

  return (
    <div>
      {/* Theme Color Switcher */}
      <select value={theme.name} onChange={(e) => setTheme(e.target.value)}>
        <option value="blue">💙 Blue</option>
        <option value="rose">💗 Pink</option>
        <option value="emerald">💚 Green</option>
      </select>

      {/* Light/Dark Mode Toggle */}
      <button onClick={toggleMode}>{mode === "dark" ? "☀️" : "🌙"}</button>
    </div>
  );
}

Custom Theme

Create your own brand colors!

File Structure

your-project/
├── lib/
│   └── theme.ts        ◄── Create this file
├── app/
│   └── layout.tsx      ◄── Import theme here
└── components/
    └── theme-toggle.tsx

theme.ts

import { createTheme } from "shadcn-theme-kit";

export const myBrandTheme = createTheme({
  name: "my-brand", // Used for localStorage key

  // 🌞 LIGHT MODE COLORS
  light: {
    background: "#ffffff",
    foreground: "#0a0a0a",
    primary: "#0066cc", // Your brand color
    primaryForeground: "#ffffff",
    secondary: "#f5f5f5",
    secondaryForeground: "#171717",
    muted: "#f5f5f5",
    mutedForeground: "#737373",
    accent: "#f5f5f5",
    accentForeground: "#171717",
    destructive: "#ef4444",
    destructiveForeground: "#fafafa",
    card: "#ffffff",
    cardForeground: "#0a0a0a",
    popover: "#ffffff",
    popoverForeground: "#0a0a0a",
    border: "#e5e5e5",
    input: "#e5e5e5",
    ring: "#0066cc",
  },

  // 🌙 DARK MODE COLORS
  dark: {
    background: "#0a0a0a",
    foreground: "#fafafa",
    primary: "#3399ff", // Lighter for dark mode
    primaryForeground: "#0a0a0a",
    secondary: "#262626",
    secondaryForeground: "#fafafa",
    muted: "#262626",
    mutedForeground: "#a3a3a3",
    accent: "#262626",
    accentForeground: "#fafafa",
    destructive: "#dc2626",
    destructiveForeground: "#fafafa",
    card: "#0a0a0a",
    cardForeground: "#fafafa",
    popover: "#0a0a0a",
    popoverForeground: "#fafafa",
    border: "#262626",
    input: "#262626",
    ring: "#3399ff",
  },
});

layout.tsx

import { ThemeProvider } from "shadcn-theme-kit";
import { myBrandTheme } from "@/lib/theme";

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <ThemeProvider theme={myBrandTheme}>{children}</ThemeProvider>
      </body>
    </html>
  );
}

API Reference

<ThemeProvider>

| Prop | Type | Default | Description | | -------------- | ------------------------------- | ----------- | ----------------------------- | | theme | ThemeConfig | - | Single theme | | themes | ThemeConfig[] | - | Multiple themes for switching | | defaultTheme | string | First theme | Default active theme name | | defaultMode | 'light' \| 'dark' \| 'system' | 'system' | Default color mode | | storageKey | string | Theme name | localStorage key prefix |

useTheme()

const {
  mode, // 'light' | 'dark' | 'system' - Current setting
  resolvedMode, // 'light' | 'dark' - Actual applied mode
  setMode, // (mode) => void - Set mode
  toggleMode, // () => void - Toggle light/dark
  theme, // ThemeConfig - Current theme
  themes, // ThemeConfig[] - All available themes
  setTheme, // (name) => void - Switch theme by name
} = useTheme();

Other Hooks

| Hook | Returns | Description | | ---------------------- | ------------------- | -------------------- | | useThemeMode() | ThemeMode | Current mode setting | | useResolvedMode() | 'light' \| 'dark' | Actual applied mode | | useIsDarkMode() | boolean | Is dark mode active | | useCurrentTheme() | ThemeConfig | Current theme config | | useAvailableThemes() | ThemeConfig[] | All themes array |


Supported Color Formats

All these formats work:

createTheme({
  light: {
    primary: "#2563eb", // HEX
    secondary: "rgb(100, 116, 139)", // RGB
    accent: "rgba(245, 158, 11, 1)", // RGBA
    background: "hsl(0, 0%, 100%)", // HSL
    foreground: "black", // Color name
  },
});

Next.js App Router Setup

// app/layout.tsx
import { ThemeProvider, presets } from "shadcn-theme-kit";

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <ThemeProvider theme={presets.blue} defaultMode="system">
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}

License

MIT © Sohel Rahaman