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

streamertail

v0.4.0

Published

Streamertail — a lightweight, framework-agnostic CSS utility library with theme support

Downloads

162

Readme

Streamertail

Lightweight, framework-agnostic CSS utility library with theme support.

Works everywhere: Angular, React, Vue, Svelte, SPFx, static HTML — any UI framework or none at all.

Key Principles

  • Zero side effects — Importing Streamertail will never break your existing app. All styles are opt-in via CSS classes.
  • Dual-class output — Every class is available both prefixed (.st-btn) and unprefixed (.btn). Use st- for guaranteed Streamertail styles; use unprefixed when you want browser/cascade to decide.
  • No conflicts — The st- prefix (e.g., .st-btn, .st-p-4, .st-flex) safely coexists with Bootstrap, Tailwind, or any other library.
  • No learning curve — Class names are intuitive: .st-text-red, .st-bg-primary, .st-flex, .st-p-4, .st-shadow-lg.
  • Lightweight — Import only what you need, or grab the full bundle.
  • Theme-aware — Light/dark theme out of the box via OS preference, CSS class, or data attribute.
  • All browsers — Uses CSS custom properties with sensible defaults. No JS runtime needed.
  • Overridable — Every design token is a CSS variable you can override.

Install

npm install streamertail

What's Included

| Module | Contents | Import | |--------|----------|--------| | Full bundle | Everything below combined | streamertail | | Core | CSS variables, themes, typography, buttons, forms | streamertail/core | | Layouts | Grid, flexbox, containers, spacing, display utilities | streamertail/layouts | | Colors | Text, background, border colors + shadows | streamertail/colors | | Animations | Transitions & keyframe animations | streamertail/animations | | Tokens | Design tokens as JS/JSON for frameworks | streamertail/tokens |

Quick Start

Static HTML / CDN

<!-- Full bundle (recommended) -->
<link rel="stylesheet" href="https://unpkg.com/streamertail/dist/streamertail.css" />

<!-- Or pick individual modules -->
<link rel="stylesheet" href="https://unpkg.com/streamertail/dist/core.css" />
<link rel="stylesheet" href="https://unpkg.com/streamertail/dist/layouts.css" />
<link rel="stylesheet" href="https://unpkg.com/streamertail/dist/colors.css" />
<link rel="stylesheet" href="https://unpkg.com/streamertail/dist/animations.css" />

npm (any framework)

npm install streamertail
/* Full bundle — everything in one import */
@import 'streamertail';

/* Or pick only what you need */
@import 'streamertail/core';
@import 'streamertail/layouts';
@import 'streamertail/colors';
@import 'streamertail/animations';

Dual-Class System

Every utility class is output in two forms:

<!-- Prefixed: guaranteed Streamertail styles (safe with any other library) -->
<button class="st-btn st-btn-primary st-p-4">Save</button>

<!-- Unprefixed: same styles, but can be overridden by cascade -->
<button class="btn btn-primary p-4">Save</button>

<!-- Mix and match freely -->
<div class="st-flex gap-4 st-items-center">...</div>

Use st- prefixed classes when you want guaranteed isolation. Use unprefixed when you're the only CSS library in the project or want natural class names.

Theme Switching

Streamertail supports three mechanisms (all work simultaneously):

<!-- 1. Automatic: follows OS preference (no code needed) -->

<!-- 2. CSS class on <html> or any ancestor -->
<html class="theme-dark">

<!-- 3. data-theme attribute on any element -->
<div data-theme="dark">
  <!-- dark theme scoped here -->
</div>

Toggle via JS:

document.documentElement.classList.toggle('theme-dark');

Base Styles (Zero-Config Beautification)

Streamertail automatically enhances raw HTML elements — headings, links, code blocks, tables, forms, buttons — using CSS @layer. This means:

  • Your HTML looks good immediately without adding any classes
  • Your existing styles always win@layer ensures non-layered CSS has higher priority
  • No layout changes — margins, padding, display, width are untouched (browser defaults preserved)
  • Only appearance enhanced — fonts, colors, borders, accent-color, subtle interactions
<!-- These look good with zero classes thanks to @layer streamertail.base -->
<h1>Clean heading with proper font</h1>
<a href="#">Themed link with hover effect</a>
<code>Styled code block</code>
<blockquote>Accent-bordered quote</blockquote>
<button>Subtle styled button</button>
<input type="text" placeholder="Themed input with focus ring" />
<details><summary>Expandable</summary>Content here</details>

