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

@axair-systems/ui

v0.2.0

Published

Axair Systems design system — tokens and components

Readme

@axair-systems/ui

npm version

Design system for Axair Systems — brand tokens and React components shared across all products (ADR #26).

Published to public npm — install with a plain npm install, no authentication or token required. Component baseline is shadcn/ui (ADR D2); tokens are the single source of truth.


Contents

| File / export | Purpose | |---|---| | tokens.css | :root CSS variables — primitives and semantic tokens. Framework-agnostic. | | theme.css | tokens.css + @theme inline block that wires Tailwind v4 utilities to the tokens. | | tailwind-preset.js | Tailwind v3 preset (legacy; use theme.css for v4). | | Package main (dist/) | React components: Button, Card, Input, Label, Badge. |


Installation

The package lives on the public npm registry. No .npmrc, token, or PAT is needed — install it like any other dependency:

npm install @axair-systems/ui

Peer dependencies

Install these in the consuming app if they aren't already present:

npm install react react-dom        # required
npm install tailwindcss            # required only if you use the components / Tailwind utilities
  • react / react-dom (^18 or ^19) are required by the components.
  • tailwindcss (^3.4 or ^4) is an optional peer — needed to render the components and their utility classes, but not for token-only (tokens.css) consumption. npm won't warn if you omit it.

CI / other repos consuming this package

Because the package is public, no auth step is required. A plain install works in any CI runner:

- uses: actions/setup-node@v4
  with:
    node-version: '20'

- run: npm ci

Usage

Tailwind v4 (Next.js, Vite, etc.)

1 — Import the theme in your global CSS:

/* app/globals.css  (or src/index.css) */
@import "tailwindcss";
@import "@axair-systems/ui/theme.css";

That's the only config step for Tailwind v4. theme.css loads all token variables and wires every Tailwind utility (bg-primary, text-muted-foreground, rounded-lg, …) to them via @theme inline.

2 — Load Montserrat with next/font (Next.js):

// app/layout.tsx
import { Montserrat, IBM_Plex_Mono } from 'next/font/google';

const montserrat = Montserrat({
  subsets: ['latin'],
  variable: '--font-sans',
  display: 'swap',
});

const ibmMono = IBM_Plex_Mono({
  subsets: ['latin'],
  weight: ['400', '500', '600'],
  variable: '--font-mono',
  display: 'swap',
});

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" className={`${montserrat.variable} ${ibmMono.variable}`}>
      <body className="bg-background text-foreground font-sans">{children}</body>
    </html>
  );
}

The variable option injects --font-sans / --font-mono into the HTML element, overriding the Google Fonts fallback already in tokens.css.

3 — Use components:

import { Button, Badge, Card, CardHeader, CardTitle, CardContent, Input, Label } from '@axair-systems/ui';

export default function Page() {
  return (
    <Card>
      <CardHeader>
        <Badge variant="accent">Active</Badge>
        <CardTitle>Mission Status</CardTitle>
      </CardHeader>
      <CardContent className="space-y-3">
        <div className="space-y-1.5">
          <Label htmlFor="callsign">Callsign</Label>
          <Input id="callsign" placeholder="AX-0042" />
        </div>
        <Button>Deploy</Button>
      </CardContent>
    </Card>
  );
}

Tailwind v3 (legacy consumers)

Use the preset instead of theme.css:

// tailwind.config.js
const preset = require('@axair-systems/ui/tailwind-preset');
module.exports = {
  presets: [preset],
  content: ['./src/**/*.{ts,tsx}'],
};

Import only tokens.css in your global CSS (not theme.css):

@import '@axair-systems/ui/tokens.css';
@tailwind base;
@tailwind components;
@tailwind utilities;

Token-only (no Tailwind)

@import '@axair-systems/ui/tokens.css';

All semantic tokens (--primary, --background, etc.) are then available as CSS variables anywhere in your stylesheet.


Components

All components accept a className prop for one-off overrides via Tailwind classes.

Button

import { Button } from '@axair-systems/ui';

<Button>Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="accent">Accent</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="link">Link</Button>

