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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@hydrogen-ui/core

v0.1.0

Published

Core utilities and hooks for Hydrogen UI

Downloads

7

Readme

@hydrogen-ui/core

The foundational package for Hydrogen UI that provides theme management, design token system, and core utilities for building Shopify Hydrogen storefronts.

Installation

npm install @hydrogen-ui/core
# or
yarn add @hydrogen-ui/core
# or
pnpm add @hydrogen-ui/core

Features

  • 🎨 Theme System - Built-in themes with runtime switching
  • 🎯 Design Tokens - Comprehensive token system with dot notation access
  • Performance - Advanced caching with LRU and stale-while-revalidate
  • 🔧 TypeScript - Full type safety and autocompletion
  • 🌗 Dark Mode - System preference detection and persistence
  • 💾 SSR Support - Server-side rendering compatible
  • 🎭 CSS Variables - Automatic CSS custom property generation

Quick Start

import { HydrogenUIProvider } from '@hydrogen-ui/core';
import { tokens } from '@hydrogen-ui/tokens';
import { dawn } from '@hydrogen-ui/themes';

function App() {
  return (
    <HydrogenUIProvider tokens={tokens} theme={dawn}>
      <YourApp />
    </HydrogenUIProvider>
  );
}

Provider System

HydrogenUIProvider

The root provider that sets up the entire Hydrogen UI system.

<HydrogenUIProvider
  tokens={tokens}           // Design tokens object
  theme="dawn"              // Theme name or theme object
  themes={customThemes}     // Additional custom themes
  cache={customCache}       // Custom token cache instance
  onThemeChange={handler}   // Theme change callback
>
  <App />
</HydrogenUIProvider>

Props:

  • tokens (required) - Base design tokens object
  • theme - Theme name (string) or theme object
  • themes - Object containing additional custom themes
  • cache - Custom TokenCache instance
  • onThemeChange - Callback fired when theme changes
  • children - React children

ThemeProvider

Lower-level provider for theme management (used internally by HydrogenUIProvider).

<ThemeProvider
  theme="studio"
  themes={themes}
  tokens={mergedTokens}
  onThemeChange={(newTheme) => console.log('Theme changed to:', newTheme)}
>
  <App />
</ThemeProvider>

TokenProvider

Lower-level provider for token access (used internally by HydrogenUIProvider).

<TokenProvider tokens={tokens} cache={cache}>
  <App />
</TokenProvider>

Hooks

useToken

Access full token objects with metadata.

import { useToken } from '@hydrogen-ui/core';

function Component() {
  const colorToken = useToken('color.primary.500');
  // Returns: { value: '#FF6B6B', type: 'color', description: '...' }
  
  const spacingToken = useToken('spacing.md');
  // Returns: { value: '16px' } or just '16px' if direct value
  
  return <div style={{ color: colorToken.value }}>Content</div>;
}

useTokenValue

Access token values directly (most common use case).

import { useTokenValue } from '@hydrogen-ui/core';

function Component() {
  const primaryColor = useTokenValue('color.primary.500');
  // Returns: '#FF6B6B'
  
  const spacing = useTokenValue('spacing.lg');
  // Returns: '24px'
  
  // Also accepts token objects
  const token = { value: '#000', type: 'color' };
  const value = useTokenValue(token);
  // Returns: '#000'
  
  return (
    <div style={{ 
      color: primaryColor,
      padding: spacing 
    }}>
      Styled content
    </div>
  );
}

useTheme

Manage themes with persistence and system preferences.

import { useTheme } from '@hydrogen-ui/core';

function ThemeSelector() {
  const { 
    theme,              // Current theme name
    setTheme,           // Theme setter function
    availableThemes,    // Array of available theme names
    tokens              // Current theme's tokens
  } = useTheme();
  
  return (
    <select value={theme} onChange={(e) => setTheme(e.target.value)}>
      {availableThemes.map((themeName) => (
        <option key={themeName} value={themeName}>
          {themeName}
        </option>
      ))}
    </select>
  );
}

