npm package: @hydrogen-ui/tokens
Description: Design tokens for Hydrogen UI component library
Latest version: 0.1.0

# @hydrogen-ui/tokens

A comprehensive design token system for Hydrogen UI built with Style Dictionary. Provides consistent design values across colors, typography, spacing, and components with full TypeScript support.

## Installation

```bash
npm install @hydrogen-ui/tokens
# or
yarn add @hydrogen-ui/tokens
# or
pnpm add @hydrogen-ui/tokens
```

## Features

- 🎨 **Comprehensive Token Set** - Colors, typography, spacing, shadows, and more
- 🔧 **Multiple Output Formats** - CSS, JavaScript, TypeScript, and JSON
- 🎯 **Semantic Tokens** - Purpose-driven tokens for consistent usage
- 📦 **Component Tokens** - Pre-configured values for common components
- 🎭 **Theme Support** - Override base tokens for custom themes
- 🔒 **Type Safety** - Full TypeScript definitions
- 🚀 **Zero Runtime** - All tokens are build-time generated
- 📱 **Responsive Ready** - Tokens designed for responsive design
- ♿ **Accessibility** - WCAG compliant color combinations

## Quick Start

### CSS Variables

```css
/* Import CSS variables */
@import '@hydrogen-ui/tokens/dist/css/variables.css';

.my-component {
  color: var(--color-text-primary);
  background-color: var(--color-background-primary);
  padding: var(--spacing-md);
  font-size: var(--font-size-base);
  border-radius: var(--border-radius-md);
}
```

### JavaScript/TypeScript

```tsx
import { tokens } from '@hydrogen-ui/tokens';

const styles = {
  color: tokens.color.text.primary.value,
  backgroundColor: tokens.color.background.primary.value,
  padding: tokens.spacing.md.value,
  fontSize: tokens.typography.fontSize.base.value,
  borderRadius: tokens.border.radius.md.value
};
```

### React with TypeScript

```tsx
import { tokens, TokenColors, TokenSpacing } from '@hydrogen-ui/tokens';

interface ButtonProps {
  color?: keyof TokenColors;
  spacing?: keyof TokenSpacing;
}

function Button({ color = 'primary', spacing = 'md' }: ButtonProps) {
  return (
    <button
      style={{
        backgroundColor: tokens.color.button[color].background.value,
        padding: tokens.spacing[spacing].value
      }}
    >
      Click me
    </button>
  );
}
```

## Token Categories

### Global Tokens

#### Colors
Complete color palette with 10 shades for each color:

```tsx
// Base colors
tokens.color.black    // #000000
tokens.color.white    // #FFFFFF

// Gray scale (50-900)
tokens.color.gray[50]   // #F9FAFB
tokens.color.gray[100]  // #F3F4F6
tokens.color.gray[200]  // #E5E7EB
// ... up to gray[900]

// Color palettes (50-900)
tokens.color.red[500]    // #EF4444
tokens.color.green[500]  // #10B981
tokens.color.blue[500]   // #3B82F6
tokens.color.yellow[500] // #F59E0B
```

#### Typography

```tsx
// Font families
tokens.typography.fontFamily.sans  // 'Inter', system-ui, ...
tokens.typography.fontFamily.serif // 'Georgia', serif
tokens.typography.fontFamily.mono  // 'Fira Code', monospace

// Font sizes
tokens.typography.fontSize.xs   // 0.75rem (12px)
tokens.typography.fontSize.sm   // 0.875rem (14px)
tokens.typography.fontSize.base // 1rem (16px)
tokens.typography.fontSize.lg   // 1.125rem (18px)
tokens.typography.fontSize.xl   // 1.25rem (20px)
// ... up to 9xl

// Font weights
tokens.typography.fontWeight.thin       // 100
tokens.typography.fontWeight.light      // 300
tokens.typography.fontWeight.normal     // 400
tokens.typography.fontWeight.medium     // 500
tokens.typography.fontWeight.semibold   // 600
tokens.typography.fontWeight.bold       // 700
tokens.typography.fontWeight.extrabold  // 800
tokens.typography.fontWeight.black      // 900

// Line heights
tokens.typography.lineHeight.none     // 1
tokens.typography.lineHeight.tight    // 1.25
tokens.typography.lineHeight.snug     // 1.375
tokens.typography.lineHeight.normal   // 1.5
tokens.typography.lineHeight.relaxed  // 1.625
tokens.typography.lineHeight.loose    // 2

// Letter spacing
tokens.typography.letterSpacing.tighter  // -0.05em
tokens.typography.letterSpacing.tight    // -0.025em
tokens.typography.letterSpacing.normal   // 0
tokens.typography.letterSpacing.wide     // 0.025em
tokens.typography.letterSpacing.wider    // 0.05em
tokens.typography.letterSpacing.widest   // 0.1em
```

