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

@schemavaults/theme

v0.30.0

Published

TailwindCSS theme shared by different SchemaVaults applications

Readme

🎨 @schemavaults/theme

About 🎨

Package containing code for building opionated TailwindCSS themes/configurations that contain SchemaVaults branding colors and shared styles.

To see the theme in action you can check out the @schemavaults/ui preview site showcasing some styled React.js components and the features available in this theme.

Usage

Ensure that globals.css is imported

The generated TailwindCSS config sets colors based on CSS variables. It's important that globals.css is imported, so that these colors can be resolved. E.g. var(--foreground) and var(--card) become functional after this CSS import.

// within App.jsx / layout.jsx
import "@schemavaults/theme/globals.css"

Import and run the TailwindCSS Config Factory from your tailwind.config.mjs or tailwind.config.ts

Simple example using withSchemaVaultsTailwindTheme

import { withSchemaVaultsTailwindTheme } from "@schemavaults/theme";
const config = withSchemaVaultsTailwindTheme({
  "./src/**/*.tsx|jsx|js|ts",
  "@schemavaults/ui", // resolved and converted to an absolute path to the schemavaults package in the node_modules folder
});
export default config;

Simple example using SchemaVaultsTailwindConfigFactory

// tailwind.config.ts
import { SchemaVaultsTailwindConfigFactory } from "@schemavaults/theme";
const config = new SchemaVaultsTailwindConfigFactory().createConfig({
  content: [
    "./src/**/*.tsx|jsx|js|ts",
    "@schemavaults/ui", // resolved and converted to an absolute path to the schemavaults package in the node_modules folder
  ],
});
export default config;

More complex example using SchemaVaultsTailwindConfigFactory

// tailwind.config.ts

// Import the config factory
import { SchemaVaultsTailwindConfigFactory } from "@schemavaults/theme";


// Initialize the config factory
const configFactory = new SchemaVaultsTailwindConfigFactory({
  scope: 'schemavaults'
});

// Generate and export the config
const config = configFactory.createConfig({
  content: [
    "./src/**/*.tsx|jsx|js|ts",
    "./app/**/*.tsx|jsx|js|ts",
    "@schemavaults/ui", // resolved and converted to an absolute path to the schemavaults package in the node_modules folder. i.e. @schemavaults/ui => .../node_modules/@schemavaults/ui/dist/**/*.tsx|jsx|js|ts
    "@schemavaults/schema-ui",
  ],
});
export default config;

You may wish to also dig deeper on the options passed to the factory / createConfig in order to customize the final Tailwind configuration generated. Notably, the content parameter to createConfig, if the code for styles to be generated from is not found within ./src/**/*.ts|tsx|js|jsx!

// tailwind.config.ts
// ... initialize the factory somewhere

// An example demonstrating customization of where Tailwind searches for classnames
const config = configFactory.createConfig({
  content: ["./src/**/*.ts|tsx|js|jsx", "@schemavaults/ui", "@schemavaults/schema-ui"]
});
export default config;

