@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.
739 lines (703 loc) • 37 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Complex Application Test - UI Components React</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>
<style>
* { box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0;
padding: 0;
background: #f5f7fa;
color: #2d3748;
}
.app-container {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.nav-header {
background: linear-gradient(135deg, #2D1B69 0%, #11998e 100%);
color: white;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.main-content {
flex: 1;
padding: 2rem;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
max-width: 1400px;
margin: 0 auto;
width: 100%;
}
.full-width {
grid-column: 1 / -1;
}
.card {
background: white;
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 4px 20px rgba(0,0,0,0.08);
border: 1px solid #e2e8f0;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
padding-bottom: 1rem;
border-bottom: 2px solid #f7fafc;
}
.card-title {
font-size: 1.25rem;
font-weight: 600;
color: #2d3748;
margin: 0;
}
.data-table {
width: 100%;
border-collapse: collapse;
margin-top: 1rem;
}
.data-table th,
.data-table td {
text-align: left;
padding: 0.75rem;
border-bottom: 1px solid #e2e8f0;
}
.data-table th {
background: #f7fafc;
font-weight: 600;
color: #4a5568;
}
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin-bottom: 1rem;
}
.form-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.form-group.full-width {
grid-column: 1 / -1;
}
.label {
font-weight: 500;
color: #4a5568;
font-size: 0.875rem;
}
.metrics-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 2rem;
}
.metric-card {
background: white;
padding: 1.5rem;
border-radius: 8px;
border-left: 4px solid #4299e1;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
.metric-value {
font-size: 2rem;
font-weight: bold;
color: #2d3748;
margin: 0.5rem 0;
}
.metric-label {
color: #718096;
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.status-indicator {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.875rem;
font-weight: 500;
}
.status-active { background: #c6f6d5; color: #2f855a; }
.status-pending { background: #fef5e7; color: #c05621; }
.status-error { background: #fed7e2; color: #c53030; }
.chart-placeholder {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
height: 200px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: 600;
}
@media (max-width: 768px) {
.main-content {
grid-template-columns: 1fr;
padding: 1rem;
}
.form-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div id="react-app"></div>
<script type="text/babel">
const { useState, useEffect, useCallback } = React;
// Enhanced Component Library
const Button = ({ children, variant = 'primary', size = 'medium', onClick, disabled = false, loading = false, ...props }) => {
const baseStyles = {
border: 'none',
borderRadius: '6px',
cursor: disabled || loading ? 'not-allowed' : 'pointer',
fontWeight: '500',
transition: 'all 0.2s ease',
opacity: disabled ? 0.6 : 1,
fontFamily: 'inherit',
display: 'inline-flex',
alignItems: 'center',
gap: '0.5rem'
};
const variants = {
primary: { background: '#2D1B69', color: 'white' },
secondary: { background: '#11998e', color: 'white' },
danger: { background: '#dc3545', color: 'white' },
success: { background: '#28a745', color: 'white' },
warning: { background: '#ffc107', color: '#212529' },
outline: { background: 'transparent', color: '#2D1B69', border: '2px solid #2D1B69' }
};
const sizes = {
small: { padding: '6px 12px', fontSize: '14px' },
medium: { padding: '10px 20px', fontSize: '16px' },
large: { padding: '14px 28px', fontSize: '18px' }
};
const style = {
...baseStyles,
...variants[variant],
...sizes[size],
...props.style
};
return React.createElement('button', { onClick, disabled: disabled || loading, style }, [
loading && React.createElement('span', { key: 'spinner', style: { animation: 'spin 1s linear infinite' } }, '⟳'),
children
]);
};
const Input = ({ label, placeholder = 'Enter text...', type = 'text', value, onChange, disabled = false, error, ...props }) => {
const inputStyle = {
width: '100%',
padding: '10px 12px',
border: `1px solid ${error ? '#dc3545' : '#ced4da'}`,
borderRadius: '6px',
fontSize: '16px',
fontFamily: 'inherit',
transition: 'border-color 0.2s ease',
backgroundColor: disabled ? '#f8f9fa' : 'white',
cursor: disabled ? 'not-allowed' : 'text'
};
return React.createElement('div', { className: 'form-group' }, [
label && React.createElement('label', { key: 'label', className: 'label' }, label),
React.createElement('input', {
key: 'input',
type,
placeholder,
value,
onChange,
disabled,
style: inputStyle
}),
error && React.createElement('span', {
key: 'error',
style: { fontSize: '0.875rem', color: '#dc3545', marginTop: '0.25rem' }
}, error)
]);
};
const Select = ({ label, options = [], value, onChange, disabled = false, ...props }) => {
const style = {
width: '100%',
padding: '10px 12px',
border: '1px solid #ced4da',
borderRadius: '6px',
fontSize: '16px',
fontFamily: 'inherit',
backgroundColor: disabled ? '#f8f9fa' : 'white',
cursor: disabled ? 'not-allowed' : 'pointer'
};
return React.createElement('div', { className: 'form-group' }, [
label && React.createElement('label', { key: 'label', className: 'label' }, label),
React.createElement('select', {
key: 'select',
value,
onChange,
disabled,
style
}, [
React.createElement('option', { key: 'default', value: '' }, 'Select an option...'),
...options.map((option, index) =>
React.createElement('option', { key: index, value: option.value }, option.label)
)
])
]);
};
// Complex Application: Trading Dashboard
const TradingDashboard = () => {
const [portfolio, setPortfolio] = useState([
{ symbol: 'AAPL', shares: 50, price: 175.43, change: +2.34 },
{ symbol: 'GOOGL', shares: 25, price: 2847.92, change: -15.67 },
{ symbol: 'TSLA', shares: 30, price: 892.45, change: +12.88 },
{ symbol: 'MSFT', shares: 75, price: 334.11, change: +5.23 }
]);
const [watchlist, setWatchlist] = useState(['BTC', 'ETH', 'SPY', 'QQQ']);
const [activeOrders, setActiveOrders] = useState(3);
const [totalValue, setTotalValue] = useState(0);
useEffect(() => {
const total = portfolio.reduce((sum, stock) => sum + (stock.shares * stock.price), 0);
setTotalValue(total);
}, [portfolio]);
const addToWatchlist = (symbol) => {
if (symbol && !watchlist.includes(symbol)) {
setWatchlist([...watchlist, symbol]);
}
};
const removeFromWatchlist = (symbol) => {
setWatchlist(watchlist.filter(s => s !== symbol));
};
return React.createElement('div', null, [
// Metrics Row
React.createElement('div', { key: 'metrics', className: 'metrics-grid' }, [
React.createElement('div', { key: 'total', className: 'metric-card' }, [
React.createElement('div', { key: 'label', className: 'metric-label' }, 'Total Portfolio Value'),
React.createElement('div', { key: 'value', className: 'metric-value' }, `$${totalValue.toLocaleString()}`),
React.createElement('div', { key: 'change', style: { color: '#28a745', fontSize: '0.875rem' } }, '+2.4% Today')
]),
React.createElement('div', { key: 'positions', className: 'metric-card', style: { borderColor: '#28a745' } }, [
React.createElement('div', { key: 'label', className: 'metric-label' }, 'Open Positions'),
React.createElement('div', { key: 'value', className: 'metric-value' }, portfolio.length),
React.createElement('div', { key: 'change', style: { color: '#718096', fontSize: '0.875rem' } }, 'Across 4 stocks')
]),
React.createElement('div', { key: 'orders', className: 'metric-card', style: { borderColor: '#ffc107' } }, [
React.createElement('div', { key: 'label', className: 'metric-label' }, 'Active Orders'),
React.createElement('div', { key: 'value', className: 'metric-value' }, activeOrders),
React.createElement('div', { key: 'change', style: { color: '#718096', fontSize: '0.875rem' } }, 'Pending execution')
]),
React.createElement('div', { key: 'watchlist', className: 'metric-card', style: { borderColor: '#dc3545' } }, [
React.createElement('div', { key: 'label', className: 'metric-label' }, 'Watchlist Items'),
React.createElement('div', { key: 'value', className: 'metric-value' }, watchlist.length),
React.createElement('div', { key: 'change', style: { color: '#718096', fontSize: '0.875rem' } }, 'Monitored symbols')
])
]),
// Portfolio Table
React.createElement('div', { key: 'portfolio', className: 'card' }, [
React.createElement('div', { key: 'header', className: 'card-header' }, [
React.createElement('h3', { key: 'title', className: 'card-title' }, '📊 Portfolio Holdings'),
React.createElement('span', { key: 'status', className: 'status-indicator status-active' }, [
React.createElement('span', { key: 'dot', style: { width: '8px', height: '8px', borderRadius: '50%', background: 'currentColor' } }),
'Live Data'
])
]),
React.createElement('table', { key: 'table', className: 'data-table' }, [
React.createElement('thead', { key: 'head' }, [
React.createElement('tr', { key: 'row' }, [
React.createElement('th', { key: 'symbol' }, 'Symbol'),
React.createElement('th', { key: 'shares' }, 'Shares'),
React.createElement('th', { key: 'price' }, 'Price'),
React.createElement('th', { key: 'value' }, 'Value'),
React.createElement('th', { key: 'change' }, 'Change'),
React.createElement('th', { key: 'action' }, 'Action')
])
]),
React.createElement('tbody', { key: 'body' },
portfolio.map((stock, index) =>
React.createElement('tr', { key: stock.symbol }, [
React.createElement('td', { key: 'symbol' }, [
React.createElement('strong', null, stock.symbol)
]),
React.createElement('td', { key: 'shares' }, stock.shares.toLocaleString()),
React.createElement('td', { key: 'price' }, `$${stock.price.toFixed(2)}`),
React.createElement('td', { key: 'value' }, `$${(stock.shares * stock.price).toLocaleString()}`),
React.createElement('td', { key: 'change' }, [
React.createElement('span', {
style: { color: stock.change >= 0 ? '#28a745' : '#dc3545' }
}, `${stock.change >= 0 ? '+' : ''}${stock.change.toFixed(2)}`)
]),
React.createElement('td', { key: 'action' }, [
React.createElement(Button, {
key: 'trade',
size: 'small',
variant: 'outline',
onClick: () => alert(`Trading ${stock.symbol}`)
}, 'Trade')
])
])
)
)
])
]),
// Watchlist Manager
React.createElement('div', { key: 'watchlist-card', className: 'card' }, [
React.createElement('div', { key: 'header', className: 'card-header' }, [
React.createElement('h3', { key: 'title', className: 'card-title' }, '👁️ Watchlist Manager'),
React.createElement(Button, {
key: 'add',
size: 'small',
onClick: () => {
const symbol = prompt('Enter symbol to watch:');
if (symbol) addToWatchlist(symbol.toUpperCase());
}
}, '+ Add Symbol')
]),
React.createElement('div', { key: 'content', style: { display: 'flex', flexWrap: 'wrap', gap: '0.5rem' } },
watchlist.map(symbol =>
React.createElement('div', {
key: symbol,
style: {
display: 'flex',
alignItems: 'center',
gap: '0.5rem',
padding: '0.5rem 1rem',
background: '#f7fafc',
borderRadius: '20px',
border: '1px solid #e2e8f0'
}
}, [
React.createElement('span', { key: 'symbol', style: { fontWeight: '500' } }, symbol),
React.createElement('button', {
key: 'remove',
onClick: () => removeFromWatchlist(symbol),
style: {
background: 'none',
border: 'none',
color: '#dc3545',
cursor: 'pointer',
padding: '0',
fontSize: '14px'
}
}, '×')
])
)
)
])
]);
};
// Complex Application: User Management System
const UserManagementApp = () => {
const [users, setUsers] = useState([
{ id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin', status: 'Active', lastLogin: '2 hours ago' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'Manager', status: 'Active', lastLogin: '1 day ago' },
{ id: 3, name: 'Bob Johnson', email: 'bob@example.com', role: 'User', status: 'Pending', lastLogin: 'Never' },
{ id: 4, name: 'Alice Brown', email: 'alice@example.com', role: 'User', status: 'Inactive', lastLogin: '1 week ago' }
]);
const [formData, setFormData] = useState({
name: '',
email: '',
role: '',
status: 'Active'
});
const [editingUser, setEditingUser] = useState(null);
const [showForm, setShowForm] = useState(false);
const handleSubmit = (e) => {
e.preventDefault();
if (editingUser) {
setUsers(users.map(user =>
user.id === editingUser.id
? { ...user, ...formData, lastLogin: user.lastLogin }
: user
));
setEditingUser(null);
} else {
const newUser = {
id: Date.now(),
...formData,
lastLogin: 'Never'
};
setUsers([...users, newUser]);
}
setFormData({ name: '', email: '', role: '', status: 'Active' });
setShowForm(false);
};
const editUser = (user) => {
setFormData({
name: user.name,
email: user.email,
role: user.role,
status: user.status
});
setEditingUser(user);
setShowForm(true);
};
const deleteUser = (userId) => {
if (confirm('Are you sure you want to delete this user?')) {
setUsers(users.filter(user => user.id !== userId));
}
};
const roleOptions = [
{ value: 'Admin', label: 'Administrator' },
{ value: 'Manager', label: 'Manager' },
{ value: 'User', label: 'User' }
];
const statusOptions = [
{ value: 'Active', label: 'Active' },
{ value: 'Inactive', label: 'Inactive' },
{ value: 'Pending', label: 'Pending' }
];
return React.createElement('div', null, [
// User Stats
React.createElement('div', { key: 'stats', className: 'metrics-grid' }, [
React.createElement('div', { key: 'total', className: 'metric-card' }, [
React.createElement('div', { key: 'label', className: 'metric-label' }, 'Total Users'),
React.createElement('div', { key: 'value', className: 'metric-value' }, users.length),
React.createElement('div', { key: 'change', style: { color: '#718096', fontSize: '0.875rem' } }, 'Registered accounts')
]),
React.createElement('div', { key: 'active', className: 'metric-card', style: { borderColor: '#28a745' } }, [
React.createElement('div', { key: 'label', className: 'metric-label' }, 'Active Users'),
React.createElement('div', { key: 'value', className: 'metric-value' }, users.filter(u => u.status === 'Active').length),
React.createElement('div', { key: 'change', style: { color: '#28a745', fontSize: '0.875rem' } }, 'Currently online')
]),
React.createElement('div', { key: 'pending', className: 'metric-card', style: { borderColor: '#ffc107' } }, [
React.createElement('div', { key: 'label', className: 'metric-label' }, 'Pending Users'),
React.createElement('div', { key: 'value', className: 'metric-value' }, users.filter(u => u.status === 'Pending').length),
React.createElement('div', { key: 'change', style: { color: '#ffc107', fontSize: '0.875rem' } }, 'Awaiting approval')
])
]),
// User Form
showForm && React.createElement('div', { key: 'form', className: 'card' }, [
React.createElement('div', { key: 'header', className: 'card-header' }, [
React.createElement('h3', { key: 'title', className: 'card-title' },
editingUser ? '✏️ Edit User' : '👤 Add New User'),
React.createElement(Button, {
key: 'cancel',
variant: 'outline',
size: 'small',
onClick: () => {
setShowForm(false);
setEditingUser(null);
setFormData({ name: '', email: '', role: '', status: 'Active' });
}
}, 'Cancel')
]),
React.createElement('form', { key: 'form', onSubmit: handleSubmit }, [
React.createElement('div', { key: 'grid', className: 'form-grid' }, [
React.createElement(Input, {
key: 'name',
label: 'Full Name',
placeholder: 'Enter full name',
value: formData.name,
onChange: (e) => setFormData({...formData, name: e.target.value}),
required: true
}),
React.createElement(Input, {
key: 'email',
label: 'Email Address',
type: 'email',
placeholder: 'Enter email address',
value: formData.email,
onChange: (e) => setFormData({...formData, email: e.target.value}),
required: true
}),
React.createElement(Select, {
key: 'role',
label: 'Role',
options: roleOptions,
value: formData.role,
onChange: (e) => setFormData({...formData, role: e.target.value})
}),
React.createElement(Select, {
key: 'status',
label: 'Status',
options: statusOptions,
value: formData.status,
onChange: (e) => setFormData({...formData, status: e.target.value})
})
]),
React.createElement('div', { key: 'buttons', style: { display: 'flex', gap: '1rem', marginTop: '1rem' } }, [
React.createElement(Button, {
key: 'submit',
type: 'submit',
variant: 'primary'
}, editingUser ? 'Update User' : 'Create User'),
React.createElement(Button, {
key: 'reset',
type: 'button',
variant: 'outline',
onClick: () => setFormData({ name: '', email: '', role: '', status: 'Active' })
}, 'Reset Form')
])
])
]),
// Users Table
React.createElement('div', { key: 'users', className: 'card' }, [
React.createElement('div', { key: 'header', className: 'card-header' }, [
React.createElement('h3', { key: 'title', className: 'card-title' }, '👥 User Management'),
React.createElement(Button, {
key: 'add',
onClick: () => setShowForm(true)
}, '+ Add User')
]),
React.createElement('table', { key: 'table', className: 'data-table' }, [
React.createElement('thead', { key: 'head' }, [
React.createElement('tr', { key: 'row' }, [
React.createElement('th', { key: 'name' }, 'Name'),
React.createElement('th', { key: 'email' }, 'Email'),
React.createElement('th', { key: 'role' }, 'Role'),
React.createElement('th', { key: 'status' }, 'Status'),
React.createElement('th', { key: 'login' }, 'Last Login'),
React.createElement('th', { key: 'actions' }, 'Actions')
])
]),
React.createElement('tbody', { key: 'body' },
users.map(user =>
React.createElement('tr', { key: user.id }, [
React.createElement('td', { key: 'name' }, [
React.createElement('strong', null, user.name)
]),
React.createElement('td', { key: 'email' }, user.email),
React.createElement('td', { key: 'role' }, user.role),
React.createElement('td', { key: 'status' }, [
React.createElement('span', {
className: `status-indicator status-${user.status.toLowerCase()}`
}, user.status)
]),
React.createElement('td', { key: 'login' }, user.lastLogin),
React.createElement('td', { key: 'actions' }, [
React.createElement('div', { style: { display: 'flex', gap: '0.5rem' } }, [
React.createElement(Button, {
key: 'edit',
size: 'small',
variant: 'outline',
onClick: () => editUser(user)
}, 'Edit'),
React.createElement(Button, {
key: 'delete',
size: 'small',
variant: 'danger',
onClick: () => deleteUser(user.id)
}, 'Delete')
])
])
])
)
)
])
])
]);
};
// Main Application Shell
const ComplexApplicationTest = () => {
const [activeApp, setActiveApp] = useState('trading');
const [notifications, setNotifications] = useState(3);
const apps = {
trading: { name: 'Trading Dashboard', icon: '📈', component: TradingDashboard },
users: { name: 'User Management', icon: '👥', component: UserManagementApp }
};
return React.createElement('div', { className: 'app-container' }, [
// Navigation Header
React.createElement('nav', { key: 'nav', className: 'nav-header' }, [
React.createElement('div', { key: 'left', style: { display: 'flex', alignItems: 'center', gap: '2rem' } }, [
React.createElement('h1', { key: 'logo', style: { margin: 0, fontSize: '1.5rem' } }, '🚀 Tamyla Apps'),
React.createElement('div', { key: 'tabs', style: { display: 'flex', gap: '1rem' } },
Object.entries(apps).map(([key, app]) =>
React.createElement('button', {
key,
onClick: () => setActiveApp(key),
style: {
background: activeApp === key ? 'rgba(255,255,255,0.2)' : 'transparent',
border: 'none',
color: 'white',
padding: '0.5rem 1rem',
borderRadius: '6px',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
gap: '0.5rem',
fontFamily: 'inherit'
}
}, [app.icon, app.name])
)
)
]),
React.createElement('div', { key: 'right', style: { display: 'flex', alignItems: 'center', gap: '1rem' } }, [
React.createElement('div', { key: 'notifications', style: { position: 'relative' } }, [
React.createElement('button', {
key: 'bell',
style: {
background: 'rgba(255,255,255,0.2)',
border: 'none',
color: 'white',
padding: '0.5rem',
borderRadius: '50%',
cursor: 'pointer',
fontSize: '1.2rem'
}
}, '🔔'),
notifications > 0 && React.createElement('span', {
key: 'badge',
style: {
position: 'absolute',
top: '-2px',
right: '-2px',
background: '#dc3545',
color: 'white',
borderRadius: '50%',
width: '20px',
height: '20px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '12px',
fontWeight: 'bold'
}
}, notifications)
]),
React.createElement('div', { key: 'user', style: { display: 'flex', alignItems: 'center', gap: '0.5rem' } }, [
React.createElement('div', {
key: 'avatar',
style: {
width: '32px',
height: '32px',
borderRadius: '50%',
background: 'rgba(255,255,255,0.2)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontWeight: 'bold'
}
}, 'JD'),
React.createElement('span', { key: 'name' }, 'John Doe')
])
])
]),
// Main Content Area
React.createElement('main', { key: 'main', className: 'main-content' }, [
React.createElement('div', { key: 'app', className: 'full-width' },
React.createElement(apps[activeApp].component)
)
])
]);
};
// Render the complex application
ReactDOM.render(React.createElement(ComplexApplicationTest), document.getElementById('react-app'));
</script>
<style>
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
</style>
</body>
</html>