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

@saidabedi/design-system

v0.10.1

Published

Platform-agnostic design tokens and theme adapters for React web and React Native

Readme

@saidabedi/design-system

Platform-agnostic design tokens and theme adapters for React web and React Native applications.

Features

  • Single Package: One npm package with subpath exports for tokens, web, and native
  • Platform-Agnostic Tokens: Semantic tokens that work across platforms
  • Type-Safe: Full TypeScript support with exported types
  • Tree-Shakeable: Import only what you need
  • ESM + CJS: Dual module format support

Installation

npm install @saidabedi/design-system
# or
yarn add @saidabedi/design-system
# or
pnpm add @saidabedi/design-system

Package Structure

@saidabedi/design-system
├── /tokens  → Platform-agnostic design tokens
├── /web     → Web theme adapter (rem units, CSS variables)
└── /native  → React Native theme adapter (numeric values)

Quick Start

React Web App

import { createWebTheme, generateCSSVariablesString } from '@saidabedi/design-system/web';

// Create theme
const theme = createWebTheme({ mode: 'light' });

// Use with styled-components
import styled from 'styled-components';

const Button = styled.button`
  background: ${theme.colors.brand.primary};
  color: ${theme.colors.text.inverse};
  padding: ${theme.spacing.sm} ${theme.spacing.lg};
  border-radius: ${theme.radii.md};
  font-size: ${theme.typography.sizes.md};
  font-weight: ${theme.typography.weights.medium};
  border: none;
  cursor: pointer;

  &:hover {
    background: ${theme.colors.brand.primaryHover};
  }
`;

// Or use CSS custom properties
const cssVariables = generateCSSVariablesString(theme);
// Inject into your global styles

React Native App

import { createNativeTheme } from '@saidabedi/design-system/native';
import { Platform, StyleSheet, View, Text } from 'react-native';

// Create theme with platform detection
const theme = createNativeTheme({
  mode: 'light',
  platform: Platform.OS as 'ios' | 'android',
});

const styles = StyleSheet.create({
  container: {
    backgroundColor: theme.colors.background.primary,
    padding: theme.spacing.lg,
    borderRadius: theme.radii.lg,
  },
  title: {
    ...theme.typography.textStyles.heading.h1,
    color: theme.colors.text.primary,
  },
  body: {
    ...theme.typography.textStyles.body.medium,
    color: theme.colors.text.secondary,
  },
});

function Card() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Hello</Text>
      <Text style={styles.body}>Welcome to the app</Text>
    </View>
  );
}

Using Raw Tokens

For shared logic or custom adapters, import tokens directly:

import { colors, spacing, textStyles } from '@saidabedi/design-system/tokens';

// Access semantic values
console.log(colors.brand.primary);  // '#2563eb'
console.log(spacing.lg);            // 16
console.log(textStyles.body.medium.fontSize); // 16

API Reference

Subpath Exports

| Import Path | Description | |-------------|-------------| | @saidabedi/design-system | Root export (tokens only, safe for any environment) | | @saidabedi/design-system/tokens | Platform-agnostic design tokens | | @saidabedi/design-system/web | Web theme adapter | | @saidabedi/design-system/native | React Native theme adapter |

Tokens

Colors

Semantic color tokens organized by purpose:

colors.brand.primary      // Primary brand color
colors.background.primary // Main background
colors.text.primary       // Primary text color
colors.border.primary     // Default border color
colors.feedback.success   // Success state color
colors.interactive.primary // Interactive element color

Spacing

Consistent spacing scale (base unit: 4px):

spacing.none   // 0
spacing.xs     // 4
spacing.sm     // 8
spacing.md     // 12
spacing.lg     // 16
spacing.xl     // 20
spacing['2xl'] // 24
// ... up to 9xl (128)

Typography

Font families, weights, sizes, and pre-composed text styles:

textStyles.heading.h1  // { fontSize, fontWeight, lineHeight, letterSpacing, fontFamily }
textStyles.body.medium
textStyles.label.small
textStyles.code.inline

Radii

Border radius scale:

radii.none  // 0
radii.sm    // 4
radii.md    // 6
radii.lg    // 8
radii.xl    // 12
radii.full  // 9999 (pill shape)

Web Theme

import { createWebTheme, generateCSSVariables } from '@saidabedi/design-system/web';

