- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
10 KiB
UI Components
Component library documentation and usage examples for the design system.
🧩 Component Architecture
All components follow a consistent structure with design tokens, accessibility standards, and responsive behavior.
Base Component Pattern
<div class="component-name" data-component="name" role="[role]" aria-label="[description]">
<div class="component-name__element">
<!-- Component content -->
</div>
</div>
Component CSS Structure
/* Block */
.component-name {
/* Base styles using design tokens */
}
/* Element */
.component-name__element {
/* Element styles */
}
/* Modifier */
.component-name--variant {
/* Variant styles */
}
/* State */
.component-name.is-active {
/* State styles */
}
📋 Form Components
Buttons
Basic button implementation with variants:
<!-- Primary Button -->
<button class="btn btn--primary" type="button">
Primary Action
</button>
<!-- Secondary Button -->
<button class="btn btn--secondary" type="button">
Secondary Action
</button>
<!-- Ghost Button -->
<button class="btn btn--ghost" type="button">
Ghost Action
</button>
CSS Implementation:
.btn {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: var(--space-3) var(--space-4);
border: 1px solid transparent;
border-radius: var(--radius-md);
font-family: var(--font-family-sans);
font-size: var(--text-sm);
font-weight: var(--font-medium);
text-decoration: none;
cursor: pointer;
transition: all var(--duration-150) var(--ease-out);
&:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
.btn--primary {
background: var(--color-primary);
color: white;
&:hover:not(:disabled) {
background: var(--color-primary-600);
}
}
.btn--secondary {
background: var(--color-gray-100);
color: var(--color-gray-700);
border-color: var(--color-gray-200);
&:hover:not(:disabled) {
background: var(--color-gray-200);
}
}
.btn--ghost {
background: transparent;
color: var(--color-gray-600);
&:hover:not(:disabled) {
background: var(--color-gray-100);
}
}
Input Fields
Form input components with validation states:
<div class="form-group">
<label class="form-label" for="example-input">
Field Label
</label>
<input
class="form-input"
type="text"
id="example-input"
placeholder="Enter text..."
aria-describedby="example-help"
/>
<div class="form-help" id="example-help">
Optional help text for this field
</div>
</div>
<!-- Error State -->
<div class="form-group">
<label class="form-label" for="error-input">
Field with Error
</label>
<input
class="form-input form-input--error"
type="text"
id="error-input"
aria-invalid="true"
aria-describedby="error-message"
/>
<div class="form-error" id="error-message">
This field is required
</div>
</div>
🎭 Layout Components
Cards
Content containers with consistent styling:
<div class="card">
<div class="card__header">
<h3 class="card__title">Card Title</h3>
<div class="card__actions">
<button class="btn btn--ghost">Action</button>
</div>
</div>
<div class="card__body">
<p>Card content goes here...</p>
</div>
<div class="card__footer">
<small class="text-muted">Footer information</small>
</div>
</div>
Modals
Accessible modal dialogs:
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="modal-title">
<div class="modal__overlay" data-modal-close></div>
<div class="modal__content">
<div class="modal__header">
<h2 class="modal__title" id="modal-title">Modal Title</h2>
<button class="modal__close" data-modal-close aria-label="Close modal">
×
</button>
</div>
<div class="modal__body">
<p>Modal content...</p>
</div>
<div class="modal__footer">
<button class="btn btn--primary">Confirm</button>
<button class="btn btn--secondary" data-modal-close>Cancel</button>
</div>
</div>
</div>
📊 Data Display
Tables
Data tables with sorting and filtering:
<div class="table-container">
<table class="table">
<thead>
<tr>
<th data-sort="name" class="table__header--sortable">
Name
<span class="table__sort-indicator"></span>
</th>
<th data-sort="email" class="table__header--sortable">
Email
<span class="table__sort-indicator"></span>
</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>John Doe</td>
<td>john@example.com</td>
<td>
<div class="table__actions">
<button class="btn btn--ghost btn--sm">Edit</button>
<button class="btn btn--ghost btn--sm">Delete</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
Stats Cards
Dashboard statistics display:
<div class="stats-grid">
<div class="stat-card">
<div class="stat-card__icon">
📊
</div>
<div class="stat-card__content">
<div class="stat-card__label">Total Users</div>
<div class="stat-card__value">1,234</div>
<div class="stat-card__trend stat-card__trend--positive">
↗ +12% from last month
</div>
</div>
</div>
</div>
🔔 Feedback Components
Alerts
Status and notification messages:
<!-- Success Alert -->
<div class="alert alert--success" role="alert">
<div class="alert__icon">✅</div>
<div class="alert__content">
<div class="alert__title">Success</div>
<div class="alert__message">Operation completed successfully!</div>
</div>
<button class="alert__close" aria-label="Close alert">×</button>
</div>
<!-- Error Alert -->
<div class="alert alert--error" role="alert">
<div class="alert__icon">❌</div>
<div class="alert__content">
<div class="alert__title">Error</div>
<div class="alert__message">Something went wrong. Please try again.</div>
</div>
<button class="alert__close" aria-label="Close alert">×</button>
</div>
Loading States
Progress indicators and skeleton screens:
<!-- Spinner -->
<div class="spinner" role="status" aria-label="Loading">
<div class="spinner__circle"></div>
</div>
<!-- Progress Bar -->
<div class="progress" role="progressbar" aria-valuenow="65" aria-valuemin="0" aria-valuemax="100">
<div class="progress__bar" style="width: 65%"></div>
<div class="progress__label">65% Complete</div>
</div>
<!-- Skeleton Screen -->
<div class="skeleton">
<div class="skeleton__line skeleton__line--title"></div>
<div class="skeleton__line skeleton__line--text"></div>
<div class="skeleton__line skeleton__line--text skeleton__line--short"></div>
</div>
🎯 Interactive Components
Tabs
Content organization with tabbed interface:
<div class="tabs" role="tablist">
<button class="tabs__tab tabs__tab--active" role="tab" aria-selected="true" aria-controls="panel-1">
Tab 1
</button>
<button class="tabs__tab" role="tab" aria-selected="false" aria-controls="panel-2">
Tab 2
</button>
<button class="tabs__tab" role="tab" aria-selected="false" aria-controls="panel-3">
Tab 3
</button>
</div>
<div class="tabs__panels">
<div class="tabs__panel tabs__panel--active" role="tabpanel" id="panel-1">
Content for tab 1
</div>
<div class="tabs__panel" role="tabpanel" id="panel-2" hidden>
Content for tab 2
</div>
<div class="tabs__panel" role="tabpanel" id="panel-3" hidden>
Content for tab 3
</div>
</div>
Dropdowns
Menu and selection dropdowns:
<div class="dropdown">
<button class="dropdown__trigger" aria-haspopup="true" aria-expanded="false">
Menu
<span class="dropdown__arrow">▼</span>
</button>
<ul class="dropdown__menu" role="menu">
<li role="none">
<a class="dropdown__item" role="menuitem" href="#action1">Action 1</a>
</li>
<li role="none">
<a class="dropdown__item" role="menuitem" href="#action2">Action 2</a>
</li>
<li class="dropdown__divider" role="separator"></li>
<li role="none">
<a class="dropdown__item dropdown__item--danger" role="menuitem" href="#delete">
Delete Item
</a>
</li>
</ul>
</div>
♿ Accessibility Guidelines
ARIA Implementation
All components include proper ARIA attributes:
roleattributes for semantic meaningaria-labelfor accessible namesaria-describedbyfor help text associationsaria-expandedfor collapsible contentaria-selectedfor selectable items
Keyboard Navigation
Components support keyboard interaction:
- Tab: Navigate between focusable elements
- Enter/Space: Activate buttons and links
- Escape: Close modals and dropdowns
- Arrow Keys: Navigate within component groups
Focus Management
Proper focus indicators and management:
.component:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
/* Skip focus ring on mouse interaction */
.component:focus:not(:focus-visible) {
outline: none;
}
🎨 Theming
All components automatically adapt to theme changes through CSS custom properties:
.component {
background: var(--surface);
color: var(--text-primary);
border: 1px solid var(--border);
}
/* Dark theme automatically applied */
[data-theme="dark"] .component {
/* Inherits dark theme tokens */
}
📚 Usage Examples
JavaScript Integration
Components work with the framework's JavaScript module system:
// Auto-initialize components
document.querySelectorAll('[data-component="modal"]').forEach(element => {
new Modal(element);
});
// Event-driven interactions
events.delegate('click', '[data-action="show-alert"]', (event, element) => {
const message = element.dataset.message;
showAlert('success', message);
});
PHP Template Integration
Components integrate with the View system:
<div class="card">
<div class="card__header">
<h3 class="card__title"><?= $title ?></h3>
</div>
<div class="card__body">
<?= $content ?>
</div>
</div>
For design tokens and foundations, see Design Foundations
For CSS architecture details, see CSS Architecture
For JavaScript integration, see JavaScript Modules