Design Tokens

Token Structure

Tokens follow a hierarchical structure with dot notation access:

{
  color: {
    primary: {
      50: '#FFF5F5',
      100: '#FED7D7',
      500: '#FF6B6B',
      900: '#742A2A'
    },
    text: {
      primary: '#1A202C',
      secondary: '#718096'
    }
  },
  spacing: {
    xs: '4px',
    sm: '8px',
    md: '16px',
    lg: '24px'
  },
  typography: {
    fontSize: {
      sm: '14px',
      base: '16px',
      lg: '18px'
    }
  }
}

Token References

Tokens can reference other tokens using the {token.path} syntax:

{
  color: {
    primary: {
      base: '#FF6B6B'
    },
    button: {
      background: '{color.primary.base}',  // References primary color
      hover: '{color.primary.700}'
    }
  }
}

Token Objects

Tokens can be simple values or objects with metadata:

{
  color: {
    primary: {
      // Simple value
      500: '#FF6B6B',
      
      // Object with metadata
      600: {
        value: '#E53E3E',
        type: 'color',
        description: 'Primary brand color - hover state'
      }
    }
  }
}

Caching System

Built-in Cache Strategies

import { 
  createTokenCacheShort,
  createTokenCacheLong,
  createTokenCacheCustom 
} from '@hydrogen-ui/core';

// Short-lived cache (1 second + 9 seconds SWR)
const shortCache = createTokenCacheShort();

// Long-lived cache (1 hour + 24 hours SWR)
const longCache = createTokenCacheLong();

// Custom cache configuration
const customCache = createTokenCacheCustom({
  maxAge: 300000,      // 5 minutes
  staleWhileRevalidate: 600000,  // 10 minutes
  maxSize: 1000        // Maximum entries
});

// Use with provider
<HydrogenUIProvider tokens={tokens} cache={customCache}>
  <App />
</HydrogenUIProvider>

TokenCache API

import { TokenCache } from '@hydrogen-ui/core';

const cache = new TokenCache({
  maxAge: 60000,              // Max age in milliseconds
  staleWhileRevalidate: 300000,  // SWR period
  maxSize: 500                // Maximum cache entries
});

// Get cached value
const value = cache.get('color.primary.500');

// Set value
cache.set('color.primary.500', '#FF6B6B');

// Clear cache
cache.clear();

// Get cache statistics
const stats = cache.getStats();
// { hits: 150, misses: 20, size: 45 }

CSS Integration

CSS Variable Generation

Tokens are automatically converted to CSS custom properties:

// Token: color.primary.500 = '#FF6B6B'
// CSS Variable: --color-primary-500: #FF6B6B

// Usage in CSS
.button {
  background-color: var(--color-primary-500);
  padding: var(--spacing-md);
}

Inline Styles Helper

import { createTokenStyle, createInlineTokenStyle } from '@hydrogen-ui/core';

// Create style object from tokens
const styles = createTokenStyle({
  color: 'color.text.primary',
  padding: 'spacing.md',
  fontSize: 'typography.fontSize.lg'
});
// Returns: { color: '#1A202C', padding: '16px', fontSize: '18px' }

// Create inline style string
const inlineStyle = createInlineTokenStyle({
  backgroundColor: 'color.surface.secondary',
  borderRadius: 'radius.md'
});
// Returns: "background-color: #F7FAFC; border-radius: 8px;"

CSS Classes

import { createTokenClasses } from '@hydrogen-ui/core';

const classes = createTokenClasses({
  text: 'color.primary.500',
  bg: 'color.surface.primary',
  p: 'spacing.lg'
});
// Returns: "text-primary-500 bg-surface-primary p-lg"

Theme System

Built-in Themes

The package includes five professionally designed themes:

  • dawn - Clean and minimal design with excellent readability
  • craft - Artisanal feel with warm colors and organic shapes
  • studio - Modern and bold with high contrast
  • b2b - Professional theme for business applications
  • thnk - Creative and playful with vibrant colors