#### Spacing

Consistent spacing scale based on rem units:

```tsx
tokens.spacing[0]    // 0
tokens.spacing.px    // 1px
tokens.spacing[0.5]  // 0.125rem (2px)
tokens.spacing[1]    // 0.25rem (4px)
tokens.spacing[2]    // 0.5rem (8px)
tokens.spacing[3]    // 0.75rem (12px)
tokens.spacing[4]    // 1rem (16px)
// ... up to spacing[96]

// Named aliases
tokens.spacing.xs    // 0.5rem
tokens.spacing.sm    // 1rem
tokens.spacing.md    // 1.5rem
tokens.spacing.lg    // 2rem
tokens.spacing.xl    // 3rem
tokens.spacing['2xl'] // 4rem
```

#### Shadows

Box shadow presets:

```tsx
tokens.shadow.none   // none
tokens.shadow.sm     // 0 1px 2px 0 rgba(0, 0, 0, 0.05)
tokens.shadow.base   // 0 1px 3px 0 rgba(0, 0, 0, 0.1), ...
tokens.shadow.md     // 0 4px 6px -1px rgba(0, 0, 0, 0.1), ...
tokens.shadow.lg     // 0 10px 15px -3px rgba(0, 0, 0, 0.1), ...
tokens.shadow.xl     // 0 20px 25px -5px rgba(0, 0, 0, 0.1), ...
tokens.shadow['2xl'] // 0 25px 50px -12px rgba(0, 0, 0, 0.25)
tokens.shadow.inner  // inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)
```

#### Borders

```tsx
// Border widths
tokens.border.width.none    // 0
tokens.border.width.thin    // 1px
tokens.border.width.base    // 2px
tokens.border.width.thick   // 4px
tokens.border.width.heavy   // 8px

// Border radius
tokens.border.radius.none   // 0
tokens.border.radius.sm     // 0.125rem
tokens.border.radius.base   // 0.25rem
tokens.border.radius.md     // 0.375rem
tokens.border.radius.lg     // 0.5rem
tokens.border.radius.xl     // 0.75rem
tokens.border.radius['2xl'] // 1rem
tokens.border.radius['3xl'] // 1.5rem
tokens.border.radius.full   // 9999px
```

#### Animation

```tsx
// Durations
tokens.animation.duration.instant  // 0ms
tokens.animation.duration.fast     // 150ms
tokens.animation.duration.normal   // 300ms
tokens.animation.duration.slow     // 500ms
tokens.animation.duration.slower   // 700ms
tokens.animation.duration.slowest  // 1000ms

// Easing functions
tokens.animation.easing.linear      // linear
tokens.animation.easing.easeIn      // cubic-bezier(0.4, 0, 1, 1)
tokens.animation.easing.easeOut     // cubic-bezier(0, 0, 0.2, 1)
tokens.animation.easing.easeInOut   // cubic-bezier(0.4, 0, 0.2, 1)
tokens.animation.easing.bounce      // cubic-bezier(0.68, -0.55, 0.265, 1.55)
```

### Semantic Tokens

Purpose-driven tokens that reference global tokens:

#### Text Colors

```tsx
tokens.color.text.primary    // Primary text color
tokens.color.text.secondary  // Secondary/muted text
tokens.color.text.disabled   // Disabled state text
tokens.color.text.inverse    // Inverted text (on dark backgrounds)
tokens.color.text.link       // Link color
tokens.color.text.visited    // Visited link color
tokens.color.text.hover      // Hover state text
```

#### Background Colors

```tsx
tokens.color.background.primary    // Main background
tokens.color.background.secondary  // Secondary sections
tokens.color.background.tertiary   // Tertiary/subtle backgrounds
tokens.color.background.inverse    // Inverted backgrounds
```

#### Component Tokens

Pre-configured values for common components:

