learn and share notes on atproto (wip) 🦉
malfestio.stormlightlabs.org/
readability
solid
axum
atproto
srs
1# SolidJS UI Component Library
2
3Carbon-inspired component library for Malfestio.
4
5## Animations
6
7Presets defined in `src/lib/animations.ts`:
8
9- `fadeIn`, `fadeOut` - opacity transitions
10- `slideInRight`, `slideInUp` - directional entry
11- `scaleIn`, `scaleOut` - scale with opacity
12- `springConfig` - natural bounce settings
13- `staggerDelay(index)` - list animation helper
14
15## Components
16
17### Core
18
19| Component | File | Purpose |
20| ---------- | ------------------- | ------------------------------------------------ |
21| Dialog | `ui/Dialog.tsx` | Modal with transactional/danger/passive variants |
22| TreeView | `ui/TreeView.tsx` | Expandable hierarchy with keyboard nav |
23| DataTable | `ui/DataTable.tsx` | Sortable, selectable, expandable rows |
24| SidePanel | `ui/SidePanel.tsx` | Collapsible left navigation |
25| RightPanel | `ui/RightPanel.tsx` | Slide-in detail panel |
26| Tabs | `ui/Tabs.tsx` | Line and contained variants |
27| Dropdown | `ui/Dropdown.tsx` | Single/multi select with search |
28| Tag | `ui/Tag.tsx` | Read-only, dismissible, selectable |
29
30### Supporting
31
32| Component | File | Purpose |
33| ----------- | -------------------- | ---------------------------- |
34| Skeleton | `ui/Skeleton.tsx` | Loading placeholders |
35| EmptyState | `ui/EmptyState.tsx` | Zero-state UI |
36| Tooltip | `ui/Tooltip.tsx` | Hover info with positioning |
37| ProgressBar | `ui/ProgressBar.tsx` | Determinate/indeterminate |
38| Avatar | `ui/Avatar.tsx` | Image with initials fallback |
39| Menu | `ui/Menu.tsx` | Context/dropdown actions |
40
41### Existing
42
43| Component | File | Purpose |
44| --------- | --------------- | ------------------------------ |
45| Button | `ui/Button.tsx` | Primary/secondary/danger/ghost |
46| Card | `ui/Card.tsx` | Container with optional title |
47| Toast | `ui/Toast.tsx` | Notifications |
48
49## Keyboard Navigation
50
51- **Dialog**: `Escape` to close
52- **TreeView**: Arrow keys, `Enter`/`Space` to expand
53- **Tabs**: Left/Right arrows
54- **Dropdown**: Arrow keys, `Enter` to select, `Escape` to close
55- **Menu**: Arrow keys, `Enter` to select
56
57## Common Gotchas
58
59### Router Components in Module-Level Constants
60
61Router components (`<A>`, and hooks like `useNavigate`, `useParams`) must be created during component render, not at module initialization.
62
63**Problem:**
64
65```tsx
66// ✗ JSX created when module loads, before Router exists
67const config = {
68 action: <A href="/somewhere">Click me</A>
69}
70```
71
72**Solution:**
73
74```tsx
75// ✓ JSX created during render, inside Router context
76const getConfig = () => ({
77 action: () => <A href="/somewhere">Click me</A>
78})
79
80const MyComponent = () => {
81 const config = getConfig();
82 return <div>{config.action()}</div>
83}
84```
85
86**Why:** Module-level JSX executes immediately on import, before `<Router>` establishes its context. Router components need that context to function.
87
88**Rule:** If storing JSX that contains router components, wrap it in a function to defer creation until render time.