// Create theme
const theme = createWebTheme({ mode: 'light' }); // or 'dark'

// Theme provides rem-converted values
theme.spacing.lg        // '1rem' (16px / 16)
theme.typography.sizes.lg // '1rem'
theme.radii.md          // '0.375rem'

// Generate CSS custom properties
const vars = generateCSSVariables(theme);
// { '--color-brand-primary': '#2563eb', ... }

const cssString = generateCSSVariablesString(theme, ':root');
// :root { --color-brand-primary: #2563eb; ... }

Native Theme

import { createNativeTheme, shadows } from '@saidabedi/design-system/native';

// Create theme
const theme = createNativeTheme({
  mode: 'light',
  platform: 'ios', // or 'android'
});

// Theme provides numeric values (density-independent pixels)
theme.spacing.lg        // 16
theme.typography.sizes.lg // 16
theme.radii.md          // 6

// Text styles include calculated lineHeight
theme.typography.textStyles.body.medium
// { fontSize: 16, fontWeight: '400', lineHeight: 24, letterSpacing: 0, fontFamily: 'System' }

// Pre-defined shadows
shadows.md // { shadowColor, shadowOffset, shadowOpacity, shadowRadius, elevation }

Theming with Context (React)

Web (React Context + styled-components)

// theme-context.tsx
import { createContext, useContext, ReactNode, useState } from 'react';
import { createWebTheme, WebTheme } from '@saidabedi/design-system/web';
import { ThemeProvider as SCThemeProvider } from 'styled-components';

type ThemeMode = 'light' | 'dark';

const ThemeContext = createContext<{
  mode: ThemeMode;
  toggleMode: () => void;
} | null>(null);

export function ThemeProvider({ children }: { children: ReactNode }) {
  const [mode, setMode] = useState<ThemeMode>('light');
  const theme = createWebTheme({ mode });

  const toggleMode = () => setMode(m => m === 'light' ? 'dark' : 'light');

  return (
    <ThemeContext.Provider value={{ mode, toggleMode }}>
      <SCThemeProvider theme={theme}>
        {children}
      </SCThemeProvider>
    </ThemeContext.Provider>
  );
}

export const useThemeMode = () => {
  const context = useContext(ThemeContext);
  if (!context) throw new Error('useThemeMode must be used within ThemeProvider');
  return context;
};

React Native (Context)

// theme-context.tsx
import { createContext, useContext, ReactNode, useState } from 'react';
import { Platform, useColorScheme } from 'react-native';
import { createNativeTheme, NativeTheme } from '@saidabedi/design-system/native';

const ThemeContext = createContext<NativeTheme | null>(null);

export function ThemeProvider({ children }: { children: ReactNode }) {
  const colorScheme = useColorScheme();
  const theme = createNativeTheme({
    mode: colorScheme ?? 'light',
    platform: Platform.OS as 'ios' | 'android',
  });

  return (
    <ThemeContext.Provider value={theme}>
      {children}
    </ThemeContext.Provider>
  );
}

export const useTheme = () => {
  const theme = useContext(ThemeContext);
  if (!theme) throw new Error('useTheme must be used within ThemeProvider');
  return theme;
};

Building

# Install dependencies
npm install

# Build the package
npm run build

# Type check
npm run typecheck

# Watch mode (development)
npm run build:watch

Output Structure

After building, the dist/ folder contains:

dist/
├── index.js          # ESM root
├── index.cjs         # CJS root
├── index.d.ts        # Types root
├── tokens/
│   ├── index.js
│   ├── index.cjs
│   └── index.d.ts
├── web/
│   ├── index.js
│   ├── index.cjs
│   └── index.d.ts
└── native/
    ├── index.js
    ├── index.cjs
    └── index.d.ts

Publishing

# Ensure you're logged into your private registry
npm login --registry=https://your-registry.com

# Publish
npm publish

Design Principles

  1. Semantic over Primitive: Never use raw values like blue500 in app code. Always use semantic tokens like colors.brand.primary.

  2. Platform Adapters: Tokens are platform-agnostic. Use web/native adapters to get platform-appropriate values.

  3. Single Source of Truth: All design decisions live in the tokens. Adapters only transform, never define.

  4. Type Safety: Full TypeScript coverage prevents typos and enables autocomplete.

  5. Tree Shaking: Import from subpaths to include only what you need.