Theme Structure

interface Theme {
  name: string;
  tokens: {
    color?: Record<string, any>;
    typography?: Record<string, any>;
    spacing?: Record<string, any>;
    // ... other token categories
  };
}

Custom Themes

Create custom themes by extending base tokens:

const myCustomTheme = {
  name: 'my-brand',
  tokens: {
    color: {
      primary: {
        50: '#F0F9FF',
        500: '#3B82F6',
        900: '#1E3A8A'
      },
      text: {
        primary: '#0F172A',
        secondary: '#64748B'
      }
    },
    typography: {
      fontFamily: {
        body: '"Inter", system-ui, sans-serif',
        heading: '"Playfair Display", serif'
      }
    }
  }
};

// Use custom theme
<HydrogenUIProvider 
  tokens={baseTokens} 
  theme={myCustomTheme}
>
  <App />
</HydrogenUIProvider>

Theme Persistence

Themes are automatically persisted to localStorage and restored on page load:

// Theme preference saved as 'hydrogen-ui-theme'
localStorage.getItem('hydrogen-ui-theme'); // 'studio'

// Disable persistence
<HydrogenUIProvider 
  tokens={tokens} 
  theme="dawn"
  persistTheme={false}
>
  <App />
</HydrogenUIProvider>

Server-Side Rendering

The package is SSR-safe with proper hydration support:

// app/root.tsx (Remix example)
export default function App() {
  return (
    <html>
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <HydrogenUIProvider tokens={tokens} theme="dawn">
          <Outlet />
        </HydrogenUIProvider>
        <Scripts />
      </body>
    </html>
  );
}

TypeScript Support

Token Type Safety

import type { TokenPath, TokenValue } from '@hydrogen-ui/core';

// Type-safe token paths
const getColor = (path: TokenPath): TokenValue => {
  return useTokenValue(path);
};

// Custom token types
interface MyTokens {
  color: {
    brand: string;
    accent: string;
  };
}

const tokens: MyTokens = {
  color: {
    brand: '#FF6B6B',
    accent: '#4ECDC4'
  }
};

Provider Types

import type { 
  HydrogenUIProviderProps,
  Theme,
  ThemeContextValue,
  TokenCache 
} from '@hydrogen-ui/core';

// Custom provider wrapper
const MyProvider: React.FC<HydrogenUIProviderProps> = (props) => {
  return <HydrogenUIProvider {...props} />;
};

Performance Optimization

Memoization

Token lookups are memoized at multiple levels:

  1. Provider level - Merged tokens are memoized
  2. Hook level - Token paths are memoized with useMemo
  3. Cache level - LRU cache with configurable TTL

Bundle Size

The core package is optimized for tree-shaking:

// Only import what you need
import { useTokenValue } from '@hydrogen-ui/core';

// Tree-shakeable theme imports
import { dawn } from '@hydrogen-ui/themes/dawn';

Migration Guide

From CSS Variables

/* Before */
:root {
  --primary-color: #FF6B6B;
  --spacing-md: 16px;
}

.button {
  background: var(--primary-color);
  padding: var(--spacing-md);
}
// After
const tokens = {
  color: { primary: { base: '#FF6B6B' } },
  spacing: { md: '16px' }
};

function Button() {
  const bg = useTokenValue('color.primary.base');
  const padding = useTokenValue('spacing.md');
  
  return <button style={{ background: bg, padding }}>Click</button>;
}

From Theme Context

// Before
const theme = useContext(ThemeContext);
const color = theme.colors.primary;

// After
const color = useTokenValue('color.primary');

Best Practices

  1. Use Token Values - Prefer useTokenValue over useToken for simple value access
  2. Cache Strategy - Use long cache for static tokens, short cache for dynamic values
  3. Theme Structure - Keep theme tokens flat for better performance
  4. Token Naming - Use consistent naming: category.property.variant
  5. Type Safety - Define custom token types for better TypeScript support

Contributing

See Contributing Guide

License

MIT