whale-igniter 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,188 @@
1
+ # Surface — UI References
2
+
3
+ Surface components are containers and overlays: they frame content, present it in context, and layer it above other content. The quality of a surface shows in its edge cases — what happens when content overflows, when it's positioned near a viewport edge, or when a screen reader announces it.
4
+
5
+ ---
6
+
7
+ ## Card
8
+
9
+ A bounded content container that groups related information. Cards are surfaces, not actions: they can be clickable (linking to detail views) but clicking a card is navigation, not a form submission.
10
+
11
+ ### Reference implementations
12
+
13
+ - **[shadcn/ui Card](https://ui.shadcn.com/docs/components/card)** — `CardHeader`, `CardTitle`, `CardDescription`, `CardContent`, `CardFooter` composition pattern; clear separation of structural slots.
14
+ - **[Radix UI Card](https://www.radix-ui.com/themes/docs/components/card)** — minimal themed card with consistent shadow and radius; good baseline for a design system.
15
+ - **[Linear's cards](https://linear.app)** — observe in issues and project views: no excessive shadow, border defines the edge, hover state is a background tint (not elevation change), active selection uses a strong left border.
16
+ - **[Vercel/Geist Card](https://vercel.com/geist/components)** — flat cards with border; the standard for enterprise/dashboard contexts.
17
+
18
+ ### Minimum quality bar
19
+
20
+ - [ ] Consistent internal padding (match the project's grid unit)
21
+ - [ ] Container border-radius matches the project's `container` radius value — not the `control` radius
22
+ - [ ] If the whole card is clickable: `<a>` wrapping the card (not an `onClick` on a `<div>`)
23
+ - [ ] If part of the card is clickable (e.g. title link + action button): use `::after` pseudo-element on the title link to expand its hit area to the card; action button has its own event without conflict
24
+ - [ ] Hover state is visible; active/pressed state is visible
25
+ - [ ] Card body does not use `overflow: hidden` aggressively — truncation should be controlled and indicated
26
+
27
+ ### Common mistakes
28
+
29
+ - Wrapping an entire card in `<a>` when it also contains buttons — creates nested interactive elements and confuses screen readers
30
+ - Elevation (box-shadow) as the primary border — elevation should supplement, not replace, a visible edge
31
+ - Fixed height cards that hide overflow without indication — use truncation with ellipsis and tooltip, not silent clipping
32
+
33
+ ---
34
+
35
+ ## Popover
36
+
37
+ A floating overlay anchored to a trigger element. Used for secondary actions, rich tooltips, or inline editing. Differs from a tooltip: popovers can contain interactive elements.
38
+
39
+ ### Reference implementations
40
+
41
+ - **[Radix UI Popover](https://www.radix-ui.com/primitives/docs/components/popover)** — the reference: `role="dialog"` when interactive, focus moves into the popover on open, Escape closes and returns focus. `side`, `align`, and `avoidCollisions` handle positioning near viewport edges.
42
+ - **[shadcn/ui Popover](https://ui.shadcn.com/docs/components/popover)** — Radix Popover with Tailwind; shows the trigger + content pattern cleanly.
43
+ - **[Floating UI](https://floating-ui.com/)** — the positioning library underlying Radix, Headless UI, and others; consult for edge cases in custom positioning logic.
44
+
45
+ ### Minimum quality bar
46
+
47
+ - [ ] `role="dialog"` with `aria-label` or `aria-labelledby` when the popover contains interactive content
48
+ - [ ] Focus moves into the popover when it opens (for interactive popovers)
49
+ - [ ] Escape closes the popover; click outside closes; focus returns to trigger
50
+ - [ ] Stays within viewport: flips side and/or shifts along axis when near an edge
51
+ - [ ] Arrow indicator (optional but helpful) points to the anchor and repositions when the popover flips
52
+ - [ ] Does not scroll the page body when scrolling inside the popover
53
+
54
+ ### Common mistakes
55
+
56
+ - Non-interactive popovers that receive focus — only interactive popovers should trap/move focus
57
+ - Popover that overflows the viewport on small screens — always test positioning at mobile widths
58
+ - Opening a popover on hover without a click fallback — hover-only is inaccessible
59
+
60
+ ---
61
+
62
+ ## Tooltip
63
+
64
+ A small informational overlay that appears on hover (and focus). Tooltips explain UI elements; they do not contain interactive elements. If you need interactive content in the overlay, use a Popover.
65
+
66
+ ### Reference implementations
67
+
68
+ - **[Radix UI Tooltip](https://www.radix-ui.com/primitives/docs/components/tooltip)** — `role="tooltip"` on the content, `aria-describedby` linking the trigger to the tooltip. Delay before showing (300ms default), immediate hide on mouse leave.
69
+ - **[shadcn/ui Tooltip](https://ui.shadcn.com/docs/components/tooltip)** — clean implementation; the `TooltipProvider` wrapping pattern for shared delay configuration.
70
+ - **[Floating UI Tooltip tutorial](https://floating-ui.com/docs/tooltip)** — explains hover + focus event handling without ARIA mistakes.
71
+
72
+ ### Minimum quality bar
73
+
74
+ - [ ] `role="tooltip"` on the content element
75
+ - [ ] Trigger has `aria-describedby` pointing to the tooltip id
76
+ - [ ] Shows on hover AND on keyboard focus (not hover only)
77
+ - [ ] Delay before showing (200–300ms) prevents tooltip flicker on cursor pass-through
78
+ - [ ] Tooltip is dismissible via Escape key while visible
79
+ - [ ] Does not obscure the element being described
80
+ - [ ] Text content only — if you need a button inside, it's a Popover
81
+ - [ ] Respects `prefers-reduced-motion` for entry animation
82
+
83
+ ### Common mistakes
84
+
85
+ - Tooltip on a disabled element — disabled elements don't receive focus events; wrap the disabled element in a `<span>` for the tooltip
86
+ - Tooltip that duplicates the visible label exactly — adds no value; tooltip text should supplement, not repeat
87
+ - Interactive content (links, buttons) inside a tooltip — use Popover instead
88
+
89
+ ---
90
+
91
+ ## Sheet / Drawer
92
+
93
+ A panel that slides in from an edge of the screen (most commonly the right). Used for secondary task panels, filter drawers, detail views, or mobile navigation.
94
+
95
+ ### Reference implementations
96
+
97
+ - **[shadcn/ui Sheet](https://ui.shadcn.com/docs/components/sheet)** — four opening directions (top, right, bottom, left); `role="dialog"`, focus trap, Escape to close; uses the Radix UI Dialog primitive underneath.
98
+ - **[Radix UI Dialog as Sheet](https://www.radix-ui.com/primitives/docs/components/dialog)** — sheets are typically implemented on top of a dialog primitive with CSS positioning.
99
+ - **[Linear's right panel](https://linear.app)** — observe the issue detail panel: slides in from the right, does not cover the main content at wider viewports (side-by-side layout), full-screen on mobile.
100
+
101
+ ### Minimum quality bar
102
+
103
+ - [ ] `role="dialog"`, `aria-modal="true"`, `aria-label` or `aria-labelledby`
104
+ - [ ] Focus trap: Tab/Shift+Tab cycle inside the sheet while open
105
+ - [ ] Opens with slide animation; closes with slide animation; `prefers-reduced-motion` respects instant open/close
106
+ - [ ] Escape closes; clicking the scrim closes; close button always visible
107
+ - [ ] On mobile: always full-screen or nearly full-screen — partial drawers cause content-below-fold confusion
108
+ - [ ] Handles soft keyboard on mobile (input fields inside the sheet must be visible when keyboard opens)
109
+
110
+ ### Common mistakes
111
+
112
+ - Sheet that cannot be closed without completing a form — always allow escape/scrim close
113
+ - Sheet that scrolls the background page — lock body scroll while sheet is open
114
+ - Nested sheets — avoid; create a single sheet that can change its contents instead
115
+
116
+ ---
117
+
118
+ ## Avatar
119
+
120
+ Represents a user or entity with an image, initials, or icon. Appears in lists, comments, headers, and presence indicators.
121
+
122
+ ### Reference implementations
123
+
124
+ - **[Radix UI Avatar](https://www.radix-ui.com/primitives/docs/components/avatar)** — image with `AvatarFallback` that shows while image loads or on error. The fallback timing (delay before fallback renders) avoids flash-of-initials before the image loads.
125
+ - **[shadcn/ui Avatar](https://ui.shadcn.com/docs/components/avatar)** — clean implementation; the image + fallback pattern with consistent sizing.
126
+
127
+ ### Minimum quality bar
128
+
129
+ - [ ] Image has `alt` text describing who it represents (not `alt=""` — that's for decorative images)
130
+ - [ ] Fallback (initials or generic icon) when image fails to load or is not provided
131
+ - [ ] Fallback renders deterministically — same initials/color every time for the same user
132
+ - [ ] Consistent sizes across the product — define a size scale (sm/md/lg) and stick to it
133
+ - [ ] Avatar groups (stacked avatars): `z-index` and margin-left negative offset done with CSS, not absolute positioning
134
+
135
+ ### Common mistakes
136
+
137
+ - `alt=""` on user avatar images — these are meaningful, not decorative; describe who the image shows
138
+ - Avatar that shows a broken image icon instead of fallback — always handle image load failure
139
+ - Fallback background color that is too light against a white background — ensure sufficient contrast
140
+
141
+ ---
142
+
143
+ ## Separator / Divider
144
+
145
+ A visual line that separates groups of content. Structural, not decorative — it communicates that what's above and below belong to different groups.
146
+
147
+ ### Reference implementations
148
+
149
+ - **[Radix UI Separator](https://www.radix-ui.com/primitives/docs/components/separator)** — `role="separator"` (structural) or `role="none"` (decorative), horizontal and vertical orientation.
150
+ - **[shadcn/ui Separator](https://ui.shadcn.com/docs/components/separator)** — thin horizontal/vertical rule.
151
+
152
+ ### Minimum quality bar
153
+
154
+ - [ ] `role="separator"` when the line communicates structure (between sections); `role="none"` or `aria-hidden="true"` when purely decorative
155
+ - [ ] Color passes 3:1 contrast against its background
156
+ - [ ] Does not carry margin by default — let the container control spacing
157
+ - [ ] Horizontal separators extend to the full width of their container unless explicitly inset
158
+
159
+ ### Common mistakes
160
+
161
+ - Using `<hr>` inside inline contexts — `<hr>` has block display; use `role="separator"` on a `<span>` for inline separators
162
+ - Separator with too much vertical margin — creates too much visual space between related groups
163
+
164
+ ---
165
+
166
+ ## Badge
167
+
168
+ A small label applied to an element to communicate status, count, or category. Appears inline next to text or as an overlay on an icon.
169
+
170
+ ### Reference implementations
171
+
172
+ - **[shadcn/ui Badge](https://ui.shadcn.com/docs/components/badge)** — variant system (default, secondary, destructive, outline); small, not button-like.
173
+ - **[Radix UI Badge](https://www.radix-ui.com/themes/docs/components/badge)** — color-coded badges with good contrast defaults across themes.
174
+ - **[Linear's labels](https://linear.app)** — observe issue labels: colored dot + text, keyboard accessible in filter panels, consistent small size.
175
+ - **[GitHub Primer Label](https://primer.style/components/label/react/alpha)** — handles "filled" and "outline" variants with color theming.
176
+
177
+ ### Minimum quality bar
178
+
179
+ - [ ] Not a button — badges are not interactive; if clicking a badge does something, it should be a `<button>` or `<a>` visually styled as a badge
180
+ - [ ] Text must pass 4.5:1 contrast against its background color
181
+ - [ ] Numeric badges (notification counts): `aria-label="N notifications"` on the parent container; the badge itself is `aria-hidden`
182
+ - [ ] Never convey information through color alone — include text or icon alongside color coding
183
+ - [ ] Consistent height and padding across all badge uses in the product
184
+
185
+ ### Common mistakes
186
+
187
+ - Badge that is a `<div>` with `onClick` — should be `<button>` for interactivity or `<span>` for decoration
188
+ - Too many badge variants — three variants (default, success, danger) cover most cases; more adds cognitive load