- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
471 lines
10 KiB
Markdown
471 lines
10 KiB
Markdown
# 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
|
||
|
||
```html
|
||
<div class="component-name" data-component="name" role="[role]" aria-label="[description]">
|
||
<div class="component-name__element">
|
||
<!-- Component content -->
|
||
</div>
|
||
</div>
|
||
```
|
||
|
||
### Component CSS Structure
|
||
|
||
```css
|
||
/* 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:
|
||
|
||
```html
|
||
<!-- 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:**
|
||
```css
|
||
.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:
|
||
|
||
```html
|
||
<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:
|
||
|
||
```html
|
||
<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:
|
||
|
||
```html
|
||
<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:
|
||
|
||
```html
|
||
<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:
|
||
|
||
```html
|
||
<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:
|
||
|
||
```html
|
||
<!-- 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:
|
||
|
||
```html
|
||
<!-- 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:
|
||
|
||
```html
|
||
<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:
|
||
|
||
```html
|
||
<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:
|
||
|
||
- `role` attributes for semantic meaning
|
||
- `aria-label` for accessible names
|
||
- `aria-describedby` for help text associations
|
||
- `aria-expanded` for collapsible content
|
||
- `aria-selected` for 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:
|
||
|
||
```css
|
||
.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:
|
||
|
||
```css
|
||
.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:
|
||
|
||
```javascript
|
||
// 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:
|
||
|
||
```php
|
||
<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](foundations.md)*
|
||
*For CSS architecture details, see [CSS Architecture](css-architecture.md)*
|
||
*For JavaScript integration, see [JavaScript Modules](javascript.md)* |