How @layer works: Styles inside @layer have lower priority than regular CSS. If you write a { color: green; } anywhere in your app, it beats streamertail's a { color: blue; } — no specificity battle, no !important needed.

To override base styles selectively:

/* This automatically wins over @layer streamertail.base */
blockquote { border-left-color: hotpink; }
input:focus { box-shadow: 0 0 0 3px rgba(255, 0, 0, 0.2); }

Semantic Color Aliases

Colors have multiple names for convenience:

| Color | Aliases | |-------|---------| | Red | .st-text-red, .st-text-danger, .st-text-error | | Orange | .st-text-orange, .st-text-warning | | Yellow | .st-text-yellow, .st-text-caution | | Green | .st-text-green, .st-text-success | | Blue | .st-text-blue, .st-text-info | | Teal | .st-text-teal, .st-text-secondary |

Same aliases work for .st-bg-* and .st-border-* classes.

Responsive Breakpoints

| Prefix | Min-width | |--------|-----------| | (none) | 0px (mobile-first default) | | st-sm- | 576px | | st-md- | 768px | | st-lg- | 992px | | st-xl- | 1200px | | st-xxl- | 1400px |

<div class="st-grid st-grid-cols-1 st-sm-grid-cols-2 st-lg-grid-cols-4 st-gap-4">
  <!-- Responsive grid: 1 col mobile, 2 col tablet, 4 col desktop -->
</div>

Installation Guide

Option 1: Full Bundle (Recommended)

npm install streamertail

Then import in your app entry point:

@import 'streamertail';

Option 2: Pick Only What You Need

@import 'streamertail/core';      /* always required — provides CSS variables */
@import 'streamertail/layouts';   /* grid, flexbox, spacing */
@import 'streamertail/colors';    /* color utilities */
@import 'streamertail/animations'; /* transitions & keyframes */

Option 3: CDN (No Build Step)

Add directly to any HTML page. No npm, no bundler:

<!-- Full bundle -->
<link rel="stylesheet" href="https://unpkg.com/streamertail/dist/streamertail.css" />

<!-- Or individual modules -->
<link rel="stylesheet" href="https://unpkg.com/streamertail/dist/core.css" />
<link rel="stylesheet" href="https://unpkg.com/streamertail/dist/layouts.css" />
<link rel="stylesheet" href="https://unpkg.com/streamertail/dist/colors.css" />
<link rel="stylesheet" href="https://unpkg.com/streamertail/dist/animations.css" />

Framework-Specific Setup

React / Next.js

// app/layout.tsx or index.tsx
import 'streamertail';

export default function App() {
  return <button className="st-btn st-btn-primary">Click me</button>;
}

Angular

// angular.json → styles array
{
  "styles": [
    "node_modules/streamertail/dist/streamertail.css"
  ]
}
<!-- Then use in any component template -->
<button class="st-btn st-btn-primary st-btn-lg">Submit</button>

Vue.js

// main.js or main.ts
import 'streamertail';
<!-- In any .vue component -->
<template>
  <div class="st-container st-p-4">
    <h1 class="st-heading-2 st-text-primary">Hello Streamertail</h1>
  </div>
</template>

SPFx (SharePoint Framework)

// In your web part's onInit or top-level require
require('streamertail');

Svelte / SvelteKit

<!-- src/routes/+layout.svelte -->
<script>
  import 'streamertail';
</script>

<slot />

Nuxt 3

// nuxt.config.ts
export default defineNuxtConfig({
  css: ['streamertail'],
});

Astro

---
// src/layouts/Layout.astro
import 'streamertail';
---

<html>
  <body>
    <slot />
  </body>
</html>

Remix

// app/root.tsx
import 'streamertail';

SolidJS / SolidStart

// src/index.tsx or src/root.tsx
import 'streamertail';

Qwik / QwikCity

// src/root.tsx
import 'streamertail';

Lit / Web Components

// Import globally in your app entry point
import 'streamertail';

// Note: For Shadow DOM components, you'll need to adopt the stylesheet:
// const sheet = new CSSStyleSheet();
// sheet.replaceSync(streamertailCSS);
// this.shadowRoot.adoptedStyleSheets = [sheet];