```tsx
// Buttons
tokens.component.button.height.sm       // 2rem
tokens.component.button.height.md       // 2.5rem
tokens.component.button.height.lg       // 3rem
tokens.component.button.padding.sm      // 0.5rem 1rem
tokens.component.button.padding.md      // 0.75rem 1.5rem
tokens.component.button.padding.lg      // 1rem 2rem
tokens.component.button.fontSize.sm     // 0.875rem
tokens.component.button.fontSize.md     // 1rem
tokens.component.button.fontSize.lg     // 1.125rem

// Inputs
tokens.component.input.height.sm        // 2rem
tokens.component.input.height.md        // 2.5rem
tokens.component.input.height.lg        // 3rem
tokens.component.input.padding.sm       // 0.5rem 0.75rem
tokens.component.input.padding.md       // 0.75rem 1rem
tokens.component.input.padding.lg       // 1rem 1.25rem

// Cards
tokens.component.card.padding.sm        // 1rem
tokens.component.card.padding.md        // 1.5rem
tokens.component.card.padding.lg        // 2rem
tokens.component.card.shadow            // shadow.md
tokens.component.card.borderRadius      // border.radius.lg

// Modals
tokens.component.modal.padding.sm       // 1rem
tokens.component.modal.padding.md       // 1.5rem
tokens.component.modal.padding.lg       // 2rem
tokens.component.modal.maxWidth.sm      // 24rem
tokens.component.modal.maxWidth.md      // 32rem
tokens.component.modal.maxWidth.lg      // 48rem
```

## Usage Patterns

### Component Development

```tsx
import { tokens } from '@hydrogen-ui/tokens';

// Consistent component styling
const Button = styled.button`
  /* Size variants using component tokens */
  &.sm {
    height: ${tokens.component.button.height.sm.value};
    padding: ${tokens.component.button.padding.sm.value};
    font-size: ${tokens.component.button.fontSize.sm.value};
  }
  
  &.md {
    height: ${tokens.component.button.height.md.value};
    padding: ${tokens.component.button.padding.md.value};
    font-size: ${tokens.component.button.fontSize.md.value};
  }
  
  /* State colors using semantic tokens */
  background-color: ${tokens.color.button.primary.background.value};
  color: ${tokens.color.button.primary.text.value};
  
  &:hover {
    background-color: ${tokens.color.button.primary.hover.value};
  }
  
  &:active {
    background-color: ${tokens.color.button.primary.active.value};
  }
  
  &:disabled {
    background-color: ${tokens.color.button.primary.disabled.value};
    cursor: not-allowed;
  }
  
  /* Consistent styling */
  border-radius: ${tokens.border.radius.md.value};
  font-weight: ${tokens.typography.fontWeight.medium.value};
  transition: all ${tokens.animation.duration.fast.value} ${tokens.animation.easing.easeOut.value};
`;
```

### Responsive Design

```tsx
// Using tokens for responsive breakpoints
const ResponsiveGrid = styled.div`
  display: grid;
  gap: ${tokens.spacing.md.value};
  
  /* Mobile */
  grid-template-columns: 1fr;
  padding: ${tokens.spacing.sm.value};
  
  /* Tablet */
  @media (min-width: 768px) {
    grid-template-columns: repeat(2, 1fr);
    gap: ${tokens.spacing.lg.value};
    padding: ${tokens.spacing.md.value};
  }
  
  /* Desktop */
  @media (min-width: 1024px) {
    grid-template-columns: repeat(3, 1fr);
    gap: ${tokens.spacing.xl.value};
    padding: ${tokens.spacing.lg.value};
  }
`;
```

### Dark Mode Support

```tsx
// Define color schemes using tokens
const lightTheme = {
  background: tokens.color.white.value,
  text: tokens.color.gray[900].value,
  border: tokens.color.gray[200].value
};

const darkTheme = {
  background: tokens.color.gray[900].value,
  text: tokens.color.gray[50].value,
  border: tokens.color.gray[700].value
};

// Apply based on theme
const ThemedComponent = styled.div`
  background-color: ${props => props.theme.background};
  color: ${props => props.theme.text};
  border: 1px solid ${props => props.theme.border};
`;
```

## TypeScript Support

The package includes comprehensive TypeScript definitions:

```typescript
import type { 
  Tokens,
  TokenColors,
  TokenSpacing,
  TokenTypography,
  TokenShadows,
  TokenBorders,
  TokenAnimation,
  TokenComponents
} from '@hydrogen-ui/tokens';

// Type-safe token access
function getSpacing(size: keyof TokenSpacing): string {
  return tokens.spacing[size].value;
}

// Component prop types
interface StyledProps {
  color?: keyof TokenColors;
  spacing?: keyof TokenSpacing;
  fontSize?: keyof TokenTypography['fontSize'];
}
```

## Custom Themes

Create custom themes by extending or overriding base tokens:

### Directory Structure
```
src/
├── themes/
│   └── my-theme/
│       ├── color.json
│       ├── typography.json
│       └── component.json
```

