@annondeveloper/ui-kit 0.2.0 → 0.2.1
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.
- package/README.md +1463 -127
- package/dist/form.js +1 -2
- package/dist/form.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +123 -65
- package/dist/index.js.map +1 -1
- package/package.json +24 -26
- package/src/components/animated-counter.tsx +6 -4
- package/src/components/color-input.tsx +27 -14
- package/src/components/command-bar.tsx +2 -1
- package/src/components/copy-block.tsx +7 -12
- package/src/components/data-table.tsx +7 -12
- package/src/components/diff-viewer.tsx +21 -0
- package/src/components/heatmap-calendar.tsx +6 -1
- package/src/components/infinite-scroll.tsx +8 -3
- package/src/components/live-feed.tsx +2 -0
- package/src/components/log-viewer.tsx +2 -0
- package/src/components/notification-stack.tsx +8 -1
- package/src/components/sortable-list.tsx +17 -13
- package/src/components/step-wizard.tsx +9 -1
- package/src/components/streaming-text.tsx +6 -9
- package/src/theme.css +6 -0
package/README.md
CHANGED
|
@@ -1,215 +1,1551 @@
|
|
|
1
1
|
# @annondeveloper/ui-kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> The React component library for monitoring dashboards, infrastructure tools, and professional applications.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
53 components • Dark/Light theme • Accessible • AI-ready • Real-time primitives • Tree-shakeable
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
-
|
|
7
|
+
[](https://www.npmjs.com/package/@annondeveloper/ui-kit)
|
|
8
|
+
|
|
9
|
+
[GitHub](https://github.com/annondeveloper/ui-kit)
|
|
10
|
+
•
|
|
11
|
+
[JSR](https://jsr.io/@annondeveloper/ui-kit)
|
|
12
|
+
•
|
|
13
|
+
[Demo](https://annondeveloper.github.io/ui-kit)
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
### Install
|
|
16
20
|
|
|
17
21
|
```bash
|
|
22
|
+
# npm
|
|
18
23
|
npm install @annondeveloper/ui-kit
|
|
24
|
+
|
|
25
|
+
# pnpm
|
|
26
|
+
pnpm add @annondeveloper/ui-kit
|
|
27
|
+
|
|
28
|
+
# yarn
|
|
29
|
+
yarn add @annondeveloper/ui-kit
|
|
30
|
+
|
|
31
|
+
# bun
|
|
32
|
+
bun add @annondeveloper/ui-kit
|
|
33
|
+
|
|
34
|
+
# jsr
|
|
35
|
+
npx jsr add @annondeveloper/ui-kit
|
|
19
36
|
```
|
|
20
37
|
|
|
21
38
|
### Peer Dependencies
|
|
22
39
|
|
|
23
40
|
```bash
|
|
24
41
|
npm install react react-dom framer-motion lucide-react clsx tailwind-merge sonner \
|
|
25
|
-
@radix-ui/react-select @radix-ui/react-alert-dialog @radix-ui/react-tooltip
|
|
42
|
+
@radix-ui/react-select @radix-ui/react-alert-dialog @radix-ui/react-tooltip \
|
|
43
|
+
@radix-ui/react-popover @radix-ui/react-dropdown-menu
|
|
26
44
|
```
|
|
27
45
|
|
|
28
|
-
|
|
46
|
+
`react-hook-form` is an optional peer dependency -- only needed if you use the `@annondeveloper/ui-kit/form` entry point.
|
|
29
47
|
|
|
30
|
-
###
|
|
48
|
+
### Theme Setup
|
|
49
|
+
|
|
50
|
+
Import the theme CSS once in your app's root layout:
|
|
31
51
|
|
|
32
52
|
```tsx
|
|
33
|
-
|
|
34
|
-
import '@annondeveloper/ui-kit/src/theme.css'
|
|
53
|
+
import '@annondeveloper/ui-kit/theme.css'
|
|
35
54
|
```
|
|
36
55
|
|
|
37
|
-
Or copy the CSS custom properties into your own
|
|
56
|
+
Or copy the CSS custom properties into your own stylesheet. See [Theme System](#theme-system) below.
|
|
38
57
|
|
|
39
|
-
###
|
|
58
|
+
### Minimal Example
|
|
40
59
|
|
|
41
60
|
```tsx
|
|
42
|
-
import { Button,
|
|
61
|
+
import { Button, MetricCard, StatusBadge, Toaster } from '@annondeveloper/ui-kit'
|
|
62
|
+
import { Activity } from 'lucide-react'
|
|
43
63
|
|
|
44
64
|
function App() {
|
|
45
65
|
return (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
66
|
+
<>
|
|
67
|
+
<MetricCard label="CPU Usage" value={72.4} format={n => `${n.toFixed(1)}%`} icon={Activity} status="warning" />
|
|
68
|
+
<StatusBadge status="active" pulse />
|
|
69
|
+
<Button variant="primary" loading={isPending}>Deploy</Button>
|
|
70
|
+
<Toaster />
|
|
71
|
+
</>
|
|
49
72
|
)
|
|
50
73
|
}
|
|
51
74
|
```
|
|
52
75
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
### Layout & Feedback
|
|
76
|
+
---
|
|
56
77
|
|
|
57
|
-
|
|
58
|
-
|-----------|-------------|
|
|
59
|
-
| `Button` | 5 variants (primary/secondary/danger/outline/ghost), 4 sizes, loading state |
|
|
60
|
-
| `Badge` | Color-coded label with 10 color presets |
|
|
61
|
-
| `EmptyState` | Placeholder with icon, title, description, optional actions |
|
|
62
|
-
| `Skeleton` / `SkeletonText` / `SkeletonCard` | Loading placeholders with shimmer animation |
|
|
63
|
-
| `SuccessCheckmark` | Animated SVG checkmark for success states |
|
|
64
|
-
| `StatusBadge` | Configurable status indicator (accepts custom status map) |
|
|
65
|
-
| `StatusPulse` | Animated status dot with configurable pulse behavior |
|
|
78
|
+
## Why This Library?
|
|
66
79
|
|
|
67
|
-
|
|
80
|
+
Most component libraries are built for CRUD apps. This one is built for **ops dashboards, infrastructure tools, and AI-powered interfaces** -- where data density, real-time updates, and status visualization are first-class concerns.
|
|
68
81
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
| `FilterPill` | Rounded filter toggle pill with optional count |
|
|
82
|
+
- **Smart Components** -- SmartTable auto-generates filter suggestions (outliers, top-N, patterns). CommandBar provides fuzzy search with recent history.
|
|
83
|
+
- **AI-Ready** -- StreamingText renders LLM output with a blinking cursor. TypingIndicator, ConfidenceBar, and copy-on-complete are built in.
|
|
84
|
+
- **Real-Time** -- RealtimeValue tracks data freshness with connection state indicators and stale-data dimming. LiveFeed auto-scrolls with pause controls. NotificationStack supports auto-dismiss with progress bars.
|
|
85
|
+
- **Monitoring** -- MetricCard with trend arrows and sparklines. ThresholdGauge with color-coded zones. UtilizationBar, UptimeTracker, PortStatusGrid, and PipelineStage for infrastructure dashboards.
|
|
86
|
+
- **Data-Dense** -- DataTable with 10+ features in one import (search, column filters, sort, pagination, density control, column picker, CSV export, row animations). HeatmapCalendar, SeverityTimeline, LogViewer for high-density displays.
|
|
87
|
+
- **Developer Experience** -- CLI for scaffolding (`npx @annondeveloper/ui-kit add button`). react-hook-form adapters. Zero config theming. Full TypeScript coverage with exported types.
|
|
76
88
|
|
|
77
|
-
|
|
89
|
+
---
|
|
78
90
|
|
|
79
|
-
|
|
80
|
-
|-----------|-------------|
|
|
81
|
-
| `DataTable` | Full-featured table — sort, filter, search, paginate, density, column picker, CSV export |
|
|
82
|
-
| `AnimatedCounter` | Smooth number animation with rAF easing |
|
|
83
|
-
| `TruncatedText` | Auto-truncation with Radix tooltip + copy-to-clipboard |
|
|
91
|
+
## Component Reference
|
|
84
92
|
|
|
85
|
-
###
|
|
93
|
+
### Core
|
|
86
94
|
|
|
87
|
-
|
|
88
|
-
|-----------|-------------|
|
|
89
|
-
| `ConfirmDialog` | Radix AlertDialog with Framer Motion animations, danger variant |
|
|
90
|
-
| `Toaster` / `toast` | Sonner wrapper with theme-aware styling |
|
|
95
|
+
#### Button
|
|
91
96
|
|
|
92
|
-
|
|
97
|
+
A themed button with variant, size, and loading support.
|
|
93
98
|
|
|
94
99
|
```tsx
|
|
95
|
-
import {
|
|
100
|
+
import { Button } from '@annondeveloper/ui-kit'
|
|
96
101
|
|
|
97
|
-
|
|
98
|
-
cn('px-4 py-2', isActive && 'bg-blue-500', className)
|
|
99
|
-
|
|
100
|
-
// Formatters
|
|
101
|
-
fmtBytes(1073741824) // "1.0 GB"
|
|
102
|
-
fmtRelative('2024-01-01') // "3 months ago"
|
|
103
|
-
fmtBps(1000000000) // "1.0 Gbps"
|
|
104
|
-
fmtPct(0.956) // "95.6%"
|
|
102
|
+
<Button variant="primary" size="md" loading={isPending}>Save</Button>
|
|
105
103
|
```
|
|
106
104
|
|
|
107
|
-
|
|
105
|
+
| Prop | Type | Default | Description |
|
|
106
|
+
|------|------|---------|-------------|
|
|
107
|
+
| `variant` | `'primary' \| 'secondary' \| 'danger' \| 'outline' \| 'ghost'` | `'primary'` | Visual variant |
|
|
108
|
+
| `size` | `'sm' \| 'md' \| 'lg' \| 'icon'` | `'md'` | Size preset |
|
|
109
|
+
| `loading` | `boolean` | `false` | Show spinner and disable interaction |
|
|
108
110
|
|
|
109
|
-
|
|
111
|
+
Extends all native `<button>` attributes. Supports `ref` forwarding.
|
|
110
112
|
|
|
111
|
-
|
|
112
|
-
/* Dark mode (default) */
|
|
113
|
-
:root {
|
|
114
|
-
--bg-base: 220 15% 8%;
|
|
115
|
-
--bg-surface: 220 14% 11%;
|
|
116
|
-
--text-primary: 220 10% 93%;
|
|
117
|
-
--brand-primary: 217 91% 60%;
|
|
118
|
-
--status-ok: 142 71% 45%;
|
|
119
|
-
--status-critical: 0 84% 60%;
|
|
120
|
-
}
|
|
113
|
+
---
|
|
121
114
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
115
|
+
#### Badge
|
|
116
|
+
|
|
117
|
+
A pill-shaped label with 10 color presets and optional icon.
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
import { Badge, createBadgeVariant } from '@annondeveloper/ui-kit'
|
|
121
|
+
import { Shield } from 'lucide-react'
|
|
122
|
+
|
|
123
|
+
<Badge color="green" icon={Shield} size="sm">Secure</Badge>
|
|
128
124
|
```
|
|
129
125
|
|
|
130
|
-
|
|
126
|
+
| Prop | Type | Default | Description |
|
|
127
|
+
|------|------|---------|-------------|
|
|
128
|
+
| `children` | `ReactNode` | -- | Badge content |
|
|
129
|
+
| `color` | `'brand' \| 'blue' \| 'green' \| 'yellow' \| 'red' \| 'orange' \| 'purple' \| 'pink' \| 'teal' \| 'gray'` | `'gray'` | Color preset |
|
|
130
|
+
| `icon` | `LucideIcon` | -- | Optional icon before the label |
|
|
131
|
+
| `size` | `'xs' \| 'sm' \| 'md'` | `'sm'` | Size variant |
|
|
131
132
|
|
|
132
|
-
|
|
133
|
+
##### Badge Factory
|
|
133
134
|
|
|
134
|
-
Create domain-specific badge
|
|
135
|
+
Create domain-specific badge components without modifying the library:
|
|
135
136
|
|
|
136
137
|
```tsx
|
|
137
|
-
import { createBadgeVariant } from '@annondeveloper/ui-kit'
|
|
138
|
-
|
|
139
138
|
const SeverityBadge = createBadgeVariant({
|
|
140
139
|
colorMap: { critical: 'red', warning: 'yellow', info: 'blue' },
|
|
141
140
|
labelMap: { critical: 'Critical', warning: 'Warning', info: 'Info' },
|
|
142
141
|
})
|
|
143
142
|
|
|
144
|
-
|
|
143
|
+
<SeverityBadge value="critical" />
|
|
145
144
|
```
|
|
146
145
|
|
|
147
|
-
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
#### Card
|
|
149
|
+
|
|
150
|
+
A styled card container with subcomponents for semantic structure.
|
|
148
151
|
|
|
149
152
|
```tsx
|
|
150
|
-
import {
|
|
153
|
+
import { Card, CardHeader, CardTitle, CardContent } from '@annondeveloper/ui-kit'
|
|
154
|
+
|
|
155
|
+
<Card variant="interactive" padding="lg">
|
|
156
|
+
<CardHeader><CardTitle>Server Health</CardTitle></CardHeader>
|
|
157
|
+
<CardContent>...</CardContent>
|
|
158
|
+
</Card>
|
|
159
|
+
```
|
|
151
160
|
|
|
152
|
-
|
|
153
|
-
|
|
161
|
+
| Prop | Type | Default | Description |
|
|
162
|
+
|------|------|---------|-------------|
|
|
163
|
+
| `variant` | `'default' \| 'elevated' \| 'outlined' \| 'interactive'` | `'default'` | Visual variant (`interactive` adds hover effect) |
|
|
164
|
+
| `padding` | `'none' \| 'sm' \| 'md' \| 'lg'` | `'md'` | Padding preset |
|
|
154
165
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
166
|
+
Subcomponents: `CardHeader`, `CardTitle`, `CardDescription`, `CardContent`, `CardFooter`. All support `ref` forwarding.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
#### Tabs
|
|
171
|
+
|
|
172
|
+
Accessible tabbed interface with three visual variants and animated indicator.
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
import { Tabs } from '@annondeveloper/ui-kit'
|
|
176
|
+
|
|
177
|
+
<Tabs tabs={[{ value: 'metrics', label: 'Metrics' }, { value: 'logs', label: 'Logs' }]}
|
|
178
|
+
value={tab} onChange={setTab} variant="pills" />
|
|
161
179
|
```
|
|
162
180
|
|
|
163
|
-
|
|
181
|
+
| Prop | Type | Default | Description |
|
|
182
|
+
|------|------|---------|-------------|
|
|
183
|
+
| `tabs` | `Tab[]` | -- | Array of `{ value, label, icon?, disabled? }` |
|
|
184
|
+
| `value` | `string` | -- | Currently selected tab value |
|
|
185
|
+
| `onChange` | `(value: string) => void` | -- | Selection callback |
|
|
186
|
+
| `variant` | `'underline' \| 'pills' \| 'enclosed'` | `'underline'` | Visual variant |
|
|
187
|
+
| `size` | `'sm' \| 'md'` | `'md'` | Size preset |
|
|
164
188
|
|
|
165
|
-
|
|
189
|
+
Supports keyboard navigation (arrow keys, Home, End) and ARIA roles. Animated indicator uses Framer Motion `layoutId`.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
#### Sheet
|
|
194
|
+
|
|
195
|
+
A slide-over drawer panel from any screen edge.
|
|
166
196
|
|
|
167
197
|
```tsx
|
|
168
|
-
import {
|
|
169
|
-
|
|
198
|
+
import { Sheet } from '@annondeveloper/ui-kit'
|
|
199
|
+
|
|
200
|
+
<Sheet open={isOpen} onClose={() => setOpen(false)} title="Settings" side="right" width="max-w-lg">
|
|
201
|
+
{children}
|
|
202
|
+
</Sheet>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
| Prop | Type | Default | Description |
|
|
206
|
+
|------|------|---------|-------------|
|
|
207
|
+
| `open` | `boolean` | -- | Whether the sheet is open |
|
|
208
|
+
| `onClose` | `() => void` | -- | Close callback |
|
|
209
|
+
| `side` | `'right' \| 'left' \| 'top' \| 'bottom'` | `'right'` | Slide-in edge |
|
|
210
|
+
| `title` | `string` | -- | Header title |
|
|
211
|
+
| `description` | `string` | -- | Header description |
|
|
212
|
+
| `width` | `string` | `'max-w-md'` | Width/height class |
|
|
213
|
+
|
|
214
|
+
Features: backdrop blur, spring animation, Escape to close, body scroll lock, auto-focus.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
#### Tooltip
|
|
219
|
+
|
|
220
|
+
Simple tooltip wrapper built on Radix UI with theme-styled content and arrow pointer.
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
import { Tooltip } from '@annondeveloper/ui-kit'
|
|
224
|
+
|
|
225
|
+
<Tooltip content="Copy to clipboard" side="top"><button>...</button></Tooltip>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
| Prop | Type | Default | Description |
|
|
229
|
+
|------|------|---------|-------------|
|
|
230
|
+
| `content` | `ReactNode` | -- | Tooltip content |
|
|
231
|
+
| `children` | `ReactNode` | -- | Trigger element |
|
|
232
|
+
| `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | `'top'` | Display side |
|
|
233
|
+
| `delay` | `number` | `200` | Delay in ms |
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
#### Popover
|
|
238
|
+
|
|
239
|
+
Popover wrapper built on Radix Popover with Framer Motion entry animation.
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
import { Popover } from '@annondeveloper/ui-kit'
|
|
243
|
+
|
|
244
|
+
<Popover trigger={<button>Options</button>} side="bottom" align="end">
|
|
245
|
+
<p>Popover content</p>
|
|
246
|
+
</Popover>
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
| Prop | Type | Default | Description |
|
|
250
|
+
|------|------|---------|-------------|
|
|
251
|
+
| `trigger` | `ReactNode` | -- | Element that opens the popover |
|
|
252
|
+
| `children` | `ReactNode` | -- | Popover content |
|
|
253
|
+
| `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | `'bottom'` | Display side |
|
|
254
|
+
| `align` | `'start' \| 'center' \| 'end'` | `'center'` | Alignment |
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
#### DropdownMenu
|
|
259
|
+
|
|
260
|
+
Action/context dropdown menu built on Radix DropdownMenu with danger variant support.
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
import { DropdownMenu } from '@annondeveloper/ui-kit'
|
|
264
|
+
import { Edit, Trash2 } from 'lucide-react'
|
|
265
|
+
|
|
266
|
+
<DropdownMenu
|
|
267
|
+
trigger={<button>Actions</button>}
|
|
268
|
+
items={[
|
|
269
|
+
{ label: 'Edit', icon: Edit, onClick: handleEdit },
|
|
270
|
+
{ label: 'Delete', icon: Trash2, onClick: handleDelete, variant: 'danger' },
|
|
271
|
+
]}
|
|
272
|
+
/>
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
| Prop | Type | Default | Description |
|
|
276
|
+
|------|------|---------|-------------|
|
|
277
|
+
| `trigger` | `ReactNode` | -- | Element that opens the menu |
|
|
278
|
+
| `items` | `MenuItem[]` | -- | `{ label, icon?, onClick, variant?, disabled? }` |
|
|
279
|
+
| `align` | `'start' \| 'center' \| 'end'` | `'end'` | Menu alignment |
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
#### ConfirmDialog
|
|
284
|
+
|
|
285
|
+
Confirmation modal built on Radix AlertDialog with animated enter/exit.
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
import { ConfirmDialog } from '@annondeveloper/ui-kit'
|
|
289
|
+
|
|
290
|
+
<ConfirmDialog
|
|
291
|
+
open={showDelete} onOpenChange={setShowDelete}
|
|
292
|
+
title="Delete server?" description="This action cannot be undone."
|
|
293
|
+
variant="danger" confirmLabel="Delete" loading={isDeleting}
|
|
294
|
+
onConfirm={handleDelete}
|
|
295
|
+
/>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
| Prop | Type | Default | Description |
|
|
299
|
+
|------|------|---------|-------------|
|
|
300
|
+
| `open` | `boolean` | -- | Control open state |
|
|
301
|
+
| `onOpenChange` | `(open: boolean) => void` | -- | Open state callback |
|
|
302
|
+
| `title` | `string` | -- | Dialog title |
|
|
303
|
+
| `description` | `string` | -- | Dialog description |
|
|
304
|
+
| `confirmLabel` | `string` | `'Confirm'` | Confirm button text |
|
|
305
|
+
| `cancelLabel` | `string` | `'Cancel'` | Cancel button text |
|
|
306
|
+
| `variant` | `'danger' \| 'warning' \| 'default'` | `'danger'` | Icon and button color |
|
|
307
|
+
| `loading` | `boolean` | `false` | Show spinner on confirm button |
|
|
308
|
+
| `onConfirm` | `() => void` | -- | Confirm callback |
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
### Forms
|
|
313
|
+
|
|
314
|
+
#### FormInput
|
|
315
|
+
|
|
316
|
+
Themed form input with label, required indicator, and optional hint text.
|
|
317
|
+
|
|
318
|
+
```tsx
|
|
319
|
+
import { FormInput } from '@annondeveloper/ui-kit'
|
|
320
|
+
|
|
321
|
+
<FormInput label="Hostname" value={host} onChange={setHost} placeholder="10.0.0.1" required hint="IPv4 or FQDN" />
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
| Prop | Type | Default | Description |
|
|
325
|
+
|------|------|---------|-------------|
|
|
326
|
+
| `label` | `string` | -- | Label text |
|
|
327
|
+
| `value` | `string` | -- | Input value |
|
|
328
|
+
| `onChange` | `(value: string) => void` | -- | Value change callback |
|
|
329
|
+
| `type` | `string` | `'text'` | HTML input type |
|
|
330
|
+
| `placeholder` | `string` | -- | Placeholder text |
|
|
331
|
+
| `required` | `boolean` | -- | Show required indicator |
|
|
332
|
+
| `disabled` | `boolean` | -- | Disable input |
|
|
333
|
+
| `hint` | `string` | -- | Help text below input |
|
|
334
|
+
| `autoComplete` | `string` | -- | Autocomplete attribute |
|
|
335
|
+
|
|
336
|
+
Also exports `INPUT_CLS`, `LABEL_CLS`, and `TEXTAREA_CLS` constants for building custom inputs with consistent styling.
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
#### Select
|
|
341
|
+
|
|
342
|
+
Themed dropdown built on Radix UI Select.
|
|
343
|
+
|
|
344
|
+
```tsx
|
|
345
|
+
import { Select } from '@annondeveloper/ui-kit'
|
|
346
|
+
|
|
347
|
+
<Select value={protocol} onValueChange={setProtocol}
|
|
348
|
+
options={[{ value: 'snmp', label: 'SNMP' }, { value: 'ssh', label: 'SSH' }]}
|
|
349
|
+
placeholder="Select protocol" />
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
| Prop | Type | Default | Description |
|
|
353
|
+
|------|------|---------|-------------|
|
|
354
|
+
| `value` | `string` | -- | Selected value |
|
|
355
|
+
| `onValueChange` | `(v: string) => void` | -- | Selection callback |
|
|
356
|
+
| `options` | `SelectOption[]` | -- | `{ value, label }` |
|
|
357
|
+
| `placeholder` | `string` | -- | Placeholder text |
|
|
358
|
+
| `disabled` | `boolean` | -- | Disable select |
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
#### Checkbox
|
|
363
|
+
|
|
364
|
+
Themed checkbox with indeterminate state support. Forwards ref.
|
|
365
|
+
|
|
366
|
+
```tsx
|
|
367
|
+
import { Checkbox } from '@annondeveloper/ui-kit'
|
|
368
|
+
|
|
369
|
+
<Checkbox checked={selected} onChange={handleChange} indeterminate={isPartial} size="sm" />
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
| Prop | Type | Default | Description |
|
|
373
|
+
|------|------|---------|-------------|
|
|
374
|
+
| `indeterminate` | `boolean` | -- | Show minus indicator |
|
|
375
|
+
| `size` | `'sm' \| 'md'` | `'md'` | Size variant |
|
|
376
|
+
|
|
377
|
+
Extends native `<input>` attributes (except `type` and `size`).
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
#### ToggleSwitch
|
|
382
|
+
|
|
383
|
+
Icon-based boolean toggle using lucide icons.
|
|
384
|
+
|
|
385
|
+
```tsx
|
|
386
|
+
import { ToggleSwitch } from '@annondeveloper/ui-kit'
|
|
387
|
+
|
|
388
|
+
<ToggleSwitch enabled={isActive} onChange={setIsActive} label="Auto-refresh" />
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
| Prop | Type | Default | Description |
|
|
392
|
+
|------|------|---------|-------------|
|
|
393
|
+
| `enabled` | `boolean` | -- | Toggle state |
|
|
394
|
+
| `onChange` | `(enabled: boolean) => void` | -- | Change callback |
|
|
395
|
+
| `size` | `'sm' \| 'md'` | `'md'` | Size variant |
|
|
396
|
+
| `disabled` | `boolean` | -- | Disable toggle |
|
|
397
|
+
| `label` | `string` | -- | Accessible label |
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
#### RadioGroup
|
|
402
|
+
|
|
403
|
+
Custom-styled radio button group with animated selection indicator.
|
|
404
|
+
|
|
405
|
+
```tsx
|
|
406
|
+
import { RadioGroup } from '@annondeveloper/ui-kit'
|
|
407
|
+
|
|
408
|
+
<RadioGroup
|
|
409
|
+
options={[
|
|
410
|
+
{ value: 'v2c', label: 'SNMPv2c' },
|
|
411
|
+
{ value: 'v3', label: 'SNMPv3', description: 'Recommended for production' },
|
|
412
|
+
]}
|
|
413
|
+
value={version} onChange={setVersion} orientation="vertical"
|
|
414
|
+
/>
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
| Prop | Type | Default | Description |
|
|
418
|
+
|------|------|---------|-------------|
|
|
419
|
+
| `options` | `RadioOption[]` | -- | `{ value, label, description?, disabled? }` |
|
|
420
|
+
| `value` | `string` | -- | Selected value |
|
|
421
|
+
| `onChange` | `(value: string) => void` | -- | Selection callback |
|
|
422
|
+
| `orientation` | `'horizontal' \| 'vertical'` | `'vertical'` | Layout direction |
|
|
423
|
+
|
|
424
|
+
Supports keyboard navigation (arrow keys, Home, End) and ARIA roles.
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
#### Slider
|
|
429
|
+
|
|
430
|
+
Custom range slider with keyboard accessibility and hover tooltip.
|
|
431
|
+
|
|
432
|
+
```tsx
|
|
433
|
+
import { Slider } from '@annondeveloper/ui-kit'
|
|
434
|
+
|
|
435
|
+
<Slider value={threshold} onChange={setThreshold} min={0} max={100} step={5} label="Alert threshold" showValue />
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
| Prop | Type | Default | Description |
|
|
439
|
+
|------|------|---------|-------------|
|
|
440
|
+
| `value` | `number` | -- | Current value |
|
|
441
|
+
| `onChange` | `(value: number) => void` | -- | Change callback |
|
|
442
|
+
| `min` | `number` | `0` | Minimum value |
|
|
443
|
+
| `max` | `number` | `100` | Maximum value |
|
|
444
|
+
| `step` | `number` | `1` | Step increment |
|
|
445
|
+
| `label` | `string` | -- | Label text |
|
|
446
|
+
| `showValue` | `boolean` | `false` | Show value display |
|
|
447
|
+
|
|
448
|
+
Supports keyboard (arrow keys, Home, End), mouse drag, and touch.
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
#### ColorInput
|
|
453
|
+
|
|
454
|
+
Compact color picker with expandable panel, hue/saturation area, format switching, and presets.
|
|
455
|
+
|
|
456
|
+
```tsx
|
|
457
|
+
import { ColorInput } from '@annondeveloper/ui-kit'
|
|
458
|
+
|
|
459
|
+
<ColorInput value={color} onChange={setColor} label="Accent" format="hex"
|
|
460
|
+
presets={['#3b82f6', '#10b981', '#f59e0b', '#ef4444']} />
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
| Prop | Type | Default | Description |
|
|
464
|
+
|------|------|---------|-------------|
|
|
465
|
+
| `value` | `string` | -- | Hex color string |
|
|
466
|
+
| `onChange` | `(color: string) => void` | -- | Change callback |
|
|
467
|
+
| `label` | `string` | -- | Optional label |
|
|
468
|
+
| `presets` | `string[]` | -- | Preset color swatches |
|
|
469
|
+
| `showAlpha` | `boolean` | `false` | Show alpha slider |
|
|
470
|
+
| `format` | `'hex' \| 'rgb' \| 'hsl'` | `'hex'` | Display format |
|
|
471
|
+
|
|
472
|
+
Features: HSL picker area, hue slider, format switching, clipboard copy, recent color history (localStorage).
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
#### StepWizard
|
|
477
|
+
|
|
478
|
+
Multi-step form wizard with animated slide transitions and per-step validation.
|
|
479
|
+
|
|
480
|
+
```tsx
|
|
481
|
+
import { StepWizard } from '@annondeveloper/ui-kit'
|
|
482
|
+
|
|
483
|
+
<StepWizard
|
|
484
|
+
steps={[
|
|
485
|
+
{ id: 'creds', title: 'Credentials', content: <CredentialsForm /> },
|
|
486
|
+
{ id: 'targets', title: 'Targets', content: <TargetForm />, validate: () => targets.length > 0 },
|
|
487
|
+
{ id: 'review', title: 'Review', content: <ReviewSummary /> },
|
|
488
|
+
]}
|
|
489
|
+
onComplete={handleDeploy} showSummary
|
|
490
|
+
/>
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
| Prop | Type | Default | Description |
|
|
494
|
+
|------|------|---------|-------------|
|
|
495
|
+
| `steps` | `WizardStep[]` | -- | `{ id, title, description?, icon?, content, validate? }` |
|
|
496
|
+
| `onComplete` | `() => void` | -- | Final step completion callback |
|
|
497
|
+
| `onStepChange` | `(step: number) => void` | -- | Step change callback |
|
|
498
|
+
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Step indicator layout |
|
|
499
|
+
| `allowSkip` | `boolean` | `false` | Allow skipping to uncompleted steps |
|
|
500
|
+
| `showSummary` | `boolean` | `false` | Show completion state after last step |
|
|
501
|
+
|
|
502
|
+
Features: animated step transitions, progress bar, keyboard navigation (Enter to advance), session storage auto-save, async validation.
|
|
503
|
+
|
|
504
|
+
---
|
|
505
|
+
|
|
506
|
+
#### FilterPill
|
|
507
|
+
|
|
508
|
+
Rounded pill-style filter toggle with optional count.
|
|
509
|
+
|
|
510
|
+
```tsx
|
|
511
|
+
import { FilterPill } from '@annondeveloper/ui-kit'
|
|
512
|
+
|
|
513
|
+
<FilterPill label="Critical" count={12} active={filter === 'critical'} onClick={() => setFilter('critical')} />
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
| Prop | Type | Default | Description |
|
|
517
|
+
|------|------|---------|-------------|
|
|
518
|
+
| `label` | `string` | -- | Pill text |
|
|
519
|
+
| `count` | `number` | -- | Optional count badge |
|
|
520
|
+
| `active` | `boolean` | -- | Active/selected state |
|
|
521
|
+
| `onClick` | `() => void` | -- | Click handler |
|
|
170
522
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
523
|
+
---
|
|
524
|
+
|
|
525
|
+
### Data Display
|
|
526
|
+
|
|
527
|
+
#### DataTable
|
|
528
|
+
|
|
529
|
+
Full-featured data grid built on TanStack Table v8.
|
|
530
|
+
|
|
531
|
+
```tsx
|
|
532
|
+
import { DataTable } from '@annondeveloper/ui-kit'
|
|
176
533
|
|
|
177
534
|
<DataTable
|
|
178
|
-
columns={columns}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
exportFilename="users"
|
|
184
|
-
onRowClick={(row) => router.push(`/users/${row.id}`)}
|
|
185
|
-
emptyState={{ icon: Users, title: 'No users', description: 'Get started by inviting team members.' }}
|
|
535
|
+
columns={columns} data={devices} isLoading={isLoading}
|
|
536
|
+
searchPlaceholder="Search devices..."
|
|
537
|
+
defaultPageSize={25} exportFilename="devices"
|
|
538
|
+
onRowClick={(row) => router.push(`/devices/${row.id}`)}
|
|
539
|
+
emptyState={{ icon: Server, title: 'No devices', description: 'Run a discovery scan to get started.' }}
|
|
186
540
|
/>
|
|
187
541
|
```
|
|
188
542
|
|
|
189
|
-
|
|
543
|
+
| Prop | Type | Default | Description |
|
|
544
|
+
|------|------|---------|-------------|
|
|
545
|
+
| `columns` | `ColumnDef<T>[]` | -- | TanStack column definitions |
|
|
546
|
+
| `data` | `T[]` | -- | Row data |
|
|
547
|
+
| `isLoading` | `boolean` | `false` | Show loading skeleton |
|
|
548
|
+
| `emptyState` | `{ icon, title, description }` | -- | Custom empty state |
|
|
549
|
+
| `searchPlaceholder` | `string` | `'Search...'` | Search input placeholder |
|
|
550
|
+
| `onRowClick` | `(row: T) => void` | -- | Row click handler |
|
|
551
|
+
| `defaultSort` | `{ id, desc }` | -- | Initial sort configuration |
|
|
552
|
+
| `defaultPageSize` | `number` | `25` | Rows per page |
|
|
553
|
+
| `exportFilename` | `string` | -- | Enables CSV export button |
|
|
554
|
+
| `stickyFirstColumn` | `boolean` | `false` | Sticky first column on scroll |
|
|
555
|
+
| `density` | `'compact' \| 'comfortable' \| 'spacious'` | `'comfortable'` | Row density |
|
|
190
556
|
|
|
191
|
-
|
|
557
|
+
Built-in features: global search, auto-detected column filters (text/enum/number range), multi-column sort, pagination, density control (persisted to localStorage), column visibility picker with drag reorder, CSV export, row click, loading skeleton, empty state, Framer Motion row animations.
|
|
192
558
|
|
|
193
|
-
|
|
559
|
+
---
|
|
194
560
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
561
|
+
#### SmartTable
|
|
562
|
+
|
|
563
|
+
Enhanced DataTable that auto-generates filter suggestions by analyzing column data.
|
|
564
|
+
|
|
565
|
+
```tsx
|
|
566
|
+
import { SmartTable } from '@annondeveloper/ui-kit'
|
|
567
|
+
|
|
568
|
+
<SmartTable columns={columns} data={data} maxSuggestions={4} onFilterSuggestion={console.log} />
|
|
198
569
|
```
|
|
199
570
|
|
|
200
|
-
|
|
571
|
+
| Prop | Type | Default | Description |
|
|
572
|
+
|------|------|---------|-------------|
|
|
573
|
+
| ...all DataTable props | | | Inherits all DataTable props |
|
|
574
|
+
| `onFilterSuggestion` | `(suggestion: FilterSuggestion) => void` | -- | Suggestion click callback |
|
|
575
|
+
| `maxSuggestions` | `number` | `6` | Max visible suggestions |
|
|
201
576
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
577
|
+
Auto-detects: statistical outliers (>2 std dev), top-N frequent values, dominant pattern detection, minority value highlighting.
|
|
578
|
+
|
|
579
|
+
---
|
|
580
|
+
|
|
581
|
+
#### AnimatedCounter
|
|
582
|
+
|
|
583
|
+
Smooth number animation using requestAnimationFrame with cubic easing.
|
|
584
|
+
|
|
585
|
+
```tsx
|
|
586
|
+
import { AnimatedCounter } from '@annondeveloper/ui-kit'
|
|
587
|
+
|
|
588
|
+
<AnimatedCounter value={deviceCount} duration={400} format={n => n.toLocaleString()} />
|
|
205
589
|
```
|
|
206
590
|
|
|
207
|
-
|
|
591
|
+
| Prop | Type | Default | Description |
|
|
592
|
+
|------|------|---------|-------------|
|
|
593
|
+
| `value` | `number` | -- | Target value |
|
|
594
|
+
| `duration` | `number` | `400` | Animation duration (ms) |
|
|
595
|
+
| `format` | `(n: number) => string` | -- | Custom number formatter |
|
|
208
596
|
|
|
209
|
-
|
|
210
|
-
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
#### Sparkline
|
|
600
|
+
|
|
601
|
+
Tiny inline SVG sparkline chart with gradient fill.
|
|
602
|
+
|
|
603
|
+
```tsx
|
|
604
|
+
import { Sparkline } from '@annondeveloper/ui-kit'
|
|
605
|
+
|
|
606
|
+
<Sparkline data={[10, 25, 18, 30, 22]} width={80} height={24} showDots />
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
| Prop | Type | Default | Description |
|
|
610
|
+
|------|------|---------|-------------|
|
|
611
|
+
| `data` | `number[]` | -- | Values to plot (min 2) |
|
|
612
|
+
| `width` | `number` | `80` | SVG width |
|
|
613
|
+
| `height` | `number` | `24` | SVG height |
|
|
614
|
+
| `color` | `string` | `'hsl(var(--brand-primary))'` | Line color |
|
|
615
|
+
| `fillOpacity` | `number` | `0.1` | Gradient fill opacity (0 to disable) |
|
|
616
|
+
| `showDots` | `boolean` | `false` | Dots on first/last points |
|
|
617
|
+
|
|
618
|
+
---
|
|
619
|
+
|
|
620
|
+
#### TruncatedText
|
|
621
|
+
|
|
622
|
+
Auto-truncating text with tooltip and copy-to-clipboard on hover.
|
|
623
|
+
|
|
624
|
+
```tsx
|
|
625
|
+
import { TruncatedText } from '@annondeveloper/ui-kit'
|
|
626
|
+
|
|
627
|
+
<TruncatedText text="very-long-hostname-that-overflows.example.com" maxWidth={200} />
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
| Prop | Type | Default | Description |
|
|
631
|
+
|------|------|---------|-------------|
|
|
632
|
+
| `text` | `string` | -- | Full text content |
|
|
633
|
+
| `maxWidth` | `string \| number` | `'100%'` | Max width for truncation |
|
|
634
|
+
|
|
635
|
+
---
|
|
636
|
+
|
|
637
|
+
#### CopyBlock
|
|
638
|
+
|
|
639
|
+
Monospace code/text display with one-click copy and collapsible overflow.
|
|
640
|
+
|
|
641
|
+
```tsx
|
|
642
|
+
import { CopyBlock } from '@annondeveloper/ui-kit'
|
|
643
|
+
|
|
644
|
+
<CopyBlock content="curl -X GET https://api.example.com/health" language="bash" label="Health check" />
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
| Prop | Type | Default | Description |
|
|
648
|
+
|------|------|---------|-------------|
|
|
649
|
+
| `content` | `string` | -- | Text content |
|
|
650
|
+
| `language` | `string` | -- | Language hint (e.g. "json", "bash") |
|
|
651
|
+
| `showLineNumbers` | `boolean` | `false` | Show line number gutter |
|
|
652
|
+
| `maxHeight` | `number` | -- | Max height before "Show more" toggle |
|
|
653
|
+
| `label` | `string` | -- | Label above the block |
|
|
654
|
+
|
|
655
|
+
---
|
|
656
|
+
|
|
657
|
+
#### DiffViewer
|
|
658
|
+
|
|
659
|
+
Line-by-line diff viewer using LCS algorithm with collapsible unchanged sections.
|
|
660
|
+
|
|
661
|
+
```tsx
|
|
662
|
+
import { DiffViewer } from '@annondeveloper/ui-kit'
|
|
663
|
+
|
|
664
|
+
<DiffViewer oldValue={previousConfig} newValue={currentConfig} mode="side-by-side" showLineNumbers />
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
| Prop | Type | Default | Description |
|
|
668
|
+
|------|------|---------|-------------|
|
|
669
|
+
| `oldValue` | `string` | -- | Original text |
|
|
670
|
+
| `newValue` | `string` | -- | Modified text |
|
|
671
|
+
| `mode` | `'inline' \| 'side-by-side'` | `'inline'` | Display mode |
|
|
672
|
+
| `language` | `string` | -- | Language hint |
|
|
673
|
+
| `showLineNumbers` | `boolean` | `true` | Show line numbers |
|
|
674
|
+
|
|
675
|
+
---
|
|
676
|
+
|
|
677
|
+
### Status & Monitoring
|
|
678
|
+
|
|
679
|
+
#### StatusBadge
|
|
680
|
+
|
|
681
|
+
Configurable status indicator with colored dot and label.
|
|
682
|
+
|
|
683
|
+
```tsx
|
|
684
|
+
import { StatusBadge, defaultStatusMap } from '@annondeveloper/ui-kit'
|
|
685
|
+
|
|
686
|
+
<StatusBadge status="active" pulse />
|
|
687
|
+
<StatusBadge status="healthy" statusMap={myCustomStatuses} />
|
|
688
|
+
```
|
|
689
|
+
|
|
690
|
+
| Prop | Type | Default | Description |
|
|
691
|
+
|------|------|---------|-------------|
|
|
692
|
+
| `status` | `string` | -- | Status key |
|
|
693
|
+
| `label` | `string` | -- | Override display label |
|
|
694
|
+
| `size` | `'sm' \| 'md'` | `'md'` | Size variant |
|
|
695
|
+
| `pulse` | `boolean` | `false` | Pulse animation on the dot |
|
|
696
|
+
| `statusMap` | `Record<string, StatusConfig>` | `defaultStatusMap` | Custom status definitions |
|
|
697
|
+
|
|
698
|
+
Built-in statuses: `ok`, `active`, `warning`, `critical`, `unknown`, `maintenance`, `stale`, `inactive`, `decommissioned`, `pending`.
|
|
699
|
+
|
|
700
|
+
---
|
|
701
|
+
|
|
702
|
+
#### StatusPulse
|
|
703
|
+
|
|
704
|
+
Animated status dot with optional pulse ring and label.
|
|
705
|
+
|
|
706
|
+
```tsx
|
|
707
|
+
import { StatusPulse } from '@annondeveloper/ui-kit'
|
|
708
|
+
|
|
709
|
+
<StatusPulse status="online" />
|
|
710
|
+
<StatusPulse status="degraded" label={false} />
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
| Prop | Type | Default | Description |
|
|
714
|
+
|------|------|---------|-------------|
|
|
715
|
+
| `status` | `string` | -- | Status key |
|
|
716
|
+
| `label` | `boolean` | `true` | Show status text |
|
|
717
|
+
| `configMap` | `Record<string, PulseConfig>` | `defaultPulseConfigMap` | Custom pulse configs |
|
|
718
|
+
|
|
719
|
+
Built-in statuses: `online` (green pulse), `degraded` (yellow fast pulse), `offline` (red, no pulse), `unknown` (gray, no pulse).
|
|
720
|
+
|
|
721
|
+
---
|
|
722
|
+
|
|
723
|
+
#### MetricCard
|
|
724
|
+
|
|
725
|
+
Dashboard stat tile with animated counter, trend indicator, and optional sparkline.
|
|
726
|
+
|
|
727
|
+
```tsx
|
|
728
|
+
import { MetricCard } from '@annondeveloper/ui-kit'
|
|
729
|
+
import { HardDrive } from 'lucide-react'
|
|
730
|
+
|
|
731
|
+
<MetricCard
|
|
732
|
+
label="Disk Usage" value={78.3} format={n => `${n.toFixed(1)}%`}
|
|
733
|
+
previousValue={72.1} trendDirection="up-bad"
|
|
734
|
+
icon={HardDrive} status="warning"
|
|
735
|
+
sparklineData={[65, 68, 70, 72, 75, 78]}
|
|
736
|
+
/>
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
| Prop | Type | Default | Description |
|
|
740
|
+
|------|------|---------|-------------|
|
|
741
|
+
| `label` | `string` | -- | Metric name |
|
|
742
|
+
| `value` | `number` | -- | Current value |
|
|
743
|
+
| `format` | `(n: number) => string` | -- | Custom formatter |
|
|
744
|
+
| `previousValue` | `number` | -- | Previous value for trend |
|
|
745
|
+
| `trendDirection` | `'up-good' \| 'up-bad' \| 'down-good' \| 'down-bad'` | -- | Color interpretation |
|
|
746
|
+
| `icon` | `ElementType` | -- | Lucide icon component |
|
|
747
|
+
| `status` | `'ok' \| 'warning' \| 'critical'` | -- | Left border accent color |
|
|
748
|
+
| `sparklineData` | `number[]` | -- | Recent values for inline chart |
|
|
749
|
+
|
|
750
|
+
---
|
|
751
|
+
|
|
752
|
+
#### ThresholdGauge
|
|
753
|
+
|
|
754
|
+
Semicircular SVG gauge with color-coded threshold zones.
|
|
755
|
+
|
|
756
|
+
```tsx
|
|
757
|
+
import { ThresholdGauge } from '@annondeveloper/ui-kit'
|
|
758
|
+
|
|
759
|
+
<ThresholdGauge value={85} label="CPU" thresholds={{ warning: 70, critical: 90 }} size={120} />
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
| Prop | Type | Default | Description |
|
|
763
|
+
|------|------|---------|-------------|
|
|
764
|
+
| `value` | `number` | -- | Gauge value (0-100) |
|
|
765
|
+
| `label` | `string` | -- | Label below gauge |
|
|
766
|
+
| `thresholds` | `{ warning, critical }` | `{ warning: 70, critical: 90 }` | Color zone boundaries |
|
|
767
|
+
| `size` | `number` | `120` | Diameter in pixels |
|
|
768
|
+
| `showValue` | `boolean` | `true` | Show value in center |
|
|
769
|
+
| `format` | `(n: number) => string` | -- | Custom value formatter |
|
|
770
|
+
|
|
771
|
+
---
|
|
772
|
+
|
|
773
|
+
#### UtilizationBar
|
|
774
|
+
|
|
775
|
+
Horizontal bar with color-coded thresholds. Animates fill on mount.
|
|
776
|
+
|
|
777
|
+
```tsx
|
|
778
|
+
import { UtilizationBar } from '@annondeveloper/ui-kit'
|
|
779
|
+
|
|
780
|
+
<UtilizationBar value={92} label="Memory" thresholds={{ warning: 70, critical: 90 }} size="md" />
|
|
211
781
|
```
|
|
212
782
|
|
|
783
|
+
| Prop | Type | Default | Description |
|
|
784
|
+
|------|------|---------|-------------|
|
|
785
|
+
| `value` | `number` | -- | Utilization percentage (0-100) |
|
|
786
|
+
| `thresholds` | `{ warning, critical }` | `{ warning: 70, critical: 90 }` | Color zone boundaries |
|
|
787
|
+
| `label` | `string` | -- | Label to the left |
|
|
788
|
+
| `showValue` | `boolean` | `true` | Show percentage text |
|
|
789
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Bar height |
|
|
790
|
+
| `animated` | `boolean` | `true` | Animate fill width |
|
|
791
|
+
|
|
792
|
+
---
|
|
793
|
+
|
|
794
|
+
#### UptimeTracker
|
|
795
|
+
|
|
796
|
+
GitHub/Statuspage-style daily uptime bar strip.
|
|
797
|
+
|
|
798
|
+
```tsx
|
|
799
|
+
import { UptimeTracker } from '@annondeveloper/ui-kit'
|
|
800
|
+
|
|
801
|
+
<UptimeTracker
|
|
802
|
+
days={last90Days} label="API Server" showPercentage
|
|
803
|
+
onDayClick={(day) => showIncidents(day.date)}
|
|
804
|
+
/>
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
| Prop | Type | Default | Description |
|
|
808
|
+
|------|------|---------|-------------|
|
|
809
|
+
| `days` | `DayStatus[]` | -- | `{ date, status: 'ok'\|'degraded'\|'outage'\|'no-data', uptime? }` |
|
|
810
|
+
| `showPercentage` | `boolean` | `true` | Show overall uptime % |
|
|
811
|
+
| `label` | `string` | -- | Header label |
|
|
812
|
+
| `onDayClick` | `(day: DayStatus) => void` | -- | Day click callback |
|
|
813
|
+
|
|
814
|
+
---
|
|
815
|
+
|
|
816
|
+
#### PortStatusGrid
|
|
817
|
+
|
|
818
|
+
Grid of colored indicators for network ports/interfaces.
|
|
819
|
+
|
|
820
|
+
```tsx
|
|
821
|
+
import { PortStatusGrid } from '@annondeveloper/ui-kit'
|
|
822
|
+
|
|
823
|
+
<PortStatusGrid
|
|
824
|
+
ports={switchPorts} columns={24} size="md"
|
|
825
|
+
onPortClick={(port) => showPortDetail(port.id)}
|
|
826
|
+
/>
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
| Prop | Type | Default | Description |
|
|
830
|
+
|------|------|---------|-------------|
|
|
831
|
+
| `ports` | `PortStatus[]` | -- | `{ id, label, status: 'up'\|'down'\|'disabled'\|'error', speed?, utilization? }` |
|
|
832
|
+
| `columns` | `number` | auto-fit | Grid columns |
|
|
833
|
+
| `size` | `'sm' \| 'md'` | `'sm'` | Indicator size |
|
|
834
|
+
| `onPortClick` | `(port: PortStatus) => void` | -- | Port click callback |
|
|
835
|
+
|
|
836
|
+
---
|
|
837
|
+
|
|
838
|
+
#### PipelineStage
|
|
839
|
+
|
|
840
|
+
Horizontal data pipeline visualization with status dots and chevron connectors.
|
|
841
|
+
|
|
842
|
+
```tsx
|
|
843
|
+
import { PipelineStage } from '@annondeveloper/ui-kit'
|
|
844
|
+
|
|
845
|
+
<PipelineStage
|
|
846
|
+
stages={[
|
|
847
|
+
{ name: 'Collector', status: 'active', metric: { label: 'msg/s', value: '1.2K' } },
|
|
848
|
+
{ name: 'Normalizer', status: 'active' },
|
|
849
|
+
{ name: 'Writer', status: 'error' },
|
|
850
|
+
]}
|
|
851
|
+
onStageClick={(stage) => showStageDetail(stage)}
|
|
852
|
+
/>
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
| Prop | Type | Default | Description |
|
|
856
|
+
|------|------|---------|-------------|
|
|
857
|
+
| `stages` | `StageInfo[]` | -- | `{ name, status: 'active'\|'idle'\|'error'\|'disabled', metric?, icon? }` |
|
|
858
|
+
| `onStageClick` | `(stage, index) => void` | -- | Stage click callback |
|
|
859
|
+
|
|
860
|
+
---
|
|
861
|
+
|
|
862
|
+
#### SeverityTimeline
|
|
863
|
+
|
|
864
|
+
Horizontal scrollable event timeline with severity-colored dots.
|
|
865
|
+
|
|
866
|
+
```tsx
|
|
867
|
+
import { SeverityTimeline } from '@annondeveloper/ui-kit'
|
|
868
|
+
|
|
869
|
+
<SeverityTimeline events={recentAlerts} maxVisible={20} onEventClick={showAlertDetail} />
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
| Prop | Type | Default | Description |
|
|
873
|
+
|------|------|---------|-------------|
|
|
874
|
+
| `events` | `TimelineEvent[]` | -- | `{ time, label, severity: 'critical'\|'warning'\|'info'\|'ok', detail? }` |
|
|
875
|
+
| `maxVisible` | `number` | `20` | Max visible events |
|
|
876
|
+
| `onEventClick` | `(event) => void` | -- | Event click callback |
|
|
877
|
+
|
|
878
|
+
---
|
|
879
|
+
|
|
880
|
+
#### TimeRangeSelector
|
|
881
|
+
|
|
882
|
+
Compact horizontal pill-group time range selector.
|
|
883
|
+
|
|
884
|
+
```tsx
|
|
885
|
+
import { TimeRangeSelector } from '@annondeveloper/ui-kit'
|
|
886
|
+
|
|
887
|
+
<TimeRangeSelector value={range} onChange={(v, r) => setRange(v)} />
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
| Prop | Type | Default | Description |
|
|
891
|
+
|------|------|---------|-------------|
|
|
892
|
+
| `value` | `string` | -- | Selected range value |
|
|
893
|
+
| `onChange` | `(value, range) => void` | -- | Selection callback |
|
|
894
|
+
| `ranges` | `TimeRange[]` | `[1h, 6h, 24h, 7d, 30d]` | Custom range options (each `{ label, value, seconds }`) |
|
|
895
|
+
|
|
896
|
+
---
|
|
897
|
+
|
|
898
|
+
#### LogViewer
|
|
899
|
+
|
|
900
|
+
Real-time log stream viewer with severity-colored borders and auto-scroll.
|
|
901
|
+
|
|
902
|
+
```tsx
|
|
903
|
+
import { LogViewer } from '@annondeveloper/ui-kit'
|
|
904
|
+
|
|
905
|
+
<LogViewer entries={logs} maxHeight={400} autoScroll showTimestamps onEntryClick={showDetail} />
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
| Prop | Type | Default | Description |
|
|
909
|
+
|------|------|---------|-------------|
|
|
910
|
+
| `entries` | `LogEntry[]` | -- | `{ time, level: 'error'\|'warn'\|'info'\|'debug'\|'trace', message, source? }` |
|
|
911
|
+
| `maxHeight` | `number` | `400` | Container max height |
|
|
912
|
+
| `autoScroll` | `boolean` | `true` | Auto-scroll on new entries |
|
|
913
|
+
| `showTimestamps` | `boolean` | `true` | Show timestamps column |
|
|
914
|
+
| `showLevel` | `boolean` | `true` | Show level badge |
|
|
915
|
+
| `onEntryClick` | `(entry) => void` | -- | Entry click callback |
|
|
916
|
+
|
|
917
|
+
Features: search filtering, "N new entries" floating badge when scrolled up.
|
|
918
|
+
|
|
919
|
+
---
|
|
920
|
+
|
|
921
|
+
### Real-Time & AI
|
|
922
|
+
|
|
923
|
+
#### RealtimeValue
|
|
924
|
+
|
|
925
|
+
Live data display with freshness tracking, connection state, and delta arrows.
|
|
926
|
+
|
|
927
|
+
```tsx
|
|
928
|
+
import { RealtimeValue } from '@annondeveloper/ui-kit'
|
|
929
|
+
import { fmtBps } from '@annondeveloper/ui-kit'
|
|
930
|
+
|
|
931
|
+
<RealtimeValue
|
|
932
|
+
value={throughput} format={fmtBps}
|
|
933
|
+
previousValue={prevThroughput} lastUpdated={lastTs}
|
|
934
|
+
staleAfterMs={30000} connectionState="connected" size="lg"
|
|
935
|
+
/>
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
| Prop | Type | Default | Description |
|
|
939
|
+
|------|------|---------|-------------|
|
|
940
|
+
| `value` | `number \| string` | -- | Current value |
|
|
941
|
+
| `label` | `string` | -- | Label text |
|
|
942
|
+
| `format` | `(v: number) => string` | -- | Custom formatter |
|
|
943
|
+
| `lastUpdated` | `string \| Date` | -- | Last data timestamp |
|
|
944
|
+
| `staleAfterMs` | `number` | `30000` | Staleness threshold (ms) |
|
|
945
|
+
| `connectionState` | `'connected' \| 'reconnecting' \| 'disconnected'` | `'connected'` | Connection indicator |
|
|
946
|
+
| `previousValue` | `number` | -- | Previous value for delta |
|
|
947
|
+
| `animate` | `boolean` | `true` | Animate value changes |
|
|
948
|
+
| `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Display size |
|
|
949
|
+
|
|
950
|
+
Features: animated number transitions, freshness dot (green/yellow/red), ping animation when fresh, connection state icon (reconnecting spinner, disconnected icon), auto-updating relative timestamp.
|
|
951
|
+
|
|
952
|
+
---
|
|
953
|
+
|
|
954
|
+
#### StreamingText
|
|
955
|
+
|
|
956
|
+
AI/LLM streaming text display with blinking cursor and inline markdown formatting.
|
|
957
|
+
|
|
958
|
+
```tsx
|
|
959
|
+
import { StreamingText } from '@annondeveloper/ui-kit'
|
|
960
|
+
|
|
961
|
+
<StreamingText text={response} isStreaming={isGenerating} onComplete={() => logCompletion()} />
|
|
962
|
+
```
|
|
963
|
+
|
|
964
|
+
| Prop | Type | Default | Description |
|
|
965
|
+
|------|------|---------|-------------|
|
|
966
|
+
| `text` | `string` | -- | Text content (grows as tokens arrive) |
|
|
967
|
+
| `isStreaming` | `boolean` | -- | Whether tokens are still arriving |
|
|
968
|
+
| `speed` | `number` | `500` | Cursor blink speed (ms) |
|
|
969
|
+
| `showCursor` | `boolean` | `true` | Show blinking cursor |
|
|
970
|
+
| `onComplete` | `() => void` | -- | Streaming complete callback |
|
|
971
|
+
|
|
972
|
+
Features: auto-scroll during streaming, inline `**bold**` and `` `code` `` formatting, copy button appears on completion.
|
|
973
|
+
|
|
974
|
+
---
|
|
975
|
+
|
|
976
|
+
#### TypingIndicator
|
|
977
|
+
|
|
978
|
+
"Someone is typing" indicator with three animation variants.
|
|
979
|
+
|
|
980
|
+
```tsx
|
|
981
|
+
import { TypingIndicator } from '@annondeveloper/ui-kit'
|
|
982
|
+
|
|
983
|
+
<TypingIndicator variant="dots" label="AI is thinking" size="md" />
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
| Prop | Type | Default | Description |
|
|
987
|
+
|------|------|---------|-------------|
|
|
988
|
+
| `label` | `string` | -- | Status text |
|
|
989
|
+
| `variant` | `'dots' \| 'pulse' \| 'text'` | `'dots'` | Animation variant |
|
|
990
|
+
| `size` | `'sm' \| 'md'` | `'md'` | Size preset |
|
|
991
|
+
|
|
992
|
+
---
|
|
993
|
+
|
|
994
|
+
#### ConfidenceBar
|
|
995
|
+
|
|
996
|
+
Horizontal probability bar with color-coded threshold zones.
|
|
997
|
+
|
|
998
|
+
```tsx
|
|
999
|
+
import { ConfidenceBar } from '@annondeveloper/ui-kit'
|
|
1000
|
+
|
|
1001
|
+
<ConfidenceBar value={0.87} label="Match confidence" thresholds={{ low: 0.3, medium: 0.7 }} />
|
|
1002
|
+
```
|
|
1003
|
+
|
|
1004
|
+
| Prop | Type | Default | Description |
|
|
1005
|
+
|------|------|---------|-------------|
|
|
1006
|
+
| `value` | `number` | -- | Confidence (0-1) |
|
|
1007
|
+
| `label` | `string` | -- | Label text |
|
|
1008
|
+
| `showPercentage` | `boolean` | `true` | Show percentage |
|
|
1009
|
+
| `thresholds` | `{ low, medium }` | `{ low: 0.3, medium: 0.7 }` | Color zone boundaries |
|
|
1010
|
+
| `size` | `'sm' \| 'md'` | `'md'` | Bar height |
|
|
1011
|
+
|
|
1012
|
+
---
|
|
1013
|
+
|
|
1014
|
+
#### CommandBar
|
|
1015
|
+
|
|
1016
|
+
Universal command palette activated by Cmd+K / Ctrl+K.
|
|
1017
|
+
|
|
1018
|
+
```tsx
|
|
1019
|
+
import { CommandBar } from '@annondeveloper/ui-kit'
|
|
1020
|
+
|
|
1021
|
+
<CommandBar
|
|
1022
|
+
items={[
|
|
1023
|
+
{ id: 'devices', label: 'Go to Devices', shortcut: 'G D', onSelect: () => navigate('/devices') },
|
|
1024
|
+
{ id: 'search', label: 'Search entities', icon: Search, onSelect: openSearch, keywords: ['find'] },
|
|
1025
|
+
]}
|
|
1026
|
+
placeholder="Type a command..."
|
|
1027
|
+
onSearch={async (q) => fetchResults(q)}
|
|
1028
|
+
/>
|
|
1029
|
+
```
|
|
1030
|
+
|
|
1031
|
+
| Prop | Type | Default | Description |
|
|
1032
|
+
|------|------|---------|-------------|
|
|
1033
|
+
| `items` | `CommandItem[]` | -- | `{ id, label, description?, icon?, shortcut?, group?, onSelect, keywords? }` |
|
|
1034
|
+
| `placeholder` | `string` | `'Type a command...'` | Search placeholder |
|
|
1035
|
+
| `hotkey` | `string` | `'k'` | Hotkey letter (Cmd/Ctrl+key) |
|
|
1036
|
+
| `onSearch` | `(query) => Promise<CommandItem[]>` | -- | Async search function |
|
|
1037
|
+
| `recentKey` | `string` | `'ui-kit-command-recent'` | localStorage key for recents |
|
|
1038
|
+
| `maxRecent` | `number` | `5` | Max recent items |
|
|
1039
|
+
|
|
1040
|
+
Features: fuzzy search scoring, grouped sections, recent selections (localStorage), async search with debounce, keyboard navigation (arrows + Enter), keyboard shortcut hints in footer.
|
|
1041
|
+
|
|
1042
|
+
---
|
|
1043
|
+
|
|
1044
|
+
#### LiveFeed
|
|
1045
|
+
|
|
1046
|
+
Real-time event feed with animated entry, pause/resume, and type-colored borders.
|
|
1047
|
+
|
|
1048
|
+
```tsx
|
|
1049
|
+
import { LiveFeed } from '@annondeveloper/ui-kit'
|
|
1050
|
+
|
|
1051
|
+
<LiveFeed
|
|
1052
|
+
items={events} maxVisible={50} showTimestamps autoScroll
|
|
1053
|
+
onItemClick={(item) => showDetail(item.id)}
|
|
1054
|
+
emptyMessage="Waiting for events..."
|
|
1055
|
+
/>
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
| Prop | Type | Default | Description |
|
|
1059
|
+
|------|------|---------|-------------|
|
|
1060
|
+
| `items` | `FeedItem[]` | -- | `{ id, content: ReactNode, timestamp, type?: 'info'\|'success'\|'warning'\|'error' }` |
|
|
1061
|
+
| `maxVisible` | `number` | `50` | Max visible items |
|
|
1062
|
+
| `showTimestamps` | `boolean` | `true` | Show relative timestamps |
|
|
1063
|
+
| `autoScroll` | `boolean` | `true` | Auto-scroll to newest |
|
|
1064
|
+
| `onItemClick` | `(item) => void` | -- | Item click callback |
|
|
1065
|
+
| `emptyMessage` | `string` | `'No events yet'` | Empty state text |
|
|
1066
|
+
|
|
1067
|
+
Features: pause/resume button, "N new items" floating badge when scrolled, auto-updating relative timestamps.
|
|
1068
|
+
|
|
1069
|
+
---
|
|
1070
|
+
|
|
1071
|
+
#### NotificationStack
|
|
1072
|
+
|
|
1073
|
+
Fixed-position notification cards with auto-dismiss progress bars.
|
|
1074
|
+
|
|
1075
|
+
```tsx
|
|
1076
|
+
import { NotificationStack } from '@annondeveloper/ui-kit'
|
|
1077
|
+
|
|
1078
|
+
<NotificationStack
|
|
1079
|
+
notifications={notifications}
|
|
1080
|
+
onDismiss={(id) => removeNotification(id)}
|
|
1081
|
+
position="top-right" maxVisible={5}
|
|
1082
|
+
/>
|
|
1083
|
+
```
|
|
1084
|
+
|
|
1085
|
+
| Prop | Type | Default | Description |
|
|
1086
|
+
|------|------|---------|-------------|
|
|
1087
|
+
| `notifications` | `Notification[]` | -- | `{ id, title, message?, type, action?, dismissible?, duration? }` |
|
|
1088
|
+
| `onDismiss` | `(id: string) => void` | -- | Dismiss callback |
|
|
1089
|
+
| `position` | `'top-right' \| 'top-left' \| 'bottom-right' \| 'bottom-left'` | `'top-right'` | Screen position |
|
|
1090
|
+
| `maxVisible` | `number` | `5` | Max visible before stacking |
|
|
1091
|
+
|
|
1092
|
+
Features: type-specific icons and colors, action buttons, auto-dismiss with progress bar, overflow indicator, spring entry/exit animations.
|
|
1093
|
+
|
|
1094
|
+
---
|
|
1095
|
+
|
|
1096
|
+
### Layout & Feedback
|
|
1097
|
+
|
|
1098
|
+
#### EmptyState
|
|
1099
|
+
|
|
1100
|
+
Decorative placeholder with icon, title, description, and optional actions.
|
|
1101
|
+
|
|
1102
|
+
```tsx
|
|
1103
|
+
import { EmptyState, Button } from '@annondeveloper/ui-kit'
|
|
1104
|
+
import { Inbox } from 'lucide-react'
|
|
1105
|
+
|
|
1106
|
+
<EmptyState icon={Inbox} title="No alerts" description="Your infrastructure is healthy."
|
|
1107
|
+
actions={<Button size="sm">Configure Rules</Button>} />
|
|
1108
|
+
```
|
|
1109
|
+
|
|
1110
|
+
| Prop | Type | Default | Description |
|
|
1111
|
+
|------|------|---------|-------------|
|
|
1112
|
+
| `icon` | `LucideIcon` | -- | Center icon |
|
|
1113
|
+
| `title` | `string` | -- | Title text |
|
|
1114
|
+
| `description` | `string` | -- | Description text |
|
|
1115
|
+
| `actions` | `ReactNode` | -- | Action buttons |
|
|
1116
|
+
|
|
1117
|
+
---
|
|
1118
|
+
|
|
1119
|
+
#### Skeleton / SkeletonText / SkeletonCard
|
|
1120
|
+
|
|
1121
|
+
Shimmer loading placeholders.
|
|
1122
|
+
|
|
1123
|
+
```tsx
|
|
1124
|
+
import { Skeleton, SkeletonText, SkeletonCard } from '@annondeveloper/ui-kit'
|
|
1125
|
+
|
|
1126
|
+
<Skeleton className="h-8 w-32" />
|
|
1127
|
+
<SkeletonText lines={3} />
|
|
1128
|
+
<SkeletonCard />
|
|
1129
|
+
```
|
|
1130
|
+
|
|
1131
|
+
`SkeletonText` props: `lines?: number` (default 1).
|
|
1132
|
+
|
|
1133
|
+
---
|
|
1134
|
+
|
|
1135
|
+
#### Progress
|
|
1136
|
+
|
|
1137
|
+
Progress bar with optional label, animated fill, and indeterminate mode.
|
|
1138
|
+
|
|
1139
|
+
```tsx
|
|
1140
|
+
import { Progress } from '@annondeveloper/ui-kit'
|
|
1141
|
+
|
|
1142
|
+
<Progress value={65} max={100} label="Upload" showValue variant="success" />
|
|
1143
|
+
<Progress indeterminate label="Processing..." />
|
|
1144
|
+
```
|
|
1145
|
+
|
|
1146
|
+
| Prop | Type | Default | Description |
|
|
1147
|
+
|------|------|---------|-------------|
|
|
1148
|
+
| `value` | `number` | -- | Current value |
|
|
1149
|
+
| `max` | `number` | `100` | Maximum value |
|
|
1150
|
+
| `label` | `string` | -- | Label text |
|
|
1151
|
+
| `showValue` | `boolean` | `false` | Show percentage |
|
|
1152
|
+
| `variant` | `'default' \| 'success' \| 'warning' \| 'danger'` | `'default'` | Color variant |
|
|
1153
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Bar height |
|
|
1154
|
+
| `animated` | `boolean` | `true` | Animate fill changes |
|
|
1155
|
+
| `indeterminate` | `boolean` | `false` | Shimmer animation |
|
|
1156
|
+
|
|
1157
|
+
---
|
|
1158
|
+
|
|
1159
|
+
#### Avatar
|
|
1160
|
+
|
|
1161
|
+
User/entity avatar with image support, initials fallback, and status dot.
|
|
1162
|
+
|
|
1163
|
+
```tsx
|
|
1164
|
+
import { Avatar } from '@annondeveloper/ui-kit'
|
|
1165
|
+
|
|
1166
|
+
<Avatar src="/avatar.jpg" alt="Jane Doe" size="md" status="online" />
|
|
1167
|
+
<Avatar alt="John Smith" size="sm" /> {/* Shows "JS" initials */}
|
|
1168
|
+
```
|
|
1169
|
+
|
|
1170
|
+
| Prop | Type | Default | Description |
|
|
1171
|
+
|------|------|---------|-------------|
|
|
1172
|
+
| `src` | `string` | -- | Image URL |
|
|
1173
|
+
| `alt` | `string` | -- | Alt text (used for initials derivation) |
|
|
1174
|
+
| `fallback` | `string` | -- | Override initials |
|
|
1175
|
+
| `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Size preset |
|
|
1176
|
+
| `status` | `'online' \| 'offline' \| 'busy' \| 'away'` | -- | Status dot overlay |
|
|
1177
|
+
|
|
1178
|
+
---
|
|
1179
|
+
|
|
1180
|
+
#### InfiniteScroll
|
|
1181
|
+
|
|
1182
|
+
Virtualized infinite-scroll list using IntersectionObserver.
|
|
1183
|
+
|
|
1184
|
+
```tsx
|
|
1185
|
+
import { InfiniteScroll } from '@annondeveloper/ui-kit'
|
|
1186
|
+
|
|
1187
|
+
<InfiniteScroll
|
|
1188
|
+
items={logs} hasMore={hasNextPage} isLoading={isFetching}
|
|
1189
|
+
loadMore={fetchNextPage} itemHeight={48}
|
|
1190
|
+
renderItem={(item, i) => <LogRow key={item.id} entry={item} />}
|
|
1191
|
+
/>
|
|
1192
|
+
```
|
|
1193
|
+
|
|
1194
|
+
| Prop | Type | Default | Description |
|
|
1195
|
+
|------|------|---------|-------------|
|
|
1196
|
+
| `items` | `T[]` | -- | Loaded items |
|
|
1197
|
+
| `renderItem` | `(item, index) => JSX.Element` | -- | Item renderer |
|
|
1198
|
+
| `loadMore` | `() => void \| Promise<void>` | -- | Load more callback |
|
|
1199
|
+
| `hasMore` | `boolean` | -- | Whether more items exist |
|
|
1200
|
+
| `isLoading` | `boolean` | `false` | Loading state |
|
|
1201
|
+
| `threshold` | `number` | `200` | Trigger distance from bottom (px) |
|
|
1202
|
+
| `itemHeight` | `number` | -- | Fixed height for virtualization |
|
|
1203
|
+
| `emptyState` | `ReactNode` | -- | Empty content |
|
|
1204
|
+
|
|
1205
|
+
Features: optional height-based virtualization, scroll-to-top button, skeleton placeholders.
|
|
1206
|
+
|
|
1207
|
+
---
|
|
1208
|
+
|
|
1209
|
+
#### SortableList
|
|
1210
|
+
|
|
1211
|
+
Drag-and-drop reorderable list with smooth layout animations.
|
|
1212
|
+
|
|
1213
|
+
```tsx
|
|
1214
|
+
import { SortableList, DragHandle } from '@annondeveloper/ui-kit'
|
|
1215
|
+
|
|
1216
|
+
<SortableList
|
|
1217
|
+
items={rules} onReorder={setRules}
|
|
1218
|
+
renderItem={(item, i, dragProps) => (
|
|
1219
|
+
<div className="flex items-center gap-2 p-3">
|
|
1220
|
+
<DragHandle {...dragProps} />
|
|
1221
|
+
<span>{item.name}</span>
|
|
1222
|
+
</div>
|
|
1223
|
+
)}
|
|
1224
|
+
/>
|
|
1225
|
+
```
|
|
1226
|
+
|
|
1227
|
+
| Prop | Type | Default | Description |
|
|
1228
|
+
|------|------|---------|-------------|
|
|
1229
|
+
| `items` | `T[]` (each needs `id: string`) | -- | Items to display |
|
|
1230
|
+
| `onReorder` | `(items: T[]) => void` | -- | Reorder callback |
|
|
1231
|
+
| `renderItem` | `(item, index, dragHandleProps) => JSX.Element` | -- | Item renderer |
|
|
1232
|
+
| `direction` | `'vertical' \| 'horizontal'` | `'vertical'` | Layout direction |
|
|
1233
|
+
|
|
1234
|
+
Features: pointer-based drag (no external DnD library), keyboard reordering (Space to pick, arrows to move, Enter to drop), touch support, drop indicator line.
|
|
1235
|
+
|
|
1236
|
+
---
|
|
1237
|
+
|
|
1238
|
+
#### KanbanColumn
|
|
1239
|
+
|
|
1240
|
+
Kanban board column with title, count badge, and scrollable card list.
|
|
1241
|
+
|
|
1242
|
+
```tsx
|
|
1243
|
+
import { KanbanColumn } from '@annondeveloper/ui-kit'
|
|
1244
|
+
|
|
1245
|
+
<KanbanColumn
|
|
1246
|
+
title="In Progress" color="hsl(var(--status-warning))"
|
|
1247
|
+
items={tasks} onItemClick={showTask} onAddItem={createTask}
|
|
1248
|
+
/>
|
|
1249
|
+
```
|
|
1250
|
+
|
|
1251
|
+
| Prop | Type | Default | Description |
|
|
1252
|
+
|------|------|---------|-------------|
|
|
1253
|
+
| `title` | `string` | -- | Column title |
|
|
1254
|
+
| `items` | `KanbanItem[]` | -- | `{ id, title, description?, tags?, assignee? }` |
|
|
1255
|
+
| `count` | `number` | -- | Override count badge |
|
|
1256
|
+
| `color` | `string` | -- | Header accent color |
|
|
1257
|
+
| `onItemClick` | `(item) => void` | -- | Card click callback |
|
|
1258
|
+
| `onAddItem` | `() => void` | -- | Add button callback |
|
|
1259
|
+
|
|
1260
|
+
---
|
|
1261
|
+
|
|
1262
|
+
#### HeatmapCalendar
|
|
1263
|
+
|
|
1264
|
+
GitHub-style contribution heatmap calendar with configurable color scale.
|
|
1265
|
+
|
|
1266
|
+
```tsx
|
|
1267
|
+
import { HeatmapCalendar } from '@annondeveloper/ui-kit'
|
|
1268
|
+
|
|
1269
|
+
<HeatmapCalendar data={dailyMetrics} onDayClick={(d) => showDayDetail(d.date)} showMonthLabels showDayLabels />
|
|
1270
|
+
```
|
|
1271
|
+
|
|
1272
|
+
| Prop | Type | Default | Description |
|
|
1273
|
+
|------|------|---------|-------------|
|
|
1274
|
+
| `data` | `DayValue[]` | -- | `{ date: 'YYYY-MM-DD', value: number }` |
|
|
1275
|
+
| `startDate` | `string` | 365 days ago | Start date |
|
|
1276
|
+
| `endDate` | `string` | Today | End date |
|
|
1277
|
+
| `colorScale` | `string[]` | Green 5-step scale | 5 colors lightest to darkest |
|
|
1278
|
+
| `onDayClick` | `(day) => void` | -- | Day click callback |
|
|
1279
|
+
| `showMonthLabels` | `boolean` | `true` | Month labels at top |
|
|
1280
|
+
| `showDayLabels` | `boolean` | `true` | Day-of-week labels |
|
|
1281
|
+
| `tooltipFormat` | `(day) => string` | -- | Custom tooltip format |
|
|
1282
|
+
|
|
1283
|
+
---
|
|
1284
|
+
|
|
1285
|
+
#### Toaster / toast
|
|
1286
|
+
|
|
1287
|
+
Pre-themed Sonner toast container. Import once, use `toast()` anywhere.
|
|
1288
|
+
|
|
1289
|
+
```tsx
|
|
1290
|
+
// In layout:
|
|
1291
|
+
import { Toaster } from '@annondeveloper/ui-kit'
|
|
1292
|
+
<Toaster theme="dark" position="bottom-right" />
|
|
1293
|
+
|
|
1294
|
+
// Anywhere:
|
|
1295
|
+
import { toast } from '@annondeveloper/ui-kit'
|
|
1296
|
+
toast.success('Deployment complete')
|
|
1297
|
+
toast.error('Connection failed')
|
|
1298
|
+
```
|
|
1299
|
+
|
|
1300
|
+
| Prop | Type | Default | Description |
|
|
1301
|
+
|------|------|---------|-------------|
|
|
1302
|
+
| `theme` | `'dark' \| 'light'` | `'dark'` | Toast theme |
|
|
1303
|
+
| `position` | Sonner positions | `'bottom-right'` | Screen position |
|
|
1304
|
+
| `duration` | `number` | `4000` | Auto-dismiss (ms) |
|
|
1305
|
+
|
|
1306
|
+
---
|
|
1307
|
+
|
|
1308
|
+
#### SuccessCheckmark
|
|
1309
|
+
|
|
1310
|
+
Animated SVG checkmark with circle and path draw animations.
|
|
1311
|
+
|
|
1312
|
+
```tsx
|
|
1313
|
+
import { SuccessCheckmark } from '@annondeveloper/ui-kit'
|
|
1314
|
+
|
|
1315
|
+
<SuccessCheckmark size={24} />
|
|
1316
|
+
```
|
|
1317
|
+
|
|
1318
|
+
| Prop | Type | Default | Description |
|
|
1319
|
+
|------|------|---------|-------------|
|
|
1320
|
+
| `size` | `number` | `20` | SVG size in pixels |
|
|
1321
|
+
|
|
1322
|
+
---
|
|
1323
|
+
|
|
1324
|
+
## Utilities
|
|
1325
|
+
|
|
1326
|
+
### Class Merging
|
|
1327
|
+
|
|
1328
|
+
```tsx
|
|
1329
|
+
import { cn } from '@annondeveloper/ui-kit'
|
|
1330
|
+
|
|
1331
|
+
cn('px-4 py-2', isActive && 'bg-blue-500', className)
|
|
1332
|
+
```
|
|
1333
|
+
|
|
1334
|
+
### Formatters
|
|
1335
|
+
|
|
1336
|
+
| Function | Example | Output |
|
|
1337
|
+
|----------|---------|--------|
|
|
1338
|
+
| `fmtBps(n)` | `fmtBps(1_000_000_000)` | `"1.0 Gbps"` |
|
|
1339
|
+
| `fmtSpeed(n)` | `fmtSpeed(10_000_000_000)` | `"10G"` |
|
|
1340
|
+
| `fmtBytes(n)` | `fmtBytes(1_073_741_824)` | `"1.0 GB"` |
|
|
1341
|
+
| `fmtPct(n, d?)` | `fmtPct(95.6)` | `"95.6%"` |
|
|
1342
|
+
| `fmtUptime(secs)` | `fmtUptime(90061)` | `"1d 1h"` |
|
|
1343
|
+
| `fmtRelative(iso)` | `fmtRelative('2024-01-01')` | `"3d ago"` |
|
|
1344
|
+
| `fmtCompact(n)` | `fmtCompact(480_933_305)` | `"480.9M"` |
|
|
1345
|
+
| `fmtDuration(secs)` | `fmtDuration(0.003)` | `"3ms"` |
|
|
1346
|
+
| `fmtUtil(bps, speed)` | `fmtUtil(500_000_000, 1_000_000_000)` | `"50%"` |
|
|
1347
|
+
| `stripCidr(ip)` | `stripCidr('10.0.0.1/32')` | `"10.0.0.1"` |
|
|
1348
|
+
| `clamp(v, min, max)` | `clamp(150, 0, 100)` | `100` |
|
|
1349
|
+
|
|
1350
|
+
### utilColor
|
|
1351
|
+
|
|
1352
|
+
Returns a Tailwind class based on utilization percentage:
|
|
1353
|
+
|
|
1354
|
+
```tsx
|
|
1355
|
+
import { utilColor, defaultUtilColorMap } from '@annondeveloper/ui-kit'
|
|
1356
|
+
|
|
1357
|
+
utilColor(85) // "text-[hsl(var(--status-critical))]"
|
|
1358
|
+
utilColor(45) // "text-[hsl(var(--status-ok))]"
|
|
1359
|
+
utilColor(75, customColorMap) // uses your thresholds
|
|
1360
|
+
```
|
|
1361
|
+
|
|
1362
|
+
The `defaultUtilColorMap` thresholds: >= 80% critical (red), >= 60% warning (yellow), < 60% ok (green).
|
|
1363
|
+
|
|
1364
|
+
### createBadgeVariant
|
|
1365
|
+
|
|
1366
|
+
Factory for domain-specific badge components. See [Badge](#badge) section above.
|
|
1367
|
+
|
|
1368
|
+
---
|
|
1369
|
+
|
|
1370
|
+
## Theme System
|
|
1371
|
+
|
|
1372
|
+
The library uses CSS custom properties for theming. Dark mode is the default; add the `light` class to `<html>` for light mode.
|
|
1373
|
+
|
|
1374
|
+
### Token Reference
|
|
1375
|
+
|
|
1376
|
+
| Token | Purpose | Dark Default | Light Default |
|
|
1377
|
+
|-------|---------|--------------|---------------|
|
|
1378
|
+
| `--bg-base` | Page background | `222 47% 7%` | `210 40% 98%` |
|
|
1379
|
+
| `--bg-surface` | Card/panel background | `222 40% 10%` | `0 0% 100%` |
|
|
1380
|
+
| `--bg-elevated` | Elevated surface (dropdowns, popovers) | `222 35% 14%` | `210 40% 96%` |
|
|
1381
|
+
| `--bg-overlay` | Overlay/hover background | `222 30% 18%` | `210 30% 92%` |
|
|
1382
|
+
| `--border-subtle` | Subtle borders | `222 30% 20%` | `210 20% 88%` |
|
|
1383
|
+
| `--border-default` | Default borders | `222 25% 25%` | `210 20% 80%` |
|
|
1384
|
+
| `--border-strong` | Strong/focus borders | `222 20% 35%` | `210 20% 65%` |
|
|
1385
|
+
| `--text-primary` | Primary text | `210 40% 95%` | `222 47% 11%` |
|
|
1386
|
+
| `--text-secondary` | Secondary text | `210 20% 70%` | `222 25% 35%` |
|
|
1387
|
+
| `--text-tertiary` | Tertiary text | `210 15% 50%` | `222 15% 55%` |
|
|
1388
|
+
| `--text-disabled` | Disabled text | `210 10% 35%` | `222 10% 75%` |
|
|
1389
|
+
| `--brand-primary` | Brand/accent color | `217 91% 60%` | `217 91% 50%` |
|
|
1390
|
+
| `--brand-secondary` | Secondary accent | `258 80% 65%` | `258 80% 58%` |
|
|
1391
|
+
| `--text-on-brand` | Text on brand backgrounds | `0 0% 100%` | `0 0% 100%` |
|
|
1392
|
+
| `--status-ok` | Success/online | `142 71% 45%` | `142 71% 38%` |
|
|
1393
|
+
| `--status-warning` | Warning/degraded | `38 92% 50%` | `38 92% 42%` |
|
|
1394
|
+
| `--status-critical` | Critical/error | `0 84% 60%` | `0 84% 52%` |
|
|
1395
|
+
| `--status-unknown` | Unknown status | `220 15% 50%` | `220 15% 55%` |
|
|
1396
|
+
| `--status-maintenance` | Maintenance mode | `258 60% 65%` | `258 60% 58%` |
|
|
1397
|
+
| `--chart-1` through `--chart-8` | Chart color series | Various | Various |
|
|
1398
|
+
|
|
1399
|
+
### Customization
|
|
1400
|
+
|
|
1401
|
+
Override any token in your own CSS:
|
|
1402
|
+
|
|
1403
|
+
```css
|
|
1404
|
+
:root {
|
|
1405
|
+
--brand-primary: 160 84% 39%; /* teal accent */
|
|
1406
|
+
--status-ok: 160 84% 39%;
|
|
1407
|
+
}
|
|
1408
|
+
```
|
|
1409
|
+
|
|
1410
|
+
### Theme Toggle
|
|
1411
|
+
|
|
1412
|
+
```tsx
|
|
1413
|
+
function ThemeToggle() {
|
|
1414
|
+
const toggle = () => document.documentElement.classList.toggle('light')
|
|
1415
|
+
return <button onClick={toggle}>Toggle theme</button>
|
|
1416
|
+
}
|
|
1417
|
+
```
|
|
1418
|
+
|
|
1419
|
+
### Typography Scale
|
|
1420
|
+
|
|
1421
|
+
The theme CSS includes utility classes: `.text-display`, `.text-heading-1`, `.text-heading-2`, `.text-heading-3`, `.text-body`, `.text-small`, `.text-label`.
|
|
1422
|
+
|
|
1423
|
+
---
|
|
1424
|
+
|
|
1425
|
+
## CLI
|
|
1426
|
+
|
|
1427
|
+
Scaffold components directly into your project -- shadcn/ui-style.
|
|
1428
|
+
|
|
1429
|
+
### Initialize
|
|
1430
|
+
|
|
1431
|
+
```bash
|
|
1432
|
+
npx @annondeveloper/ui-kit init
|
|
1433
|
+
```
|
|
1434
|
+
|
|
1435
|
+
Copies `theme.css` and `utils.ts` into your target directory (default `./components/ui`).
|
|
1436
|
+
|
|
1437
|
+
### Add a Component
|
|
1438
|
+
|
|
1439
|
+
```bash
|
|
1440
|
+
npx @annondeveloper/ui-kit add button
|
|
1441
|
+
npx @annondeveloper/ui-kit add data-table
|
|
1442
|
+
npx @annondeveloper/ui-kit add metric-card
|
|
1443
|
+
```
|
|
1444
|
+
|
|
1445
|
+
Copies the component source file and resolves internal dependencies automatically.
|
|
1446
|
+
|
|
1447
|
+
### List Available Components
|
|
1448
|
+
|
|
1449
|
+
```bash
|
|
1450
|
+
npx @annondeveloper/ui-kit list
|
|
1451
|
+
```
|
|
1452
|
+
|
|
1453
|
+
### Options
|
|
1454
|
+
|
|
1455
|
+
| Flag | Description |
|
|
1456
|
+
|------|-------------|
|
|
1457
|
+
| `--dir <path>` | Target directory (default `./components/ui`) |
|
|
1458
|
+
| `--overwrite` | Overwrite existing files |
|
|
1459
|
+
|
|
1460
|
+
---
|
|
1461
|
+
|
|
1462
|
+
## Form Integration
|
|
1463
|
+
|
|
1464
|
+
Install the optional peer dependency:
|
|
1465
|
+
|
|
1466
|
+
```bash
|
|
1467
|
+
npm install react-hook-form
|
|
1468
|
+
```
|
|
1469
|
+
|
|
1470
|
+
Import from the dedicated entry point:
|
|
1471
|
+
|
|
1472
|
+
```tsx
|
|
1473
|
+
import { RHFFormInput, RHFSelect, RHFCheckbox, RHFToggleSwitch } from '@annondeveloper/ui-kit/form'
|
|
1474
|
+
```
|
|
1475
|
+
|
|
1476
|
+
### Example with Validation
|
|
1477
|
+
|
|
1478
|
+
```tsx
|
|
1479
|
+
import { useForm } from 'react-hook-form'
|
|
1480
|
+
import { RHFFormInput, RHFSelect } from '@annondeveloper/ui-kit/form'
|
|
1481
|
+
import { Button } from '@annondeveloper/ui-kit'
|
|
1482
|
+
|
|
1483
|
+
function CredentialForm() {
|
|
1484
|
+
const { control, handleSubmit } = useForm({
|
|
1485
|
+
defaultValues: { hostname: '', protocol: '' },
|
|
1486
|
+
})
|
|
1487
|
+
|
|
1488
|
+
return (
|
|
1489
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
1490
|
+
<RHFFormInput
|
|
1491
|
+
control={control} name="hostname" label="Hostname"
|
|
1492
|
+
rules={{ required: 'Hostname is required' }} placeholder="10.0.0.1"
|
|
1493
|
+
/>
|
|
1494
|
+
<RHFSelect
|
|
1495
|
+
control={control} name="protocol" label="Protocol"
|
|
1496
|
+
options={[{ value: 'snmp', label: 'SNMP' }, { value: 'ssh', label: 'SSH' }]}
|
|
1497
|
+
rules={{ required: 'Select a protocol' }}
|
|
1498
|
+
/>
|
|
1499
|
+
<Button type="submit" variant="primary">Save</Button>
|
|
1500
|
+
</form>
|
|
1501
|
+
)
|
|
1502
|
+
}
|
|
1503
|
+
```
|
|
1504
|
+
|
|
1505
|
+
All RHF wrappers automatically display validation errors from `fieldState.error`.
|
|
1506
|
+
|
|
1507
|
+
---
|
|
1508
|
+
|
|
1509
|
+
## Contributing
|
|
1510
|
+
|
|
1511
|
+
### Development Setup
|
|
1512
|
+
|
|
1513
|
+
```bash
|
|
1514
|
+
git clone https://github.com/annondeveloper/ui-kit.git
|
|
1515
|
+
cd ui-kit
|
|
1516
|
+
npm install
|
|
1517
|
+
npm run storybook # Component explorer at localhost:6006
|
|
1518
|
+
npm run test:watch # Vitest in watch mode
|
|
1519
|
+
npm run typecheck # TypeScript check
|
|
1520
|
+
```
|
|
1521
|
+
|
|
1522
|
+
### Running Tests
|
|
1523
|
+
|
|
1524
|
+
```bash
|
|
1525
|
+
npm test # Run all tests once
|
|
1526
|
+
npm run test:watch # Watch mode
|
|
1527
|
+
```
|
|
1528
|
+
|
|
1529
|
+
Tests use Vitest + Testing Library + jest-axe for accessibility.
|
|
1530
|
+
|
|
1531
|
+
### Adding a Component
|
|
1532
|
+
|
|
1533
|
+
1. Create `src/components/my-component.tsx` with the `'use client'` directive
|
|
1534
|
+
2. Export from `src/index.ts`
|
|
1535
|
+
3. Add to `src/cli/registry.ts` for CLI support
|
|
1536
|
+
4. Add a Storybook story in `src/components/my-component.stories.tsx`
|
|
1537
|
+
5. Add tests in `src/__tests__/my-component.test.tsx`
|
|
1538
|
+
6. Run `npm run typecheck && npm test` to verify
|
|
1539
|
+
|
|
1540
|
+
### Conventions
|
|
1541
|
+
|
|
1542
|
+
- All colors use `hsl(var(--token))` syntax -- never hardcoded hex values
|
|
1543
|
+
- All animations respect `useReducedMotion()` from Framer Motion
|
|
1544
|
+
- Components use `'use client'` directive for React Server Component compatibility
|
|
1545
|
+
- Types are exported alongside components for consumer use
|
|
1546
|
+
|
|
1547
|
+
---
|
|
1548
|
+
|
|
213
1549
|
## License
|
|
214
1550
|
|
|
215
|
-
MIT
|
|
1551
|
+
[MIT](./LICENSE)
|