Blazor (Server / WASM)

<!-- wwwroot/index.html or Pages/_Host.cshtml -->
<link rel="stylesheet" href="_content/node_modules/streamertail/dist/streamertail.css" />

Or via CSS import in wwwroot/css/app.css:

@import '../../node_modules/streamertail/dist/streamertail.css';

WordPress / PHP

// functions.php (after npm install in your theme)
function enqueue_streamertail() {
  wp_enqueue_style('streamertail', get_template_directory_uri() . '/node_modules/streamertail/dist/streamertail.css');
}
add_action('wp_enqueue_scripts', 'enqueue_streamertail');

Or copy dist/streamertail.css to your theme's assets/ folder and reference it directly.


Usage Guide

Colors

<!-- Text colors -->
<p class="st-text-primary">Primary brand color</p>
<p class="st-text-danger">Error / danger text (also: .st-text-red, .st-text-error)</p>
<p class="st-text-warning">Warning text (also: .st-text-orange)</p>
<p class="st-text-success">Success text (also: .st-text-green)</p>
<p class="st-text-muted">Muted/secondary text</p>

<!-- Background colors -->
<div class="st-bg-primary st-text-white st-p-4">Primary background</div>
<div class="st-bg-danger-light st-text-danger st-p-4">Light danger alert</div>
<div class="st-bg-surface st-p-4">Surface (auto theme-aware)</div>

<!-- Border colors -->
<div class="st-border-primary" style="border: 1px solid;">Primary border</div>

Typography

<!-- Headings (fluid responsive sizing) -->
<h1 class="st-heading-1">Page Title</h1>
<h2 class="st-heading-3">Section Title</h2>

<!-- Font sizes -->
<p class="st-text-xs">Extra small</p>
<p class="st-text-sm">Small</p>
<p class="st-text-body">Base (default)</p>
<p class="st-text-lg">Large</p>
<p class="st-text-2xl">2X Large</p>

<!-- Font weight -->
<span class="st-font-bold">Bold text</span>
<span class="st-font-light">Light text</span>

<!-- Text utilities -->
<p class="st-text-center st-text-uppercase">Centered uppercase</p>
<p class="st-text-truncate">This very long text will be truncated with ellipsis...</p>

Layouts

<!-- Responsive grid -->
<div class="st-grid st-grid-cols-1 st-sm-grid-cols-2 st-md-grid-cols-3 st-lg-grid-cols-4 st-gap-4">
  <div>Card 1</div>
  <div>Card 2</div>
  <div>Card 3</div>
  <div>Card 4</div>
</div>

<!-- Flexbox row -->
<div class="st-flex st-justify-between st-items-center st-gap-4">
  <div>Left</div>
  <div>Right</div>
</div>

<!-- Centered content -->
<div class="st-flex st-justify-center st-items-center" style="min-height: 200px;">
  <p>I'm centered!</p>
</div>

<!-- Container (responsive max-width) -->
<div class="st-container">
  <!-- Content is centered with max-width per breakpoint -->
</div>

<!-- Column spanning -->
<div class="st-grid st-grid-cols-12 st-gap-4">
  <aside class="st-col-span-3">Sidebar</aside>
  <main class="st-col-span-9">Main content</main>
</div>

Spacing

<!-- Padding -->
<div class="st-p-4">Padding all sides (1rem)</div>
<div class="st-px-6 st-py-2">Horizontal 1.5rem, vertical 0.5rem</div>
<div class="st-pt-8">Top padding only (2rem)</div>

<!-- Margin -->
<div class="st-mb-4">Bottom margin 1rem</div>
<div class="st-mx-auto">Centered horizontally</div>
<div class="st-mt-8 st-mb-4">Top 2rem, bottom 1rem</div>

Buttons

<!-- Solid variants -->
<button class="st-btn st-btn-primary">Save</button>
<button class="st-btn st-btn-danger">Delete</button>
<button class="st-btn st-btn-success">Confirm</button>

<!-- Outline & ghost -->
<button class="st-btn st-btn-outline">Cancel</button>
<button class="st-btn st-btn-outline-primary">Edit</button>
<button class="st-btn st-btn-ghost">More options</button>

<!-- Sizes -->
<button class="st-btn st-btn-primary st-btn-sm">Small</button>
<button class="st-btn st-btn-primary">Default</button>
<button class="st-btn st-btn-primary st-btn-lg">Large</button>