### Theme Configuration

```json
// src/themes/my-theme/color.json
{
  "color": {
    "primary": {
      "50": { "value": "#E3F2FD" },
      "100": { "value": "#BBDEFB" },
      "500": { "value": "#2196F3" },
      "900": { "value": "#0D47A1" }
    },
    "text": {
      "primary": { "value": "{color.gray.900.value}" },
      "secondary": { "value": "{color.gray.600.value}" }
    }
  }
}
```

### Building Custom Themes

```bash
# Add your theme to the build config
npm run build:tokens -- --theme my-theme

# Generate all formats
npm run build
```

## Build Configuration

The package uses Style Dictionary for token generation:

```javascript
// style-dictionary.config.js
module.exports = {
  source: ['src/**/*.json'],
  platforms: {
    css: {
      transformGroup: 'css',
      buildPath: 'dist/css/',
      files: [{
        destination: 'variables.css',
        format: 'css/variables'
      }]
    },
    js: {
      transformGroup: 'js',
      buildPath: 'dist/js/',
      files: [{
        destination: 'tokens.js',
        format: 'javascript/es6'
      }]
    },
    json: {
      transformGroup: 'js',
      buildPath: 'dist/json/',
      files: [{
        destination: 'tokens.json',
        format: 'json/nested'
      }]
    }
  }
};
```

## Integration Examples

### With CSS-in-JS Libraries

```tsx
// Styled Components
import styled from 'styled-components';
import { tokens } from '@hydrogen-ui/tokens';

const Card = styled.div`
  background: ${tokens.color.background.primary.value};
  padding: ${tokens.component.card.padding.md.value};
  border-radius: ${tokens.component.card.borderRadius.value};
  box-shadow: ${tokens.component.card.shadow.value};
`;

// Emotion
import { css } from '@emotion/react';

const cardStyles = css`
  background: ${tokens.color.background.primary.value};
  padding: ${tokens.component.card.padding.md.value};
  border-radius: ${tokens.component.card.borderRadius.value};
  box-shadow: ${tokens.component.card.shadow.value};
`;
```

### With Tailwind CSS

```javascript
// tailwind.config.js
const { tokens } = require('@hydrogen-ui/tokens');

module.exports = {
  theme: {
    extend: {
      colors: {
        primary: tokens.color.primary,
        gray: tokens.color.gray
      },
      spacing: tokens.spacing,
      fontSize: tokens.typography.fontSize,
      fontWeight: tokens.typography.fontWeight,
      borderRadius: tokens.border.radius,
      boxShadow: tokens.shadow
    }
  }
};
```

### With Sass

```scss
// Import generated Sass variables
@import '@hydrogen-ui/tokens/dist/scss/variables';

.button {
  background-color: $color-button-primary-background;
  color: $color-button-primary-text;
  padding: $component-button-padding-md;
  border-radius: $border-radius-md;
  
  &:hover {
    background-color: $color-button-primary-hover;
  }
}
```

## Design Token Best Practices

1. **Use Semantic Tokens**: Prefer semantic tokens over global tokens for better maintainability
   ```tsx
   // ✅ Good
   color: tokens.color.text.primary.value
   
   // ❌ Avoid
   color: tokens.color.gray[900].value
   ```

2. **Component Tokens for Consistency**: Use component tokens for standard UI elements
   ```tsx
   // ✅ Good
   height: tokens.component.button.height.md.value
   
   // ❌ Avoid
   height: '40px'
   ```

3. **Type Safety**: Leverage TypeScript for compile-time checks
   ```tsx
   // ✅ Good
   function getColor(variant: keyof TokenColors): string {
     return tokens.color[variant].value;
   }
   ```

4. **Token References**: Use token references in your custom tokens
   ```json
   {
     "button": {
       "primary": {
         "background": { "value": "{color.primary.500.value}" }
       }
     }
   }
   ```

## Browser Support

- Modern browsers with CSS Custom Properties support
- IE11 requires polyfills for CSS variables
- All JavaScript tokens work in any environment

## Contributing

### Adding New Tokens

1. Add token definitions to appropriate category in `src/`
2. Follow existing naming conventions
3. Include semantic aliases where appropriate
4. Run `npm run build` to generate outputs
5. Update TypeScript definitions if needed

### Token Naming Convention

- Use lowercase with dots as separators
- Start with category (color, spacing, typography)
- Include subcategories as needed
- End with specific value or variant

```
category.subcategory.variant.state.property
color.button.primary.hover.background
```

## License

MIT