@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/coreFeatures
- 🎨 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 objecttheme- Theme name (string) or theme objectthemes- Object containing additional custom themescache- Custom TokenCache instanceonThemeChange- Callback fired when theme changeschildren- 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:
- Provider level - Merged tokens are memoized
- Hook level - Token paths are memoized with useMemo
- 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
- Use Token Values - Prefer
useTokenValueoveruseTokenfor simple value access - Cache Strategy - Use long cache for static tokens, short cache for dynamic values
- Theme Structure - Keep theme tokens flat for better performance
- Token Naming - Use consistent naming: category.property.variant
- Type Safety - Define custom token types for better TypeScript support
Contributing
License
MIT