<!-- Shapes -->
<button class="st-btn st-btn-primary st-btn-pill">Rounded Pill</button>
<button class="st-btn st-btn-primary st-btn-full">Full Width</button>

<!-- Disabled -->
<button class="st-btn st-btn-primary" disabled>Can't click me</button>

<!-- Button group -->
<div class="st-btn-group">
  <button class="st-btn st-btn-primary">Left</button>
  <button class="st-btn st-btn-primary">Center</button>
  <button class="st-btn st-btn-primary">Right</button>
</div>

Forms

<!-- Basic input -->
<div class="st-form-group">
  <label class="st-label st-label-required">Email</label>
  <input class="st-input" type="email" placeholder="[email protected]" />
  <span class="st-form-helper">We'll never share your email.</span>
</div>

<!-- Input with error -->
<div class="st-form-group">
  <label class="st-label">Password</label>
  <input class="st-input st-input-error" type="password" />
  <span class="st-form-error">Password must be at least 8 characters.</span>
</div>

<!-- Select -->
<div class="st-form-group">
  <label class="st-label">Country</label>
  <select class="st-input">
    <option>United States</option>
    <option>Canada</option>
    <option>United Kingdom</option>
  </select>
</div>

<!-- Textarea -->
<textarea class="st-input" placeholder="Write your message..."></textarea>

<!-- Sizes -->
<input class="st-input st-input-sm" placeholder="Small input" />
<input class="st-input st-input-lg" placeholder="Large input" />

<!-- Checkbox & Radio -->
<label class="st-checkbox"><input type="checkbox" /> Remember me</label>
<label class="st-radio"><input type="radio" name="plan" /> Free</label>
<label class="st-radio"><input type="radio" name="plan" /> Pro</label>

<!-- Inline form -->
<div class="st-form-inline">
  <input class="st-input" placeholder="Search..." style="width: auto;" />
  <button class="st-btn st-btn-primary">Go</button>
</div>

Semantic Layouts

<!-- Stack: vertical rhythm with consistent spacing -->
<div class="st-stack">
  <h2>Title</h2>
  <p>Paragraph</p>
  <button class="st-btn st-btn-primary">Action</button>
</div>

<!-- Cluster: horizontal wrapping group (tags, pills) -->
<div class="st-cluster">
  <span class="st-badge-primary">Tag 1</span>
  <span class="st-badge-secondary">Tag 2</span>
  <span class="st-badge-success">Tag 3</span>
</div>

<!-- Center: max-width + auto margins (ideal for content) -->
<div class="st-center">
  <p>Centered readable content area (max 65ch)</p>
</div>

<!-- Auto-grid: responsive grid that auto-fills columns -->
<div class="st-auto-grid">
  <div>Card 1</div>
  <div>Card 2</div>
  <div>Card 3</div>
</div>

<!-- Sidebar layout: intrinsic two-panel -->
<div class="st-with-sidebar">
  <aside>Sidebar (fixed width)</aside>
  <main>Main content (fills remaining space)</main>
</div>

<!-- Switcher: row → column when space runs out -->
<div class="st-switcher">
  <div>Panel A</div>
  <div>Panel B</div>
  <div>Panel C</div>
</div>

<!-- Reel: horizontal scrolling strip (carousel) -->
<div class="st-reel">
  <img src="1.jpg" />
  <img src="2.jpg" />
  <img src="3.jpg" />
</div>

<!-- Cover: full-viewport section with centered content -->
<div class="st-cover">
  <header>Top</header>
  <div class="st-cover-center">Centered hero content</div>
  <footer>Bottom</footer>
</div>

<!-- Pancake: header/main/footer app shell -->
<div class="st-pancake">
  <header>Header</header>
  <main>Main (grows to fill)</main>
  <footer>Footer</footer>
</div>

Semantic Colors & States

<!-- Alerts: pre-styled contextual messages -->
<div class="st-alert-success">Operation completed successfully.</div>
<div class="st-alert-danger">Something went wrong!</div>
<div class="st-alert-warning">Please review before continuing.</div>
<div class="st-alert-info">Here's some helpful information.</div>

<!-- Badges: solid -->
<span class="st-badge-primary">New</span>
<span class="st-badge-danger">3</span>
<span class="st-badge-success">Active</span>

