Components and dialogs
Reuse the components that already carry the shared style and behavior.
Core components
| Component | Source | Props |
|---|---|---|
| Card | src/components/Card.tsx | title, subtitle, action, children, className |
| PageHeader | src/components/PageHeader.tsx | title, description, action |
| Modal | src/components/Modal.tsx | title, open, onClose, children, size |
| AsyncState | src/components/AsyncState.tsx | state, title, description, onRetry |
| ResourceTable | features/business/ResourceTable.tsx | rows, columns, label, onArchive, actions |
React dialog example
import { useState } from 'react';
import { Modal } from '../components/Modal';
export default function ExampleDialog() {
const [open, setOpen] = useState(false);
return <>
<button onClick={() => setOpen(true)}>Open details</button>
<Modal title="Project details" open={open} onClose={() => setOpen(false)}>
<p>Your details go here.</p>
<button onClick={() => setOpen(false)}>Done</button>
</Modal>
</>;
}Modal uses the native dialog element. Optional sizes: sm, lg, fullscreen and drawer. Preserve labelled fields, dismissal and focus behavior.
Loading, failure, and empty states
Route loading keeps the application shell and displays a content skeleton. Saves disable the submit action while pending. Workspace settings → Simulate network failure makes saves fail without committing data. The error offers Restore demo connection; the original form values remain available for resubmission. A failed save is not automatically retried because production mutations may have side effects.
Search and filters display helpful empty states. Missing customer IDs show a recovery link. Storage corruption falls back to seed data; unavailable storage keeps an in-memory session and displays a persistence warning after a save.