In the above example, local .js/.ts/.jsx/.tsx paths will be resolved in the app that @schemavaults/theme config factory is running in. Also, @schemavaults/* scoped packages will be resolved from node_modules.

Theming a deployment (overriding the tokens)

globals.css declares every design token through an override variable with the stock value as its fallback:

:root  { --background: var(--sv-theme-light-background, 0 0% 100%); }
.dark  { --background: var(--sv-theme-dark-background, 222.2 84% 4.9%); }
:root  { --radius: var(--sv-theme-radius, 0.5rem); }

So a white-labelled deployment re-themes itself by setting --sv-theme-light-*, --sv-theme-dark-* and (for tokens shared by both modes) --sv-theme-* on the <html> element — no fork of globals.css, and the stylesheet's defaults keep applying to whatever is not set. A light override only affects light mode; the .dark block reads its own variables.

@schemavaults/theme/tokens (safe to import from browser bundles and client components — it has no Node.js dependencies, unlike the config factory at the package root) ships the manifest and the helpers:

import {
  THEME_TOKENS,                    // every token: id, css variable, format, group, label, description, light/dark defaults
  createThemeOverrideStyle,        // ThemeOverrides -> { "--sv-theme-light-background": "210 40% 98%", ... }
  renderThemeOverrideCss,          // ThemeOverrides -> ":root{--sv-theme-light-background:210 40% 98%;}"
  resolveThemeTokens,              // every token with default + override + effective value, for a settings page
  themeOverridesFromEnvironment,   // reads THEME_LIGHT_BACKGROUND, THEME_DARK_BACKGROUND, THEME_RADIUS, ...
} from "@schemavaults/theme/tokens";

// e.g. in a Next.js root layout
const { overrides, problems } = themeOverridesFromEnvironment(process.env, { prefix: "THEME" });
// problems: variables set to a value the token cannot take; they keep the default
const style = createThemeOverrideStyle(overrides);
// <html style={style}> ... </html>

Values are validated and normalised before they are emitted. Tokens whose format is hsl-channels (the shadcn/ui component colours the Tailwind theme wraps in hsl()) accept bare channels (222.2 84% 4.9%), a hex colour, or an opaque rgb()/hsl(), and are stored as channels; css-color tokens (the brand colours, warning and the sidebar) take any CSS colour; radius takes a CSS length. A value that could break the stylesheet or escape an attribute is refused with a reason you can show an administrator.

A token can take its default from another token instead of a literal value (defaultFrom in the manifest): globals.css then falls back to that token's variable, so re-theming it re-colours both. resolveThemeTokens() reports such a token's defaultValue as the resolved value of the token it follows, that token's override included.

Environment variable names follow the token id: <PREFIX>_LIGHT_<TOKEN>, <PREFIX>_DARK_<TOKEN> and <PREFIX>_<TOKEN> for shared tokens, upper-cased with hyphens as underscores (sidebar-primary-foreground → THEME_DARK_SIDEBAR_PRIMARY_FOREGROUND); themeTokenEnvironmentVariable() returns the name for a token and scope.

The generated Tailwind config safelists the dark class so the .dark token block survives Tailwind's purge in applications that only add the class at runtime.

Chart colours

globals.css defines a categorical palette for charts: --chart-1 … --chart-8 for series, in slot order, and --chart-other for the de-emphasis grey (a folded "Other" tail, an overflow bucket, a series past the palette). The Tailwind config exposes them as the chart-1 … chart-8 and chart-other colours (fill-chart-2, stroke-chart-1, bg-chart-other/40).

| Slot | Hue | Light | Dark | | --- | --- | --- | --- | | 1 | Blue | #2a78d6 | #3987e5 | | 2 | Orange | #eb6834 | #d95926 | | 3 | Aqua | #1baf7a | #199e70 | | 4 | Yellow | #eda100 | #c98500 | | 5 | Magenta | #e87ba4 | #d55181 | | 6 | Green | #008300 | #008300 | | 7 | Violet | #4a3aa7 | #9085e9 | | 8 | Red | #e34948 | #e66767 | | Other | Grey | #898781 | #898781 |

The slots come from the data-viz reference palette and are validated in this order against the card surfaces (#ffffff light, #020817 dark) with the data-viz validate_palette.js:

  • Light: every slot inside the lightness band and above the chroma floor; worst neighbouring pair ΔE 9.1 under colour-blindness simulation (target ≥ 8) and ΔE 19.6 for normal vision (floor 15). Aqua (2.82:1), yellow (2.17:1) and magenta (2.69:1) fall under 3:1 contrast on white, so a chart that uses them needs a legend or direct labels plus a table view.
  • Dark: worst neighbouring pair ΔE 8.4 (simulated) and ΔE 19.3 (normal vision); every slot clears 3:1.

Rules for using them:

  • Assign slots in order and never cycle them. A ninth series folds into chart-other (or the chart becomes small multiples).
  • The order is the colour-blindness safety: the checks above hold for neighbouring slots. Charts where every pair can sit side by side (scatter plots, maps) are validated only for the first three slots (worst pair ΔE 9.2 light / 9.4 dark); no ordering of four or more passes, so colour at most three series there.
  • Colour follows the entity, not its position: filtering a series out must not repaint the others.
  • A single-series chart uses slot 1 for every mark.
  • These are identity colours. Status colours (destructive, warning, success) stay reserved for series that mean good or bad, and the brand blue is an explicit choice rather than slot 1 (at #60a5fa it is 2.54:1 on white and too light for dark mode).

Like every other token, the chart colours can be re-themed per deployment (--sv-theme-light-chart-1, THEME_DARK_CHART_OTHER, …); re-run the validator on any replacement palette.

Sidebar active gradient

A two-colour gradient marks the navigation sidebar item for the current page (@schemavaults/ui's DashboardLayout paints a wash across the row, a glowing bar down its left edge and a gradient label with it). Its colours are two tokens:

| Token | Environment variables | Default (light and dark) | | --- | --- | --- | | --sidebar-active-start | THEME_LIGHT_SIDEBAR_ACTIVE_START, THEME_DARK_SIDEBAR_ACTIVE_START | var(--schemavaults-brand-blue) | | --sidebar-active-end | THEME_LIGHT_SIDEBAR_ACTIVE_END, THEME_DARK_SIDEBAR_ACTIVE_END | var(--schemavaults-brand-red) |

:root { --sidebar-active-start: var(--sv-theme-light-sidebar-active-start, var(--schemavaults-brand-blue)); }
.dark { --sidebar-active-start: var(--sv-theme-dark-sidebar-active-start, var(--schemavaults-brand-blue)); }

By default they follow the brand colours, so a deployment that re-themes brand-blue / brand-red gets a matching gradient without setting anything else. Set --sv-theme-light-sidebar-active-start (and friends), or the environment variables above, to give the gradient its own colours; each mode is independent, as for every other token.

The Tailwind config exposes them as the sidebar-active-start and sidebar-active-end colours, so an application can reuse the gradient: bg-gradient-to-r from-sidebar-active-start to-sidebar-active-end, bg-sidebar-active-start/20.

These are accent colours, not text colours. The UI paints the bar and the wash with them directly, and mixes each 60/40 with --foreground for the item's icon and label; with the default pair that mix stays at about 5.6:1 or better against the sidebar background in both modes. The raw colours are not safe for text on their own (the brand blue is 2.4:1 on the light sidebar), so avoid text-sidebar-active-start for body copy. When overriding them, pick saturated, mid-lightness colours: very light or very dark values wash the gradient out against one of the two modes' sidebars and pull the mixed label towards too little contrast.

CommonJS

Note that currently CommonJS is not supported. I believe that I was struggling to get tailwindcss-animate working from CJS, then decided not to support it. Change your tailwind.config.cjs files to tailwind.config.ts or tailwind.config.mjs to use TypeScript or ES modules instead.