<!-- Badges: soft (lighter) -->
<span class="st-badge-soft-primary">Draft</span>
<span class="st-badge-soft-danger">Failed</span>
<span class="st-badge-soft-success">Passed</span>

<!-- Status indicators -->
<span class="st-status-online"></span> Online
<span class="st-status-offline"></span> Offline
<span class="st-status-busy"></span> Busy
<span class="st-status-away"></span> Away

<!-- Highlight: inline text emphasis -->
<p>This is <span class="st-highlight">highlighted</span> text.</p>
<p>This is <span class="st-highlight-success">success highlighted</span>.</p>

<!-- Gradient backgrounds -->
<section class="st-gradient-primary st-p-8">Primary → Secondary</section>
<section class="st-gradient-sunset st-p-8">Orange → Pink → Rose</section>
<section class="st-gradient-ocean st-p-8">Cyan → Blue → Indigo</section>

<!-- Surface variants (for cards) -->
<div class="st-surface-raised st-p-4">Raised card</div>
<div class="st-surface-sunken st-p-4">Sunken/recessed area</div>
<div class="st-surface-interactive st-p-4">Clickable card (hover effect)</div>

<!-- Dividers -->
<hr class="st-divider" />
<hr class="st-divider-strong" />
<hr class="st-divider-dashed" />
<span class="st-divider-vertical"></span> <!-- vertical separator -->

Semantic Typography

<!-- Prose: full typographic formatting for long-form content -->
<article class="st-prose">
  <h2>Article Title</h2>
  <p>Paragraphs, lists, links, code blocks — all beautifully formatted.</p>
</article>
<article class="st-prose-sm">Smaller prose</article>
<article class="st-prose-lg">Larger prose</article>

<!-- Display headings: large hero titles -->
<h1 class="st-display-1">Huge Hero Title</h1>
<h1 class="st-display-2">Large Hero Title</h1>
<h1 class="st-display-3">Medium Hero Title</h1>

<!-- Lead: intro paragraph -->
<p class="st-lead">This article explores the fundamentals of design systems.</p>

<!-- Caption: figure/table descriptions -->
<figcaption class="st-caption">Photo by John Doe, 2024</figcaption>

<!-- Overline: small label above headings -->
<span class="st-overline">Featured Article</span>
<h2 class="st-heading-2">The Main Title</h2>
<p class="st-subtitle">A supporting subtitle goes here</p>

<!-- Keyboard keys -->
<p>Press <kbd class="st-kbd">Ctrl</kbd> + <kbd class="st-kbd">C</kbd> to copy.</p>

<!-- Inline code -->
<p>Use the <code class="st-code">useState</code> hook.</p>

<!-- Blockquote -->
<blockquote class="st-blockquote">Design is not just what it looks like.</blockquote>

<!-- List styles -->
<ul class="st-list-check">
  <li>Feature one</li>
  <li>Feature two</li>
  <li>Feature three</li>
</ul>

<!-- Number formatting -->
<span class="st-tabular-nums">1,234,567.89</span>

<!-- Modern text wrapping -->
<h2 class="st-text-balance">A Heading That Wraps Evenly Across Lines</h2>
<p class="st-text-pretty">Paragraph with better line-break decisions.</p>

Shadows

<!-- Elevation levels -->
<div class="st-p-4 st-bg-elevated st-shadow-sm">Subtle shadow</div>
<div class="st-p-4 st-bg-elevated st-shadow">Default shadow</div>
<div class="st-p-4 st-bg-elevated st-shadow-md">Medium shadow</div>
<div class="st-p-4 st-bg-elevated st-shadow-lg">Large shadow</div>
<div class="st-p-4 st-bg-elevated st-shadow-xl">Extra-large shadow</div>

<!-- Colored shadows (glow effect) -->
<button class="st-btn st-btn-primary st-shadow-primary">Glowing button</button>

<!-- Inner shadow -->
<div class="st-p-4 st-shadow-inner">Inset shadow</div>

Animations

<!-- Enter animations -->
<div class="st-animate-fade-in">Fades in on load</div>
<div class="st-animate-slide-up">Slides up on load</div>
<div class="st-animate-scale-in">Scales in on load</div>