<Button size="sm">Small</Button>
<Button size="lg">Large</Button>
<Button size="icon">…</Button>

<Button asChild><a href="/dashboard">Dashboard</a></Button>

Badge

import { Badge } from '@axair-systems/ui';

<Badge>Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="accent">Accent</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="muted">Muted</Badge>
<Badge variant="destructive">Destructive</Badge>

Card

import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@axair-systems/ui';

<Card>
  <CardHeader>
    <CardTitle>Title</CardTitle>
    <CardDescription>Supporting text</CardDescription>
  </CardHeader>
  <CardContent>…</CardContent>
  <CardFooter>
    <Button size="sm">Action</Button>
  </CardFooter>
</Card>

Input + Label

import { Input, Label } from '@axair-systems/ui';

<div className="space-y-1.5">
  <Label htmlFor="email">Email</Label>
  <Input id="email" type="email" placeholder="[email protected]" />
</div>

Token reference

The rule: no raw hex in components

Components reference semantic tokens only. The two-tier system means changing a primitive updates every component that uses it.

Brand primitives (--ax-*)  →  Semantic tokens (--primary, --background, …)  →  Components

Wrong:

<div className="bg-[#153d5d]" style={{ color: '#fff7ea' }}>

Correct:

<div className="bg-primary text-primary-foreground">

Audit for violations:

grep -rn '#[0-9a-fA-F]\{3,6\}' src app components

Semantic tokens quick reference

| Token | Default value | Tailwind | |---|---|---| | --background | #f3e6cf (sand) | bg-background | | --foreground | #3b3b38 (dark) | text-foreground | | --primary | #153d5d (navy) | bg-primary | | --primary-foreground | #fff7ea (cream) | text-primary-foreground | | --secondary | #c4d4e0 (blue) | bg-secondary | | --muted | #b9a58a (grey) | bg-muted | | --muted-foreground | #878787 | text-muted-foreground | | --accent | #b0812c (gold) | bg-accent | | --destructive | #b3261e | bg-destructive | | --border | #b9a58a | border-border | | --ring | #153d5d | (focus ring) | | --font-sans | "Montserrat", … | font-sans | | --font-mono | "IBM Plex Mono", … | font-mono | | --radius | 0.5rem | rounded-lg / rounded-md / rounded-sm |

Full table and instructions for adding new tokens: see USAGE.md.


Demo site

A local Vite app that shows all tokens, the type scale, every component variant, and a sample Fleet Overview screen.

# From the repo root — builds the package then starts the demo
npm run demo

Opens at http://localhost:5174 (or next available port).

To run the demo independently after an initial npm run demo:

cd demo
npm run dev

Development

# Install dependencies
npm install

# Build the package (outputs to dist/)
npm run build

# Watch mode during development
npm run dev

# Type check without building
npm run typecheck

Publishing

The package is published to the public npm registry automatically when a version tag is pushed.

# 1. Bump the version (updates package.json and creates a git tag)
npm version patch    # 0.1.0 → 0.1.1
npm version minor    # 0.1.0 → 0.2.0
npm version major    # 0.1.0 → 1.0.0

# 2. Push the commit and tag — the GitHub Action does the rest
git push --follow-tags

The publish.yml workflow runs typecheck → build → npm publish using the repository's NPM_TOKEN secret (a publish-only npm automation token). Do not publish manually unless asked.


Repo layout

design-system/
├── src/
│   ├── components/ui/     # Button, Card, Input, Label, Badge
│   ├── lib/utils.ts       # cn() helper (clsx + tailwind-merge)
│   └── index.ts           # public exports
├── demo/                  # Vite + React demo site
│   └── src/App.tsx        # Colors / Typography / Components / Sample Screen
├── tokens.css             # :root brand primitives + semantic tokens
├── theme.css              # tokens.css + @theme inline (Tailwind v4)
├── tailwind-preset.js     # Tailwind v3 preset
├── tsup.config.ts         # Library build config
├── USAGE.md               # Token table, rules, adding tokens
└── .github/workflows/
    └── publish.yml        # public npm publish on v* tag