@tamyla/ui-components-react
Version:
React-based UI component library with Factory Bridge pattern - integrates seamlessly with @tamyla/ui-components. Enhanced AI agent discoverability with structured component registry, comprehensive Storybook (8 components), and detailed guides.
498 lines (436 loc) • 21.7 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tamyla UI Components - Themed Showcase</title>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script src="https://unpkg.com/redux@4.2.1/dist/redux.min.js"></script>
<script src="https://unpkg.com/react-redux@8.1.3/dist/react-redux.min.js"></script>
<script src="https://unpkg.com/@reduxjs/toolkit@1.9.7/dist/redux-toolkit.umd.min.js"></script>
<script src="https://unpkg.com/styled-components@6.1.8/dist/styled-components.min.js"></script>
<script src="https://unpkg.com/framer-motion@10.16.16/dist/framer-motion.min.js"></script>
<!-- Import the design tokens CSS -->
<link rel="stylesheet" href="../src/core/design-tokens.css">
<style>
body {
margin: 0;
padding: 20px;
background: var(--background);
color: var(--foreground);
font-family: var(--font-family);
transition: all 0.3s ease;
}
.theme-toggle {
position: fixed;
top: 20px;
right: 20px;
padding: var(--space-2) var(--space-4);
background: var(--primary);
color: var(--primary-foreground);
border: none;
border-radius: var(--radius);
cursor: pointer;
font-weight: var(--font-weight-medium);
z-index: var(--z-fixed);
}
.showcase-container {
max-width: 1200px;
margin: 0 auto;
}
.showcase-header {
text-align: center;
margin-bottom: var(--space-12);
padding: var(--space-8);
background: var(--surface-elevated);
border-radius: var(--radius-lg);
box-shadow: var(--shadow);
}
.showcase-header h1 {
margin: 0 0 var(--space-4) 0;
font-size: 2.5rem;
font-weight: var(--font-weight-bold);
color: var(--text-primary);
}
.component-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: var(--space-6);
margin-bottom: var(--space-12);
}
.component-demo {
background: var(--surface-primary);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: var(--space-6);
box-shadow: var(--shadow-sm);
transition: all 0.2s ease;
}
.component-demo:hover {
box-shadow: var(--shadow-md);
transform: translateY(-2px);
}
.component-title {
font-size: var(--font-size-lg);
font-weight: var(--font-weight-semibold);
margin-bottom: var(--space-4);
color: var(--text-primary);
}
.demo-controls {
display: flex;
gap: var(--space-2);
margin-bottom: var(--space-4);
flex-wrap: wrap;
}
.demo-button {
padding: var(--space-2) var(--space-4);
border: 1px solid var(--border);
border-radius: var(--radius);
background: var(--surface-secondary);
color: var(--text-secondary);
cursor: pointer;
font-size: var(--font-size-sm);
transition: all 0.2s ease;
}
.demo-button:hover {
background: var(--primary);
color: var(--primary-foreground);
border-color: var(--primary);
}
.demo-button.active {
background: var(--primary);
color: var(--primary-foreground);
border-color: var(--primary);
}
.color-palette {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: var(--space-3);
margin-top: var(--space-6);
}
.color-item {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--space-2);
}
.color-swatch {
width: 60px;
height: 60px;
border-radius: var(--radius);
border: 2px solid var(--border);
box-shadow: var(--shadow-sm);
}
.color-name {
font-size: var(--font-size-xs);
color: var(--text-secondary);
text-align: center;
}
.spacing-demo {
display: flex;
flex-direction: column;
gap: var(--space-4);
}
.spacing-item {
display: flex;
align-items: center;
gap: var(--space-3);
}
.spacing-bar {
height: 20px;
background: var(--primary);
border-radius: var(--radius-sm);
}
.typography-demo {
display: flex;
flex-direction: column;
gap: var(--space-4);
}
.text-sample {
padding: var(--space-2);
border-left: 3px solid var(--primary);
background: var(--surface-secondary);
border-radius: 0 var(--radius) var(--radius) 0;
}
/* Dark theme styles */
body.dark .showcase-header {
background: var(--surface-elevated);
}
body.dark .component-demo {
background: var(--surface-primary);
border-color: var(--border);
}
body.dark .demo-button {
background: var(--surface-secondary);
border-color: var(--border);
color: var(--text-secondary);
}
</style>
</head>
<body>
<button class="theme-toggle" onclick="toggleTheme()">Toggle Theme</button>
<div class="showcase-container">
<div class="showcase-header">
<h1>🎨 Tamyla UI Components</h1>
<p>Design System with CSS Custom Properties & Theme Provider</p>
<p><strong>Version:</strong> 1.0.0 | <strong>Theme:</strong> <span id="theme-status">Light</span></p>
</div>
<!-- Loading State -->
<div id="loading" style="display: flex; align-items: center; justify-content: center; min-height: 200px; color: var(--text-secondary);">
<div>🔄 Loading themed components...</div>
</div>
<!-- Main React App Container -->
<div id="react-app" style="display: none;"></div>
</div>
<!-- React Application -->
<script type="text/babel">
const { useState, useEffect } = React;
const { Provider } = ReactRedux;
const { configureStore, createSlice } = RTK;
// Mock the actual UI components library for demo purposes
// In a real app, you'd import: import { Button, Card, TamylaThemeProvider } from '@tamyla/ui-components-react'
const TamylaUIComponents = {
Button: ({ children, variant = 'default', size = 'default', onClick, className = '', ...props }) => {
const baseClasses = 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none';
const variantClasses = {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline: 'border border-input hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'underline-offset-4 hover:underline text-primary'
};
const sizeClasses = {
default: 'h-10 py-2 px-4',
sm: 'h-9 px-3 rounded-md',
lg: 'h-11 px-8 rounded-md',
icon: 'h-10 w-10'
};
return React.createElement('button', {
onClick,
className: `${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]} ${className}`,
...props
}, children);
},
Card: ({ children, className = '', ...props }) => {
return React.createElement('div', {
className: `rounded-lg border bg-card text-card-foreground shadow-sm ${className}`,
...props
}, children);
},
CardHeader: ({ children, className = '', ...props }) => {
return React.createElement('div', {
className: `flex flex-col space-y-1.5 p-6 ${className}`,
...props
}, children);
},
CardTitle: ({ children, className = '', ...props }) => {
return React.createElement('h3', {
className: `text-2xl font-semibold leading-none tracking-tight ${className}`,
...props
}, children);
},
CardContent: ({ children, className = '', ...props }) => {
return React.createElement('div', {
className: `p-6 pt-0 ${className}`,
...props
}, children);
}
};
// Theme store setup
const themeSlice = createSlice({
name: 'theme',
initialState: {
mode: 'light',
primaryColor: '#3b82f6',
fontSize: 'md',
animations: true,
reducedMotion: false,
highContrast: false
},
reducers: {
toggleTheme: (state) => {
state.mode = state.mode === 'light' ? 'dark' : 'light';
}
}
});
const store = configureStore({
reducer: {
theme: themeSlice.reducer
}
});
// Main App Component
const App = () => {
const [activeDemo, setActiveDemo] = useState('buttons');
return React.createElement(Provider, { store },
React.createElement('div', null,
React.createElement('div', { className: 'component-grid' },
React.createElement('div', { className: 'component-demo' },
React.createElement('h3', { className: 'component-title' }, '🎯 Buttons'),
React.createElement('div', { className: 'demo-controls' },
React.createElement('button', {
className: `demo-button ${activeDemo === 'buttons' ? 'active' : ''}`,
onClick: () => setActiveDemo('buttons')
}, 'Variants'),
React.createElement('button', {
className: `demo-button ${activeDemo === 'sizes' ? 'active' : ''}`,
onClick: () => setActiveDemo('sizes')
}, 'Sizes')
),
activeDemo === 'buttons' ? React.createElement(ButtonVariants) : React.createElement(ButtonSizes)
),
React.createElement('div', { className: 'component-demo' },
React.createElement('h3', { className: 'component-title' }, '📋 Cards'),
React.createElement(CardDemo)
),
React.createElement('div', { className: 'component-demo' },
React.createElement('h3', { className: 'component-title' }, '🎨 Colors'),
React.createElement(ColorPalette)
),
React.createElement('div', { className: 'component-demo' },
React.createElement('h3', { className: 'component-title' }, '📏 Spacing'),
React.createElement(SpacingDemo)
),
React.createElement('div', { className: 'component-demo' },
React.createElement('h3', { className: 'component-title' }, '📝 Typography'),
React.createElement(TypographyDemo)
),
React.createElement('div', { className: 'component-demo' },
React.createElement('h3', { className: 'component-title' }, '🔧 Design Tokens'),
React.createElement(DesignTokensDemo)
)
)
)
);
};
// Demo Components
const ButtonVariants = () => {
return React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 'var(--space-3)' } },
React.createElement(TamylaUIComponents.Button, { variant: 'default' }, 'Default Button'),
React.createElement(TamylaUIComponents.Button, { variant: 'secondary' }, 'Secondary Button'),
React.createElement(TamylaUIComponents.Button, { variant: 'destructive' }, 'Destructive Button'),
React.createElement(TamylaUIComponents.Button, { variant: 'outline' }, 'Outline Button'),
React.createElement(TamylaUIComponents.Button, { variant: 'ghost' }, 'Ghost Button'),
React.createElement(TamylaUIComponents.Button, { variant: 'link' }, 'Link Button')
);
};
const ButtonSizes = () => {
return React.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 'var(--space-3)' } },
React.createElement(TamylaUIComponents.Button, { size: 'sm' }, 'Small Button'),
React.createElement(TamylaUIComponents.Button, { size: 'default' }, 'Default Button'),
React.createElement(TamylaUIComponents.Button, { size: 'lg' }, 'Large Button')
);
};
const CardDemo = () => {
return React.createElement(TamylaUIComponents.Card, null,
React.createElement(TamylaUIComponents.CardHeader, null,
React.createElement(TamylaUIComponents.CardTitle, null, 'Card Title')
),
React.createElement(TamylaUIComponents.CardContent, null,
React.createElement('p', null, 'This card uses design tokens for consistent styling across light and dark themes.')
)
);
};
const ColorPalette = () => {
const colors = [
{ name: 'Primary', value: 'var(--primary)' },
{ name: 'Secondary', value: 'var(--neutral-200)' },
{ name: 'Success', value: 'var(--success)' },
{ name: 'Warning', value: 'var(--warning)' },
{ name: 'Error', value: 'var(--error)' },
{ name: 'Background', value: 'var(--background)' }
];
return React.createElement('div', { className: 'color-palette' },
colors.map(color =>
React.createElement('div', { key: color.name, className: 'color-item' },
React.createElement('div', {
className: 'color-swatch',
style: { backgroundColor: color.value }
}),
React.createElement('span', { className: 'color-name' }, color.name)
)
)
);
};
const SpacingDemo = () => {
const spaces = [
{ name: 'space-1', value: 'var(--space-1)', width: '25px' },
{ name: 'space-2', value: 'var(--space-2)', width: '50px' },
{ name: 'space-4', value: 'var(--space-4)', width: '100px' },
{ name: 'space-6', value: 'var(--space-6)', width: '150px' },
{ name: 'space-8', value: 'var(--space-8)', width: '200px' }
];
return React.createElement('div', { className: 'spacing-demo' },
spaces.map(space =>
React.createElement('div', { key: space.name, className: 'spacing-item' },
React.createElement('span', { style: { minWidth: '80px', fontSize: 'var(--font-size-sm)', color: 'var(--text-secondary)' } }, space.name),
React.createElement('div', {
className: 'spacing-bar',
style: { width: space.width }
})
)
)
);
};
const TypographyDemo = () => {
return React.createElement('div', { className: 'typography-demo' },
React.createElement('div', { className: 'text-sample' },
React.createElement('div', { style: { fontSize: 'var(--font-size-xs)' } }, 'Extra Small Text (xs)'),
React.createElement('div', { style: { fontSize: 'var(--font-size-sm)' } }, 'Small Text (sm)'),
React.createElement('div', { style: { fontSize: 'var(--font-size-base)' } }, 'Base Text (base)'),
React.createElement('div', { style: { fontSize: 'var(--font-size-lg)' } }, 'Large Text (lg)'),
React.createElement('div', { style: { fontSize: 'var(--font-size-xl)' } }, 'Extra Large Text (xl)')
)
);
};
const DesignTokensDemo = () => {
return React.createElement('div', null,
React.createElement('p', { style: { marginBottom: 'var(--space-4)', color: 'var(--text-secondary)' } },
'This demo uses CSS custom properties from the design tokens system.'
),
React.createElement('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 'var(--space-4)' } },
React.createElement('div', null,
React.createElement('h4', { style: { marginBottom: 'var(--space-2)', fontSize: 'var(--font-size-sm)', fontWeight: 'var(--font-weight-semibold)' } }, 'Current Values'),
React.createElement('div', { style: { fontSize: 'var(--font-size-xs)', color: 'var(--text-secondary)' } },
React.createElement('div', null, 'Primary: ', React.createElement('code', null, 'var(--primary)')),
React.createElement('div', null, 'Border Radius: ', React.createElement('code', null, 'var(--radius)')),
React.createElement('div', null, 'Shadow: ', React.createElement('code', null, 'var(--shadow)'))
)
),
React.createElement('div', null,
React.createElement('h4', { style: { marginBottom: 'var(--space-2)', fontSize: 'var(--font-size-sm)', fontWeight: 'var(--font-weight-semibold)' } }, 'Usage'),
React.createElement('div', { style: { fontSize: 'var(--font-size-xs)', color: 'var(--text-secondary)' } },
React.createElement('div', null, 'Colors: ', React.createElement('code', null, 'var(--primary-500)')),
React.createElement('div', null, 'Spacing: ', React.createElement('code', null, 'var(--space-4)')),
React.createElement('div', null, 'Typography: ', React.createElement('code', null, 'var(--font-size-lg)'))
)
)
)
);
};
// Render the app
const root = ReactDOM.createRoot(document.getElementById('react-app'));
root.render(React.createElement(App));
// Hide loading, show app
document.getElementById('loading').style.display = 'none';
document.getElementById('react-app').style.display = 'block';
</script>
<script>
function toggleTheme() {
const body = document.body;
const themeStatus = document.getElementById('theme-status');
if (body.classList.contains('dark')) {
body.classList.remove('dark');
themeStatus.textContent = 'Light';
} else {
body.classList.add('dark');
themeStatus.textContent = 'Dark';
}
}
// Initialize theme status
document.getElementById('theme-status').textContent = 'Light';
</script>
</body>
</html>