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

@loom-sdc/design-system

v0.6.3

Published

Token-driven, framework-agnostic Web Components design system. Built with Vanilla Extract, Vite, and TypeScript — zero runtime overhead, full tree-shaking, native Custom Elements.

Readme

@loom-sdc/design-system

Token-driven, framework-agnostic Web Components design system. Built with Vanilla Extract, Vite, and TypeScript — zero runtime overhead, full tree-shaking, native Custom Elements.

npm version TypeScript Vite Web Components Vanilla Extract Storybook


Overview

Loom Design System provides a single, canonical layer of UI primitives as native Custom Elements (loom-* tags). Framework wrappers (React) are thin adapters — all visual logic lives in the Web Component layer.

Key principles:

  • Token-driven — all design decisions (color, spacing, typography) are exposed as CSS custom properties via Vanilla Extract
  • Framework-agnostic — use in any framework, vanilla HTML, or no framework at all
  • Tree-shakeable — import only what you use via per-component subpath exports
  • Zero runtime — styles are compiled at build time with no JavaScript style injection

Installation

npm install @loom-sdc/design-system

React peer dependency (optional):

npm install react react-dom

Quick Start

1. Import global styles (required)

import '@loom-sdc/design-system/style.css'; // design tokens + global styles
import '@loom-sdc/design-system/fonts.css'; // TWK Everett font-face (optional)

2. Register a component

import { LoomButton } from '@loom-sdc/design-system/elements/button';

LoomButton.define(); // registers <loom-button> as a custom element

3. Use in your markup

<loom-button variant="primary" size="md">Get started</loom-button>

Import Strategy

Production — subpath imports (recommended)

Import and register only the components your application needs. This enables real tree-shaking and minimal bundle size.

import { LoomButton } from '@loom-sdc/design-system/elements/button';
import { LoomStack }  from '@loom-sdc/design-system/elements/stack';

LoomButton.define();
LoomStack.define();

Prototyping — barrel import

Registers all components at once. Not recommended for production.

import '@loom-sdc/design-system/custom-elements'; // auto-registers everything

Tokens only

import '@loom-sdc/design-system/core';

Exports Reference

| Subpath | Description | |---|---| | @loom-sdc/design-system | Full barrel (all exports) | | @loom-sdc/design-system/core | Design tokens only | | @loom-sdc/design-system/elements | All components (tree-shakeable) | | @loom-sdc/design-system/custom-elements | Auto-registers all custom elements | | @loom-sdc/design-system/react-jsx | React wrappers | | @loom-sdc/design-system/elements/<Component> | Per-component subpath | | @loom-sdc/design-system/style.css | Global styles + tokens (mandatory) | | @loom-sdc/design-system/fonts.css | Font-face declarations |


Components

| Component | Subpath import | Custom element tag | |---|---|---| | LoomBox | .../elements/box | <loom-box> | | LoomButton | .../elements/button | <loom-button> | | LoomIcon | .../elements/icon | <loom-icon> | | LoomInline | .../elements/inline | <loom-inline> | | LoomStack | .../elements/stack | <loom-stack> |

Additional primitives (Divider, Fab, Link, Progress, Tag) are available in source and will be published in upcoming releases.


Framework Usage

Vanilla HTML / Web Components

<script type="module">
  import '@loom-sdc/design-system/style.css';
  import { LoomButton, LoomStack } from '@loom-sdc/design-system/elements';

  LoomButton.define();
  LoomStack.define();
</script>

<loom-stack gap="md">
  <h1 class="loom-heading-1">Hello, Loom</h1>
  <loom-button variant="primary">Get started</loom-button>
</loom-stack>

React

import '@loom-sdc/design-system/style.css';
import { Button, Stack } from '@loom-sdc/design-system/react-jsx';

export function App() {
  return (
    <Stack gap="md">
      <h1 className="loom-heading-1">Hello, Loom</h1>
      <Button variant="primary" onClick={() => console.log('clicked')}>
        Get started
      </Button>
    </Stack>
  );
}

Angular (Custom Elements)

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideExperimentalZonelessChangeDetection } from '@angular/core';

export const appConfig: ApplicationConfig = {
  providers: [provideExperimentalZonelessChangeDetection()],
};
// app.module.ts
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { LoomButton } from '@loom-sdc/design-system/elements/button';

LoomButton.define();

@NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA] })
export class AppModule {}
<loom-button variant="primary">Submit</loom-button>

Design Tokens

All tokens are exposed as CSS custom properties. Override them in your theme or consume them directly in CSS.

Token groups

| Group | Description | |---|---| | color | Semantic color aliases | | palette | Raw color scale (50–950) | | spacing | 4px base grid (xs → 3xl) | | typography | Font size, weight, line height, letter spacing | | fontFamily | Brand and monospace font stacks | | radius | Border radius scale | | shadow | Elevation shadows | | motion | Duration and easing tokens | | zIndex | Layer stack | | iconSize | Icon size scale |

Example — custom theme override

:root {
  --loom-color-brand-primary: #your-brand-color;
  --loom-spacing-md: 1rem;
}

TypeScript Configuration

Ensure your tsconfig.json uses bundler module resolution to resolve subpath exports correctly:

{
  "compilerOptions": {
    "moduleResolution": "bundler"
  }
}

Development

Prerequisites

  • Node.js ≥ 20
  • npm ≥ 10

Setup

git clone <repo-url>
cd loom-design-system
npm install

Commands

| Command | Description | |---|---| | npm run storybook | Start Storybook dev server on port 6007 | | npm run build:lib | Build the library to dist/ | | npm run build-storybook | Build static Storybook | | npm run test-storybook | Run Vitest browser tests (Playwright) | | npm run lint | Run ESLint | | npx tsc -b --noEmit | Type-check without emitting | | npm run release | Build and publish to npm |

Project structure

src/design-system/
├── package/
│   ├── tokens/           # Vanilla Extract token groups
│   ├── ui/primitives/    # Component implementations
│   ├── elements/         # Per-component subpath re-exports
│   └── styles/           # Global shared CSS
└── apps/storybook/
    ├── foundations/      # Token documentation stories
    └── ui/primitives/    # Component stories + interaction tests

Component anatomy

Every primitive under ui/primitives/<Name>/ follows this structure:

Name.css.ts           # Vanilla Extract styles
Name.types.ts         # TypeScript interfaces
index.ts              # Public re-export
adapters/
  Name.element.ts     # Web Component (canonical)
  Name.react.tsx      # React wrapper — renders <loom-name>, no logic

Contributing

  1. Follow the existing component anatomy strictly.
  2. Run npx tsc -b --noEmit before submitting any change.
  3. Add or update Storybook stories for any new component or token.
  4. Use named exports only — no default exports.
  5. Use type unions or as const objects — no TypeScript enum.
  6. All internal imports must include file extensions (.ts, .tsx, .css.ts).

License

Private — © Kyndryl. All rights reserved.