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

sx-chain

v0.1.0

Published

Chainable styled elements for React - write styles and DOM in one expression

Readme

sx-chain

CI npm version License: MIT

Chainable styled elements for React - write styles and DOM in one expression.

Features

  • 🔗 Chainable API - Write styles, variants, and DOM elements in a single chain
  • 🎯 Type-safe - Full TypeScript support with autocomplete
  • Zero runtime overhead - Uses native className strings
  • 🎨 Framework agnostic - Works with Tailwind, vanilla CSS, CSS Modules (limited)
  • 📦 Tiny bundle - ~2KB minified + gzipped
  • 🚀 React 19+ - Built for React 19+ applications with full type safety

Requirements

  • React 19.0.0 or higher - This library requires React 19+ for proper TypeScript type safety with custom components
  • TypeScript 5.0+ (recommended for full autocomplete support)

Installation

npm install sx-chain
# or
yarn add sx-chain
# or
pnpm add sx-chain

Quick Start

import sx from 'sx-chain';

// Define your styles (Tailwind classes or plain strings)
const styles = {
  container: 'max-w-7xl mx-auto px-4',
  title: 'text-2xl font-bold text-gray-900',
  btn: {
    base: 'px-4 py-2 rounded transition-colors',
    primary: 'bg-blue-500 text-white hover:bg-blue-600',
    secondary: 'bg-gray-500 text-white hover:bg-gray-600',
  }
};

const s = sx(styles);

// Use it in your components
function App() {
  return (
    <s.container.div>
      <s.title.h1>Hello World</s.title.h1>
      <s.btn.primary.button>Click me</s.btn.primary.button>
    </s.container.div>
  );
}

With Tailwind Autocomplete

For Tailwind class autocomplete in your IDE, use a template literal helper:

import sx from 'sx-chain';

// Helper function for Tailwind IntelliSense
const tw = (strings: TemplateStringsArray, ...values: any[]) => {
  return String.raw(strings, ...values);
};

const styles = {
  // Now you get full Tailwind autocomplete!
  container: tw`max-w-7xl mx-auto px-4`,
  title: tw`text-2xl font-bold text-gray-900`,
  btn: {
    base: tw`
      px-4 py-2 rounded
      transition-colors font-medium
    `,
    primary: tw`bg-blue-500 text-white hover:bg-blue-600`,
    secondary: tw`bg-gray-500 text-white hover:bg-gray-600`,
  }
};

const s = sx(styles);

IDE Setup for Tailwind IntelliSense

VS Code:

  1. Install Tailwind CSS IntelliSense extension
  2. Add to your VS Code settings (.vscode/settings.json):
{
  "tailwindCSS.experimental.classRegex": [
    ["tw`([^`]*)`", "([^`]*)"]
  ]
}

WebStorm / IntelliJ:

  1. Install the Tailwind CSS plugin
  2. The plugin should automatically detect tw template literals
  3. If needed, configure in Settings → Languages & Frameworks → Style Sheets → Tailwind CSS
    • Add to Class Detection: "classRegex": ["tw([^]*)"]`

API

Basic Usage

const s = sx(styles);

// Any style can be applied to any HTML element
<s.container.div />      // <div className="max-w-7xl mx-auto px-4" />
<s.container.section />  // <section className="max-w-7xl mx-auto px-4" />
<s.title.h1 />          // <h1 className="text-2xl font-bold" />
<s.title.span />        // <span className="text-2xl font-bold" />

Variants

Define variants using nested objects (works with tw helper too):

const tw = (strings: TemplateStringsArray, ...values: any[]) =>
  String.raw(strings, ...values);

const styles = {
  btn: {
    base: tw`px-4 py-2 rounded`,
    primary: tw`bg-blue-500 text-white`,
    secondary: tw`bg-gray-500 text-white`,
    danger: tw`bg-red-500 text-white`,
  }
};

const s = sx(styles);

// Use variants
<s.btn.button>Base button</s.btn.button>                    // base styles only
<s.btn.primary.button>Primary</s.btn.primary.button>        // base + primary
<s.btn.secondary.button>Secondary</s.btn.secondary.button>  // base + secondary
<s.btn.danger.button>Danger</s.btn.danger.button>          // base + danger

With CSS Modules (Limited Support)

CSS Modules work at runtime but without TypeScript autocomplete:

import styles from './styles.module.css';
import sx from 'sx-chain';

const s = sx(styles);

// ⚠️ Works, but no autocomplete or type checking
<s.container.div>
  <s.heading.h1>CSS Modules</s.heading.h1>
</s.container.div>

Note: For full type safety and autocomplete, use inline style objects:

// ✅ Full autocomplete and type safety
const styles = {
  container: 'max-w-7xl mx-auto px-4',
  heading: 'text-2xl font-bold'
};

const s = sx(styles);

With Custom Components

import sx from 'sx-chain';

const styles = {
  card: 'bg-white rounded-lg shadow p-4',
};

// Register custom components
const s = sx(styles, {
  customComponents: {
    Card: MyCardComponent,
    Icon: MyIconComponent,
  }
});

// Use custom components
<s.card.Card>Custom card</s.card.Card>
<s.card.Icon />

Next.js Integration

import Image from 'next/image';
import Link from 'next/link';
import sx from 'sx-chain';
import { createNextComponents } from 'sx-chain/next';

const s = sx(styles, {
  customComponents: createNextComponents({ Image, Link })
});

// Now you can use Next.js components
<s.hero.Image src="/hero.jpg" alt="Hero" />
<s.navLink.Link href="/about">About</s.navLink.Link>

Additional Classes

You can add extra classes using the standard className prop:

<s.btn.primary.button className="ml-2">
  Button with margin
</s.btn.primary.button>

Default Element

If you don't specify an element, it defaults to div:

<s.container>This is a div</s.container>
// Same as: <s.container.div>This is a div</s.container.div>

TypeScript

sx-chain is written in TypeScript and provides full type safety:

import sx, { type StylesConfig } from 'sx-chain';

const styles = {
  container: 'max-w-7xl mx-auto',
  btn: {
    base: 'px-4 py-2',
    primary: 'bg-blue-500',
  }
} as const satisfies StylesConfig;

const s = sx(styles);

// TypeScript will autocomplete available styles and HTML elements
// s.container. -> div, span, section, article, etc.
// s.btn. -> primary, secondary, button, div, etc.

Comparison

vs styled-components / emotion

// styled-components / emotion
const Button = styled.button`
  padding: 8px 16px;
  background: ${props => props.primary ? 'blue' : 'gray'};
`;

<Button primary>Click</Button>

// sx-chain
<s.btn.primary.button>Click</s.btn.primary.button>

vs clsx / classnames

// clsx
<button className={clsx('btn', variant === 'primary' && 'btn-primary')}>
  Click
</button>

// sx-chain
<s.btn.primary.button>Click</s.btn.primary.button>

vs CVA

// CVA
const button = cva('btn', {
  variants: {
    intent: {
      primary: 'btn-primary',
      secondary: 'btn-secondary',
    }
  }
});

<button className={button({ intent: 'primary' })}>Click</button>

// sx-chain
<s.btn.primary.button>Click</s.btn.primary.button>

Performance

sx-chain uses:

  • WeakMap for component caching
  • Proxy for lazy evaluation
  • No runtime style generation
  • Minimal bundle size

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Author

keisuke-na

Links