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

@amberdaugherty/theme

v0.1.3

Published

Reusable theme system: follows system theme, per-tab manual override (new tab resets), Tailwind v4 + shadcn-style tokens.

Readme

@amberdaugherty/theme

可复用的 React 主题系统:跟随系统主题、当前 tab 可手动切换、新开 tab 自动重置回跟随系统。Tailwind v4 + shadcn 风格 token。

两种用法:

  • 完整模式:自带 ThemeToggle 组件 + shadcn 风格 token(配合 Tailwind v4)。
  • Headless 模式:纯逻辑(ThemeProvider + useTheme),UI、样式、定位完全自定义。

特性

  • 🖥️ 跟随系统:默认读 prefers-color-scheme,系统切换时实时跟随
  • 🔄 三态切换:系统 → 浅色 → 深色 循环
  • 🗂️ per-tab 隔离:手动选择存在 sessionStorage,只影响当前 tab;新开 tab 自动重置回跟随系统,同 tab 刷新则保留
  • 🧩 Headless 友好:核心只是切 <html>.dark class + 管记忆,不绑定任何样式方案
  • 🎨 可选 shadcn 风格 token:语义化变量 + Tailwind v4 映射(完整模式才用)
  • 🌫️ 无首屏闪烁:模块加载即应用一次

安装

npm install @amberdaugherty/theme

React ≥ 18。完整模式还需 tailwindcss + @tailwindcss/vite;Headless 模式无任何样式依赖。


用法 A:完整模式(ThemeToggle + token)

自带切换按钮和配色,开箱即用。

1. 主 CSS

/* src/index.css */
@import "tailwindcss";
@import "@amberdaugherty/theme/tokens.css";

/* ⚠ 必需:让 Tailwind 扫到包里 ThemeToggle 的 class(fixed/top-4 等),
   否则这些工具类不会生成,定位/样式会失效。 */
@source "../node_modules/@amberdaugherty/theme";

2. Vite 配置 Tailwind 插件

// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";

export default defineConfig({
  plugins: [react(), tailwindcss()],
});

3. 入口

import { ThemeProvider, ThemeToggle } from "@amberdaugherty/theme";
import "./index.css";

createRoot(document.getElementById("root")!).render(
  <ThemeProvider>
    <ThemeToggle />
    <App />
  </ThemeProvider>,
);

组件里用语义化 Tailwind class,主题自动跟随:

<main className="bg-background text-foreground">
  <p className="text-muted-foreground">跟随主题的文字</p>
</main>

用法 B:Headless 模式(纯逻辑,自定义 UI)

只用 ThemeProvider + useTheme,不引 tokens.css、不用 ThemeToggle、不需要 @source。按钮、配色、定位全部自己写。

// src/main.tsx —— 只包 Provider,不引任何包样式
import { ThemeProvider } from "@amberdaugherty/theme";

createRoot(document.getElementById("root")!).render(
  <ThemeProvider>
    <App />
  </ThemeProvider>,
);
// 自己的切换按钮
import { useTheme } from "@amberdaugherty/theme";

export function MyToggle() {
  const { theme, cycle } = useTheme();
  return (
    <button onClick={cycle}>
      {theme === "dark" ? "🌙" : theme === "light" ? "☀️" : "🖥️"}
    </button>
  );
}
/* 自己配色:包负责切 <html> 上的 .dark class,你用它写样式即可 */
:root { --my-bg: #fff; --my-fg: #111; }
.dark { --my-bg: #111; --my-fg: #fff; }
body { background: var(--my-bg); color: var(--my-fg); }

Headless 模式下,包做三件事:切 .dark class、跟随系统、per-tab 记忆。其余一概由你决定(连 Tailwind 都不需要)。


什么时候需要 tokens.css / @source?

| 你用到的 | tokens.css | @source | | --- | :---: | :---: | | ThemeToggle(包自带的组件) | ✅ 需要 | ✅ 需要 | | 只用 useTheme(Headless) | ❌ 不需要 | ❌ 不需要 |

@source 的作用:让消费方的 Tailwind 扫描包里的 class 字符串。只有用了包里带 Tailwind class 的组件(目前是 ThemeToggle)才需要。纯 hook 不涉及 class,自然不需要。

API

<ThemeProvider>

包裹在应用根部,无需 props。

useTheme()

const { theme, resolved, setTheme, cycle } = useTheme();

| 字段 | 类型 | 说明 | | --- | --- | --- | | theme | "system" \| "light" \| "dark" | 用户选择 | | resolved | "light" \| "dark" | 实际生效值(system 时取系统当前值) | | setTheme(t) | (t: Theme) => void | 显式设置 | | cycle() | () => void | 循环切换:系统 → 浅 → 深 |

<ThemeToggle />(完整模式)

三态切换按钮,默认固定右上角(fixed top-4 right-4)。接受可选 className 追加样式(如 className="left-4 right-auto" 移到左上)。

可用 token(完整模式)

tokens.css 定义并通过 @theme inline 暴露为 Tailwind 颜色:

background · foreground · card / card-foreground · muted / muted-foreground · border · input · primary / primary-foreground · accent / accent-foreground · ring

用法:bg-backgroundtext-muted-foregroundborder-borderbg-primary text-primary-foreground 等。圆角:rounded-lg / rounded-md / rounded-sm。改配色只动 tokens.css:root.dark 两套变量。

行为说明

  • 选择存在 sessionStorage(per-tab),localStorage —— 这是「新开 tab 重置回跟随系统」的关键。
  • 暗色通过给 <html>.dark class 切换。完整模式下配合 Tailwind v4 的 @custom-variant dark,dark: 变体也能用;Headless 模式下你直接用 .dark 选择器写自己的样式。

License

MIT