<!-- Continuous animations -->
<span class="st-animate-spin">⟳</span>     <!-- Loading spinner -->
<div class="st-animate-pulse">Loading...</div>  <!-- Skeleton loader -->
<span class="st-animate-bounce">↓</span>   <!-- Scroll indicator -->

<!-- Hover effects (pair with transition class) -->
<div class="st-p-4 st-bg-elevated st-shadow st-transition-transform st-hover-lift">
  Lifts on hover
</div>
<button class="st-btn st-btn-primary st-transition-transform st-hover-grow">
  Grows on hover
</button>

<!-- Transition utilities -->
<button class="st-btn st-btn-outline st-transition-colors">Smooth color change</button>
<div class="st-shadow-sm st-transition-shadow">Shadow transition on interaction</div>

Accessibility: All animations automatically disable when the user has prefers-reduced-motion: reduce enabled in their OS.

Design Tokens (JS)

For programmatic access in React, Vue, Angular, or any JS code:

// ESM import (recommended)
import { colors, spacing, typography, breakpoints } from 'streamertail/tokens';

console.log(colors.primary);      // '#2563eb'
console.log(colors.danger);       // '#dc2626'
console.log(spacing[4]);          // '1rem'
console.log(breakpoints.md);      // '768px'
console.log(typography.fontWeight.bold); // 700
// CommonJS
const { colors, spacing } = require('streamertail/dist/tokens/index.js');
// JSON import
import tokens from 'streamertail/tokens/json';

Customization

Override any CSS variable to match your brand:

:root {
  --st-color-primary: #your-brand-color;
  --st-color-secondary: #your-secondary;
  --st-color-accent: #your-accent;
  --st-font-family: 'Your Font', sans-serif;
  --st-border-radius: 0.5rem;
}

Scoped Overrides

You can scope variable overrides to specific sections:

.admin-panel {
  --st-color-primary: #9333ea;
  --st-bg-surface: #faf5ff;
}

Dark Theme Customization

.theme-dark {
  --st-color-primary: #60a5fa; /* lighter blue for dark backgrounds */
  --st-bg: #0a0a0a;
}

Will Streamertail Break My Existing App?

No. Streamertail is designed to be 100% safe to add to any existing project:

  • Dual-class system — use st- prefixed classes for guaranteed isolation, or unprefixed for natural names
  • Base styles use @layer — element-level styles (headings, links, inputs, etc.) are wrapped in @layer streamertail.base, meaning any existing CSS in your project automatically takes priority
  • No layout changes — no box-sizing reset, no margin: 0 on body, no display: block on images, no width: 100% on tables
  • Appearance only — base styles only enhance fonts, colors, borders, and interactions
  • Utility classes require explicit class names to activate
  • No !important used anywhere
  • Low specificity — easy to override with your existing styles
  • No JavaScript runtime — pure CSS, zero side effects

How @layer Ensures Safety

/* streamertail ships this (inside @layer — lowest priority): */
@layer streamertail.base {
  a { color: var(--st-text-link); }
}

/* Your app writes this (no @layer — higher priority automatically): */
a { color: green; }
/* ✅ Your green wins. No specificity fight. */

Development

# Install dependencies
npm install

# Build everything (CSS + tokens)
npm run build

# Build CSS only
npm run build:css

# Build tokens only
npm run build:tokens

# Watch mode (auto-rebuild on changes)
npm run dev

# Run demo locally
cd demo && npx vite

Project Structure

streamertail/
├── src/
│   ├── index.scss        # Full bundle entry point
│   ├── _mixins.scss      # Shared SCSS mixins (dual-class system)
│   ├── core/             # Variables, themes, base, typography, buttons, forms
│   ├── colors/           # Text, background, border colors, shadows, hover states
│   ├── layouts/          # Grid, flexbox, containers, spacing, borders, sizing
│   ├── animations/       # Transitions, keyframe animations, easter eggs
│   └── tokens/           # Design tokens as JS (source)
├── dist/
│   ├── streamertail.css        # Full bundle
│   ├── core.css          # Core only
│   ├── colors.css        # Colors only
│   ├── layouts.css       # Layouts only
│   ├── animations.css    # Animations only
│   └── tokens/           # JS/ESM/JSON/d.ts
├── scripts/              # Build scripts
├── demo/                 # Demo page
└── docs/                 # Usage guide

Requirements

  • Node.js >= 18

License

MIT