harebear-ui 0.0.0-stage → 0.1.0
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/AGENTS.md +63 -0
- package/LICENSE +21 -0
- package/README.md +92 -2
- package/bin/harebear-ui.mjs +125 -0
- package/dist/components/admin/activity-feed.d.ts +15 -0
- package/dist/components/admin/activity-feed.js +50 -0
- package/dist/components/admin/app-shell.d.ts +47 -0
- package/dist/components/admin/app-shell.js +108 -0
- package/dist/components/admin/callout.d.ts +7 -0
- package/dist/components/admin/callout.js +18 -0
- package/dist/components/admin/key-value-grid.d.ts +11 -0
- package/dist/components/admin/key-value-grid.js +23 -0
- package/dist/components/admin/link-tile.d.ts +17 -0
- package/dist/components/admin/link-tile.js +36 -0
- package/dist/components/admin/page-header.d.ts +14 -0
- package/dist/components/admin/page-header.js +41 -0
- package/dist/components/admin/search-input.d.ts +12 -0
- package/dist/components/admin/search-input.js +32 -0
- package/dist/components/admin/stat-card.d.ts +20 -0
- package/dist/components/admin/stat-card.js +53 -0
- package/dist/components/admin/status.d.ts +12 -0
- package/dist/components/admin/status.js +32 -0
- package/dist/components/admin/timeline.d.ts +13 -0
- package/dist/components/admin/timeline.js +36 -0
- package/dist/components/admin/usage-meter.d.ts +17 -0
- package/dist/components/admin/usage-meter.js +43 -0
- package/dist/components/admin/user-chip.d.ts +14 -0
- package/dist/components/admin/user-chip.js +38 -0
- package/dist/components/ai/chat.d.ts +44 -0
- package/dist/components/ai/chat.js +147 -0
- package/dist/components/ai/code-block.d.ts +21 -0
- package/dist/components/ai/code-block.js +53 -0
- package/dist/components/ai/conversation-list.d.ts +18 -0
- package/dist/components/ai/conversation-list.js +30 -0
- package/dist/components/ai/model-picker.d.ts +21 -0
- package/dist/components/ai/model-picker.js +55 -0
- package/dist/components/ai/prompt-input.d.ts +27 -0
- package/dist/components/ai/prompt-input.js +99 -0
- package/dist/components/data/bar-list.d.ts +14 -0
- package/dist/components/data/bar-list.js +27 -0
- package/dist/components/data/data-table.d.ts +70 -0
- package/dist/components/data/data-table.js +208 -0
- package/dist/components/data/sparkline.d.ts +16 -0
- package/dist/components/data/sparkline.js +72 -0
- package/dist/components/data/status-bars.d.ts +17 -0
- package/dist/components/data/status-bars.js +37 -0
- package/dist/components/data/trend-chart.d.ts +31 -0
- package/dist/components/data/trend-chart.js +136 -0
- package/dist/components/theme/theme-provider.d.ts +42 -0
- package/dist/components/theme/theme-provider.js +110 -0
- package/dist/components/theme/theme-toggle.d.ts +5 -0
- package/dist/components/theme/theme-toggle.js +20 -0
- package/dist/components/ui/accordion.d.ts +7 -0
- package/dist/components/ui/accordion.js +53 -0
- package/dist/components/ui/alert-dialog.d.ts +18 -0
- package/dist/components/ui/alert-dialog.js +99 -0
- package/dist/components/ui/alert.d.ts +10 -0
- package/dist/components/ui/alert.js +42 -0
- package/dist/components/ui/aspect-ratio.d.ts +3 -0
- package/dist/components/ui/aspect-ratio.js +11 -0
- package/dist/components/ui/avatar.d.ts +11 -0
- package/dist/components/ui/avatar.js +49 -0
- package/dist/components/ui/badge.d.ts +9 -0
- package/dist/components/ui/badge.js +30 -0
- package/dist/components/ui/breadcrumb.d.ts +11 -0
- package/dist/components/ui/breadcrumb.js +70 -0
- package/dist/components/ui/button-group.d.ts +11 -0
- package/dist/components/ui/button-group.js +39 -0
- package/dist/components/ui/button.d.ts +11 -0
- package/dist/components/ui/button.js +55 -0
- package/dist/components/ui/calendar.d.ts +10 -0
- package/dist/components/ui/calendar.js +108 -0
- package/dist/components/ui/card.d.ts +11 -0
- package/dist/components/ui/card.js +55 -0
- package/dist/components/ui/carousel.d.ts +28 -0
- package/dist/components/ui/carousel.js +131 -0
- package/dist/components/ui/chart.d.ts +44 -0
- package/dist/components/ui/chart.js +148 -0
- package/dist/components/ui/checkbox.d.ts +4 -0
- package/dist/components/ui/checkbox.js +19 -0
- package/dist/components/ui/collapsible.d.ts +5 -0
- package/dist/components/ui/collapsible.js +23 -0
- package/dist/components/ui/command.d.ts +18 -0
- package/dist/components/ui/command.js +86 -0
- package/dist/components/ui/context-menu.d.ts +31 -0
- package/dist/components/ui/context-menu.js +123 -0
- package/dist/components/ui/dialog.d.ts +17 -0
- package/dist/components/ui/dialog.js +94 -0
- package/dist/components/ui/drawer.d.ts +13 -0
- package/dist/components/ui/drawer.js +76 -0
- package/dist/components/ui/dropdown-menu.d.ts +29 -0
- package/dist/components/ui/dropdown-menu.js +126 -0
- package/dist/components/ui/empty.d.ts +11 -0
- package/dist/components/ui/empty.js +59 -0
- package/dist/components/ui/field.d.ts +24 -0
- package/dist/components/ui/field.js +109 -0
- package/dist/components/ui/hover-card.d.ts +6 -0
- package/dist/components/ui/hover-card.js +30 -0
- package/dist/components/ui/input-group.d.ts +16 -0
- package/dist/components/ui/input-group.js +77 -0
- package/dist/components/ui/input-otp.d.ts +11 -0
- package/dist/components/ui/input-otp.js +46 -0
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/input.js +13 -0
- package/dist/components/ui/item.d.ts +23 -0
- package/dist/components/ui/item.js +117 -0
- package/dist/components/ui/kbd.d.ts +3 -0
- package/dist/components/ui/kbd.js +19 -0
- package/dist/components/ui/label.d.ts +4 -0
- package/dist/components/ui/label.js +13 -0
- package/dist/components/ui/menubar.d.ts +30 -0
- package/dist/components/ui/menubar.js +133 -0
- package/dist/components/ui/navigation-menu.d.ts +14 -0
- package/dist/components/ui/navigation-menu.js +79 -0
- package/dist/components/ui/pagination.d.ts +17 -0
- package/dist/components/ui/pagination.js +79 -0
- package/dist/components/ui/popover.d.ts +10 -0
- package/dist/components/ui/popover.js +54 -0
- package/dist/components/ui/progress.d.ts +4 -0
- package/dist/components/ui/progress.js +18 -0
- package/dist/components/ui/radio-group.d.ts +5 -0
- package/dist/components/ui/radio-group.js +25 -0
- package/dist/components/ui/resizable.d.ts +7 -0
- package/dist/components/ui/resizable.js +27 -0
- package/dist/components/ui/scroll-area.d.ts +5 -0
- package/dist/components/ui/scroll-area.js +35 -0
- package/dist/components/ui/select.d.ts +15 -0
- package/dist/components/ui/select.js +98 -0
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/components/ui/separator.js +15 -0
- package/dist/components/ui/sheet.d.ts +14 -0
- package/dist/components/ui/sheet.js +88 -0
- package/dist/components/ui/sidebar.d.ts +69 -0
- package/dist/components/ui/sidebar.js +377 -0
- package/dist/components/ui/skeleton.d.ts +2 -0
- package/dist/components/ui/skeleton.js +12 -0
- package/dist/components/ui/slider.d.ts +4 -0
- package/dist/components/ui/slider.js +35 -0
- package/dist/components/ui/sonner.d.ts +3 -0
- package/dist/components/ui/sonner.js +29 -0
- package/dist/components/ui/spinner.d.ts +2 -0
- package/dist/components/ui/spinner.js +15 -0
- package/dist/components/ui/switch.d.ts +6 -0
- package/dist/components/ui/switch.js +18 -0
- package/dist/components/ui/table.d.ts +10 -0
- package/dist/components/ui/table.js +65 -0
- package/dist/components/ui/tabs.d.ts +11 -0
- package/dist/components/ui/tabs.js +45 -0
- package/dist/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/textarea.js +12 -0
- package/dist/components/ui/toggle-group.d.ts +10 -0
- package/dist/components/ui/toggle-group.js +50 -0
- package/dist/components/ui/toggle.d.ts +9 -0
- package/dist/components/ui/toggle.js +35 -0
- package/dist/components/ui/tooltip.d.ts +7 -0
- package/dist/components/ui/tooltip.js +34 -0
- package/dist/hooks/use-copy-to-clipboard.d.ts +5 -0
- package/dist/hooks/use-copy-to-clipboard.js +24 -0
- package/dist/hooks/use-mobile.d.ts +1 -0
- package/dist/hooks/use-mobile.js +17 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.js +80 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.js +8 -0
- package/dist/shadcn-base.css +638 -0
- package/dist/styles.css +188 -0
- package/docs/COMPONENTS.md +352 -0
- package/llms.txt +34 -0
- package/package.json +116 -4
- package/skills/harebear-ui/SKILL.md +33 -0
package/dist/styles.css
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* harebear-ui theme.
|
|
3
|
+
*
|
|
4
|
+
* Usage in an app (Tailwind CSS v4):
|
|
5
|
+
* @import "tailwindcss";
|
|
6
|
+
* @import "harebear-ui/styles.css";
|
|
7
|
+
*
|
|
8
|
+
* Every component reads the shadcn token names below. To rebrand, override
|
|
9
|
+
* --brand (accent), --radius, or any token on :root / .dark in your own CSS,
|
|
10
|
+
* or pass props to <ThemeProvider>.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
@import "tw-animate-css";
|
|
14
|
+
@import "@fontsource-variable/geist";
|
|
15
|
+
@import "@fontsource-variable/geist-mono";
|
|
16
|
+
@import "./shadcn-base.css";
|
|
17
|
+
|
|
18
|
+
/* Let the consumer's Tailwind scan this package's compiled components. */
|
|
19
|
+
@source "./";
|
|
20
|
+
|
|
21
|
+
@custom-variant dark (&:where(.dark, .dark *));
|
|
22
|
+
|
|
23
|
+
@theme inline {
|
|
24
|
+
--font-sans: var(--hb-font-sans);
|
|
25
|
+
--font-heading: var(--hb-font-sans);
|
|
26
|
+
--font-mono: var(--hb-font-mono);
|
|
27
|
+
|
|
28
|
+
--color-background: var(--background);
|
|
29
|
+
--color-foreground: var(--foreground);
|
|
30
|
+
--color-card: var(--card);
|
|
31
|
+
--color-card-foreground: var(--card-foreground);
|
|
32
|
+
--color-popover: var(--popover);
|
|
33
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
34
|
+
--color-primary: var(--primary);
|
|
35
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
36
|
+
--color-primary-soft: var(--primary-soft);
|
|
37
|
+
--color-secondary: var(--secondary);
|
|
38
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
39
|
+
--color-muted: var(--muted);
|
|
40
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
41
|
+
--color-accent: var(--accent);
|
|
42
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
43
|
+
--color-destructive: var(--destructive);
|
|
44
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
45
|
+
--color-success: var(--success);
|
|
46
|
+
--color-warning: var(--warning);
|
|
47
|
+
--color-border: var(--border);
|
|
48
|
+
--color-input: var(--input);
|
|
49
|
+
--color-ring: var(--ring);
|
|
50
|
+
--color-chart-1: var(--chart-1);
|
|
51
|
+
--color-chart-2: var(--chart-2);
|
|
52
|
+
--color-chart-3: var(--chart-3);
|
|
53
|
+
--color-chart-4: var(--chart-4);
|
|
54
|
+
--color-chart-5: var(--chart-5);
|
|
55
|
+
--color-chart-grid: var(--chart-grid);
|
|
56
|
+
--color-sidebar: var(--sidebar);
|
|
57
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
58
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
59
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
60
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
61
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
62
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
63
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
64
|
+
|
|
65
|
+
--radius-sm: calc(var(--radius) * 0.55);
|
|
66
|
+
--radius-md: calc(var(--radius) * 0.8);
|
|
67
|
+
--radius-lg: var(--radius);
|
|
68
|
+
--radius-xl: calc(var(--radius) * 1.35);
|
|
69
|
+
--radius-2xl: calc(var(--radius) * 1.8);
|
|
70
|
+
--radius-3xl: calc(var(--radius) * 2.2);
|
|
71
|
+
--radius-4xl: calc(var(--radius) * 2.6);
|
|
72
|
+
|
|
73
|
+
--shadow-card: var(--elevation);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
:root {
|
|
77
|
+
/* Brand levers. ThemeProvider writes these at runtime. */
|
|
78
|
+
--brand: #2f5bd3;
|
|
79
|
+
--radius: 0.875rem;
|
|
80
|
+
--hb-font-sans: "Geist Variable", "Geist", ui-sans-serif, system-ui, sans-serif;
|
|
81
|
+
--hb-font-mono: "Geist Mono Variable", "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
82
|
+
|
|
83
|
+
--background: #f7f7f8;
|
|
84
|
+
--foreground: #18181b;
|
|
85
|
+
--card: #ffffff;
|
|
86
|
+
--card-foreground: #18181b;
|
|
87
|
+
--popover: #ffffff;
|
|
88
|
+
--popover-foreground: #18181b;
|
|
89
|
+
--primary: var(--brand);
|
|
90
|
+
--primary-foreground: #ffffff;
|
|
91
|
+
--primary-soft: color-mix(in oklab, var(--primary) 10%, var(--card));
|
|
92
|
+
--secondary: #f1f1f3;
|
|
93
|
+
--secondary-foreground: #18181b;
|
|
94
|
+
--muted: #f1f1f3;
|
|
95
|
+
--muted-foreground: #63636b;
|
|
96
|
+
--accent: #f1f1f3;
|
|
97
|
+
--accent-foreground: #18181b;
|
|
98
|
+
--destructive: #c2410c;
|
|
99
|
+
--destructive-foreground: #ffffff;
|
|
100
|
+
--success: #1e8a4c;
|
|
101
|
+
--warning: #b26a00;
|
|
102
|
+
--border: #e6e6e9;
|
|
103
|
+
--input: #e6e6e9;
|
|
104
|
+
--ring: var(--primary);
|
|
105
|
+
--chart-1: var(--primary);
|
|
106
|
+
--chart-2: #8a8a93;
|
|
107
|
+
--chart-3: #c2702a;
|
|
108
|
+
--chart-4: #0f8a7e;
|
|
109
|
+
--chart-5: #8b5cc9;
|
|
110
|
+
--chart-grid: #eeeef0;
|
|
111
|
+
--elevation: 0 1px 2px rgb(24 24 27 / 0.04), 0 6px 20px rgb(24 24 27 / 0.05);
|
|
112
|
+
|
|
113
|
+
--sidebar: var(--background);
|
|
114
|
+
--sidebar-foreground: var(--foreground);
|
|
115
|
+
--sidebar-primary: var(--primary);
|
|
116
|
+
--sidebar-primary-foreground: var(--primary-foreground);
|
|
117
|
+
--sidebar-accent: var(--muted);
|
|
118
|
+
--sidebar-accent-foreground: var(--foreground);
|
|
119
|
+
--sidebar-border: var(--border);
|
|
120
|
+
--sidebar-ring: var(--ring);
|
|
121
|
+
|
|
122
|
+
color-scheme: light;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.dark {
|
|
126
|
+
--background: #101012;
|
|
127
|
+
--foreground: #ededef;
|
|
128
|
+
--card: #18181b;
|
|
129
|
+
--card-foreground: #ededef;
|
|
130
|
+
--popover: #18181b;
|
|
131
|
+
--popover-foreground: #ededef;
|
|
132
|
+
--primary: color-mix(in oklab, var(--brand), white 26%);
|
|
133
|
+
--primary-foreground: #0b1020;
|
|
134
|
+
--primary-soft: color-mix(in oklab, var(--primary) 15%, var(--card));
|
|
135
|
+
--secondary: #232326;
|
|
136
|
+
--secondary-foreground: #ededef;
|
|
137
|
+
--muted: #232326;
|
|
138
|
+
--muted-foreground: #9d9da5;
|
|
139
|
+
--accent: #232326;
|
|
140
|
+
--accent-foreground: #ededef;
|
|
141
|
+
--destructive: #f07a50;
|
|
142
|
+
--destructive-foreground: #18181b;
|
|
143
|
+
--success: #4cc38a;
|
|
144
|
+
--warning: #e5a23a;
|
|
145
|
+
--border: #2a2a2e;
|
|
146
|
+
--input: #2a2a2e;
|
|
147
|
+
--chart-2: #8b8b94;
|
|
148
|
+
--chart-3: #c9772b;
|
|
149
|
+
--chart-4: #3cb8a8;
|
|
150
|
+
--chart-5: #a98ae0;
|
|
151
|
+
--chart-grid: #242427;
|
|
152
|
+
--elevation: 0 1px 2px rgb(0 0 0 / 0.3), 0 8px 24px rgb(0 0 0 / 0.22);
|
|
153
|
+
|
|
154
|
+
color-scheme: dark;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@layer base {
|
|
158
|
+
* {
|
|
159
|
+
@apply border-border outline-ring/50;
|
|
160
|
+
}
|
|
161
|
+
html {
|
|
162
|
+
@apply font-sans;
|
|
163
|
+
}
|
|
164
|
+
body {
|
|
165
|
+
@apply bg-background text-foreground antialiased;
|
|
166
|
+
font-size: 14px;
|
|
167
|
+
line-height: 1.5;
|
|
168
|
+
}
|
|
169
|
+
button:not(:disabled),
|
|
170
|
+
[role="button"]:not(:disabled) {
|
|
171
|
+
cursor: pointer;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@keyframes hb-typing {
|
|
176
|
+
0%,
|
|
177
|
+
80%,
|
|
178
|
+
100% {
|
|
179
|
+
opacity: 0.25;
|
|
180
|
+
}
|
|
181
|
+
40% {
|
|
182
|
+
opacity: 1;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
@utility animate-typing {
|
|
187
|
+
animation: hb-typing 1.2s infinite ease-in-out;
|
|
188
|
+
}
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
# harebear-ui component catalog
|
|
2
|
+
|
|
3
|
+
Every export, what it is for, and the props that matter. All components import from the package root:
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Button, Card, DataTable, ChatMessage } from "harebear-ui"
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Full working screens that combine these live in the repo under `playground/screens/` (admin dashboard, AI chat, data table with detail panel, status home page). Copy from them.
|
|
10
|
+
|
|
11
|
+
## Rules of thumb
|
|
12
|
+
|
|
13
|
+
- **shadcn-compatible.** Primitives keep shadcn/ui names, parts, and props. If you know shadcn, you know these. Only the styling (and a few added variants) differ.
|
|
14
|
+
- **Style with tokens, not colors.** Use `bg-card`, `text-muted-foreground`, `bg-primary-soft`, `text-success`, `shadow-card`, `rounded-xl`. Never hard-code hex values or Tailwind palette colors (`bg-blue-500`). See [Tokens](#tokens).
|
|
15
|
+
- **Compose, don't fork.** Every component accepts `className` (merged with `cn`, later classes win). Reach for a primitive before writing a new component.
|
|
16
|
+
- **Icons are lucide-react elements.** Pass `<SearchIcon />`, not the component. Buttons size icons automatically.
|
|
17
|
+
- **Status uses tones**, not colors: `"success" | "warning" | "danger" | "info" | "neutral"`.
|
|
18
|
+
|
|
19
|
+
## Theme
|
|
20
|
+
|
|
21
|
+
| Export | Use |
|
|
22
|
+
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
23
|
+
| `ThemeProvider` | Wrap the app once. Props: `defaultMode` (`"light" \| "dark" \| "system"`, default `"system"`), `accent` (CSS color, drives primary), `radius` (px, default 14), `font` (family name; Geist is bundled), `storageKey` (default `"harebear-theme"`, `null` disables persistence). |
|
|
24
|
+
| `useTheme` | `{ mode, resolvedMode, setMode, toggleMode, accent, setAccent, radius, setRadius }`. Safe outside a provider. |
|
|
25
|
+
| `ThemeToggle` | Ghost icon button that flips light/dark. Accepts Button props. |
|
|
26
|
+
| `ThemeScript` | For SSR (Next.js, Remix): render in `<head>` to set `.dark` before paint and avoid a flash. Props: `storageKey`, `defaultMode`. |
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
;<ThemeProvider accent="#2F5BD3" radius={14}>
|
|
30
|
+
<TooltipProvider>
|
|
31
|
+
<App />
|
|
32
|
+
<Toaster />
|
|
33
|
+
</TooltipProvider>
|
|
34
|
+
</ThemeProvider>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Primitives (shadcn/ui, restyled)
|
|
38
|
+
|
|
39
|
+
These are the shadcn/ui `radix-nova` components, restyled to the harebear tokens. API docs: https://ui.shadcn.com/docs/components. harebear-specific changes are noted.
|
|
40
|
+
|
|
41
|
+
| Family | Exports | harebear notes |
|
|
42
|
+
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
43
|
+
| Accordion | `Accordion`, `AccordionItem`, `AccordionTrigger`, `AccordionContent` | |
|
|
44
|
+
| Alert | `Alert`, `AlertTitle`, `AlertDescription`, `AlertAction` | |
|
|
45
|
+
| Alert dialog | `AlertDialog`, `AlertDialogTrigger`, `AlertDialogContent`, `AlertDialogHeader`, `AlertDialogFooter`, `AlertDialogTitle`, `AlertDialogDescription`, `AlertDialogAction`, `AlertDialogCancel`, `AlertDialogMedia`, `AlertDialogOverlay`, `AlertDialogPortal` | Use for destructive confirmations. |
|
|
46
|
+
| Aspect ratio | `AspectRatio` | |
|
|
47
|
+
| Avatar | `Avatar`, `AvatarImage`, `AvatarFallback`, `AvatarGroup`, `AvatarGroupCount`, `AvatarBadge` | `size`: `sm` 28px, `default` 36px, `lg` 56px. Fallback is tinted initials. |
|
|
48
|
+
| Badge | `Badge`, `badgeVariants` | 24px pill. `variant`: `default` (primary), `secondary` (neutral, the common one), `soft` (tinted primary), `outline`, `success`, `warning`, `destructive`, `ghost`, `link`. |
|
|
49
|
+
| Breadcrumb | `Breadcrumb`, `BreadcrumbList`, `BreadcrumbItem`, `BreadcrumbLink`, `BreadcrumbPage`, `BreadcrumbSeparator`, `BreadcrumbEllipsis` | |
|
|
50
|
+
| Button | `Button`, `buttonVariants` | 40px default. `variant`: `default`, `secondary`, `outline`, `ghost`, `soft`, `dashed`, `destructive`, `link`. `size`: `xs`, `sm` (32px), `default`, `lg`, `icon`, `icon-xs`, `icon-sm`, `icon-lg`. `shape`: `default`, `pill`. Icon-only buttons need `aria-label`. |
|
|
51
|
+
| Button group | `ButtonGroup`, `ButtonGroupSeparator`, `ButtonGroupText`, `buttonGroupVariants` | |
|
|
52
|
+
| Calendar | `Calendar`, `CalendarDayButton` | react-day-picker v10. Combine with `Popover` for a date picker. |
|
|
53
|
+
| Card | `Card`, `CardHeader`, `CardTitle`, `CardDescription`, `CardAction`, `CardContent`, `CardFooter` | Bordered, elevated (`shadow-card`), `rounded-xl`, 24px padding. `size="sm"` for 16px. `CardAction` puts a control top-right of the header. |
|
|
54
|
+
| Carousel | `Carousel`, `CarouselContent`, `CarouselItem`, `CarouselPrevious`, `CarouselNext`, `useCarousel`, type `CarouselApi` | embla. |
|
|
55
|
+
| Chart | `ChartContainer`, `ChartTooltip`, `ChartTooltipContent`, `ChartLegend`, `ChartLegendContent`, `ChartStyle` | Recharts wrappers. Prefer `TrendChart` for line/area; use these for custom charts. |
|
|
56
|
+
| Checkbox | `Checkbox` | |
|
|
57
|
+
| Collapsible | `Collapsible`, `CollapsibleTrigger`, `CollapsibleContent` | |
|
|
58
|
+
| Command | `Command`, `CommandDialog`, `CommandInput`, `CommandList`, `CommandEmpty`, `CommandGroup`, `CommandItem`, `CommandShortcut`, `CommandSeparator` | Use for ⌘K palettes. |
|
|
59
|
+
| Context menu | `ContextMenu`, `ContextMenuTrigger`, `ContextMenuContent`, `ContextMenuItem`, `ContextMenuCheckboxItem`, `ContextMenuRadioItem`, `ContextMenuRadioGroup`, `ContextMenuLabel`, `ContextMenuSeparator`, `ContextMenuShortcut`, `ContextMenuGroup`, `ContextMenuPortal`, `ContextMenuSub`, `ContextMenuSubContent`, `ContextMenuSubTrigger` | |
|
|
60
|
+
| Dialog | `Dialog`, `DialogTrigger`, `DialogContent`, `DialogHeader`, `DialogFooter`, `DialogTitle`, `DialogDescription`, `DialogClose`, `DialogOverlay`, `DialogPortal` | |
|
|
61
|
+
| Drawer | `Drawer`, `DrawerTrigger`, `DrawerContent`, `DrawerHeader`, `DrawerFooter`, `DrawerTitle`, `DrawerDescription`, `DrawerClose`, `DrawerOverlay`, `DrawerPortal` | vaul. Mobile bottom sheets. |
|
|
62
|
+
| Dropdown menu | `DropdownMenu`, `DropdownMenuTrigger`, `DropdownMenuContent`, `DropdownMenuItem`, `DropdownMenuCheckboxItem`, `DropdownMenuRadioGroup`, `DropdownMenuRadioItem`, `DropdownMenuLabel`, `DropdownMenuSeparator`, `DropdownMenuShortcut`, `DropdownMenuGroup`, `DropdownMenuPortal`, `DropdownMenuSub`, `DropdownMenuSubTrigger`, `DropdownMenuSubContent` | |
|
|
63
|
+
| Empty state | `Empty`, `EmptyHeader`, `EmptyMedia`, `EmptyTitle`, `EmptyDescription`, `EmptyContent` | Use for zero-data screens. |
|
|
64
|
+
| Field | `Field`, `FieldLabel`, `FieldDescription`, `FieldError`, `FieldGroup`, `FieldLegend`, `FieldSeparator`, `FieldSet`, `FieldContent`, `FieldTitle` | Form layout. Works with react-hook-form or plain state. |
|
|
65
|
+
| Hover card | `HoverCard`, `HoverCardTrigger`, `HoverCardContent` | |
|
|
66
|
+
| Input | `Input` | 40px, filled `bg-muted`, turns `bg-card` with a primary ring on focus. |
|
|
67
|
+
| Input group | `InputGroup`, `InputGroupAddon`, `InputGroupButton`, `InputGroupText`, `InputGroupInput`, `InputGroupTextarea` | Inputs with icons, prefixes, buttons. |
|
|
68
|
+
| Input OTP | `InputOTP`, `InputOTPGroup`, `InputOTPSlot`, `InputOTPSeparator` | |
|
|
69
|
+
| Item | `Item`, `ItemMedia`, `ItemContent`, `ItemTitle`, `ItemDescription`, `ItemActions`, `ItemGroup`, `ItemSeparator`, `ItemHeader`, `ItemFooter` | Generic list rows. |
|
|
70
|
+
| Kbd | `Kbd`, `KbdGroup` | Mono keycap. |
|
|
71
|
+
| Label | `Label` | |
|
|
72
|
+
| Menubar | `Menubar`, `MenubarMenu`, `MenubarTrigger`, `MenubarContent`, `MenubarItem`, `MenubarCheckboxItem`, `MenubarRadioGroup`, `MenubarRadioItem`, `MenubarLabel`, `MenubarSeparator`, `MenubarShortcut`, `MenubarGroup`, `MenubarPortal`, `MenubarSub`, `MenubarSubTrigger`, `MenubarSubContent` | |
|
|
73
|
+
| Navigation menu | `NavigationMenu`, `NavigationMenuList`, `NavigationMenuItem`, `NavigationMenuTrigger`, `NavigationMenuContent`, `NavigationMenuLink`, `NavigationMenuIndicator`, `NavigationMenuViewport`, `navigationMenuTriggerStyle` | Marketing-style top nav. |
|
|
74
|
+
| Pagination | `Pagination`, `PaginationContent`, `PaginationItem`, `PaginationLink`, `PaginationPrevious`, `PaginationNext`, `PaginationEllipsis` | `DataTable` has its own pager. |
|
|
75
|
+
| Popover | `Popover`, `PopoverTrigger`, `PopoverContent`, `PopoverAnchor`, `PopoverHeader`, `PopoverTitle`, `PopoverDescription` | |
|
|
76
|
+
| Progress | `Progress` | 8px rounded meter. `UsageMeter` adds a label row. |
|
|
77
|
+
| Radio group | `RadioGroup`, `RadioGroupItem` | |
|
|
78
|
+
| Resizable | `ResizablePanelGroup`, `ResizablePanel`, `ResizableHandle` | |
|
|
79
|
+
| Scroll area | `ScrollArea`, `ScrollBar` | |
|
|
80
|
+
| Select | `Select`, `SelectTrigger`, `SelectValue`, `SelectContent`, `SelectItem`, `SelectGroup`, `SelectLabel`, `SelectSeparator`, `SelectScrollUpButton`, `SelectScrollDownButton` | |
|
|
81
|
+
| Separator | `Separator` | |
|
|
82
|
+
| Sheet | `Sheet`, `SheetTrigger`, `SheetContent`, `SheetHeader`, `SheetFooter`, `SheetTitle`, `SheetDescription`, `SheetClose` | Side panels. |
|
|
83
|
+
| Sidebar | `SidebarProvider`, `Sidebar`, `SidebarHeader`, `SidebarContent`, `SidebarFooter`, `SidebarGroup`, `SidebarGroupLabel`, `SidebarGroupAction`, `SidebarGroupContent`, `SidebarMenu`, `SidebarMenuItem`, `SidebarMenuButton`, `SidebarMenuAction`, `SidebarMenuBadge`, `SidebarMenuSkeleton`, `SidebarMenuSub`, `SidebarMenuSubItem`, `SidebarMenuSubButton`, `SidebarInput`, `SidebarInset`, `SidebarRail`, `SidebarSeparator`, `SidebarTrigger`, `useSidebar` | Active item is a raised card. Prefer `AppShell` unless you need a custom layout. |
|
|
84
|
+
| Skeleton | `Skeleton` | Loading placeholders. |
|
|
85
|
+
| Slider | `Slider` | |
|
|
86
|
+
| Spinner | `Spinner` | |
|
|
87
|
+
| Switch | `Switch` | |
|
|
88
|
+
| Table | `Table`, `TableHeader`, `TableBody`, `TableFooter`, `TableRow`, `TableHead`, `TableCell`, `TableCaption` | Borderless rows with rounded hover; quiet 12px headers. `data-state="selected"` tints a row. |
|
|
89
|
+
| Tabs | `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent`, `tabsListVariants` | `TabsList variant`: `default` (segmented control), `pill` (rounded top-level nav), `line`. Use `Tabs` as a segmented filter too (date ranges, status filters). |
|
|
90
|
+
| Textarea | `Textarea` | Same filled style as `Input`, auto-grows. |
|
|
91
|
+
| Toast | `Toaster` | sonner. Mount once; call `toast("Saved")` from `sonner`. Follows the theme mode. |
|
|
92
|
+
| Toggle | `Toggle`, `toggleVariants`, `ToggleGroup`, `ToggleGroupItem` | |
|
|
93
|
+
| Tooltip | `TooltipProvider`, `Tooltip`, `TooltipTrigger`, `TooltipContent` | Mount `TooltipProvider` once near the root. |
|
|
94
|
+
|
|
95
|
+
## Admin and layout
|
|
96
|
+
|
|
97
|
+
### `AppShell`
|
|
98
|
+
|
|
99
|
+
Full app layout: collapsible sidebar (a sheet on mobile) plus a main column with a top bar.
|
|
100
|
+
|
|
101
|
+
Props: `brand` (node, usually `AppBrand`), `nav: AppNavSection[]`, `sidebarExtra` (node under the nav), `sidebarFooter` (node, usually `UserChip`), `header` (top bar content), `linkComponent` (e.g. Next.js `Link`; default `"a"`), `defaultOpen`, `children` (page content, laid out in a column with 28px gaps).
|
|
102
|
+
|
|
103
|
+
`AppNavSection = { label?: string; items: AppNavItem[] }`
|
|
104
|
+
`AppNavItem = { label: string; icon?: ReactNode; href?: string; onSelect?: () => void; active?: boolean; badge?: ReactNode }`
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
;<AppShell
|
|
108
|
+
brand={<AppBrand name="Console" subtitle="Personal workspace" icon={<SparklesIcon />} />}
|
|
109
|
+
nav={[
|
|
110
|
+
{
|
|
111
|
+
label: "Workspace",
|
|
112
|
+
items: [
|
|
113
|
+
{ label: "Overview", icon: <LayoutDashboardIcon />, href: "/", active: true },
|
|
114
|
+
{ label: "Orders", icon: <ShoppingBagIcon />, href: "/orders", badge: 12 },
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
]}
|
|
118
|
+
sidebarFooter={<UserChip name="Harrison M" subtitle="Owner" />}
|
|
119
|
+
header={
|
|
120
|
+
<>
|
|
121
|
+
<SearchInput placeholder="Search anything" shortcut="⌘K" wrapperClassName="flex-[0_1_380px]" />
|
|
122
|
+
<div className="flex-1" />
|
|
123
|
+
<ThemeToggle />
|
|
124
|
+
</>
|
|
125
|
+
}
|
|
126
|
+
linkComponent={Link}
|
|
127
|
+
>
|
|
128
|
+
<PageHeader title="Overview" description="Last 30 days." actions={<Button>New report</Button>} />
|
|
129
|
+
...
|
|
130
|
+
</AppShell>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `AppBrand`
|
|
134
|
+
|
|
135
|
+
Logo tile + name. Props: `name`, `subtitle?`, `icon?`, `action?` (trailing control).
|
|
136
|
+
|
|
137
|
+
### `PageHeader`
|
|
138
|
+
|
|
139
|
+
Title row. Props: `title`, `description?`, `count?` (badge after title), `eyebrow?` (small text above), `actions?` (right side, wraps on mobile).
|
|
140
|
+
|
|
141
|
+
### `StatCard`
|
|
142
|
+
|
|
143
|
+
KPI tile. Props: `label`, `value`, `delta?` ("12.4%"), `trend?` (`"up" | "down"`, default up), `positive?` (good/bad color; defaults to `trend === "up"`, so set `positive` for "latency went down"), `note?` ("vs last month"), `icon?`, `data?: number[]` (sparkline).
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
;<div className="grid grid-cols-[repeat(auto-fit,minmax(220px,1fr))] gap-5">
|
|
147
|
+
<StatCard
|
|
148
|
+
label="Revenue"
|
|
149
|
+
value="$48,210"
|
|
150
|
+
delta="12.4%"
|
|
151
|
+
note="vs last month"
|
|
152
|
+
icon={<DollarSignIcon />}
|
|
153
|
+
data={revenue}
|
|
154
|
+
/>
|
|
155
|
+
<StatCard label="Avg. response" value="182 ms" delta="18 ms" trend="down" positive note="faster" icon={<ZapIcon />} />
|
|
156
|
+
</div>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `SearchInput`
|
|
160
|
+
|
|
161
|
+
Search field with icon. Props: all `<input>` props, `shortcut?` (display-only key hint like `"⌘K"`), `size?` (`"default"` or `"lg"` hero pill), `wrapperClassName?` (size/flex the wrapper).
|
|
162
|
+
|
|
163
|
+
### `StatusDot`, `StatusBadge`
|
|
164
|
+
|
|
165
|
+
Dot or pill for status. Prop `tone`: `success | warning | danger | info | neutral`. `StatusBadge` takes Badge props (`variant="outline"` for a white pill).
|
|
166
|
+
|
|
167
|
+
### `UsageMeter`
|
|
168
|
+
|
|
169
|
+
Label + value over a bar. Props: `label`, `percent` (0-100, clamped), `value?` (bold), `detail?` (muted), `color?` (CSS color, e.g. `"var(--warning)"`), `trackClassName?`.
|
|
170
|
+
|
|
171
|
+
### `ActivityFeed`
|
|
172
|
+
|
|
173
|
+
Props: `items: { actor; action; target?; time; avatarUrl?; id? }[]`. Renders "**Maya** commented on **Q4 roadmap**".
|
|
174
|
+
|
|
175
|
+
### `Timeline`
|
|
176
|
+
|
|
177
|
+
Vertical events with a rail. Props: `items: { title; time; tone?; id? }[]`.
|
|
178
|
+
|
|
179
|
+
### `KeyValueGrid`
|
|
180
|
+
|
|
181
|
+
Label-over-value pairs as a `<dl>`. Props: `items: { label; value }[]`, `columns?: 1 | 2 | 3`.
|
|
182
|
+
|
|
183
|
+
### `UserChip`
|
|
184
|
+
|
|
185
|
+
Avatar + name + subtitle. Props: `name`, `subtitle?`, `avatarUrl?`, `action?`, `size?`. Also exports `initials(name)`.
|
|
186
|
+
|
|
187
|
+
### `Callout`
|
|
188
|
+
|
|
189
|
+
Quiet note with an icon (sparkle by default). Props: `icon?`, `tone?` (`"muted" | "soft"`).
|
|
190
|
+
|
|
191
|
+
### `LinkTile`
|
|
192
|
+
|
|
193
|
+
Muted tile that lifts on hover, for service launchers. Props: `title`, `subtitle?` (mono), `icon?`, `status?: { tone; label }`, `href`, or `asChild` with your router `<Link>` as the only child.
|
|
194
|
+
|
|
195
|
+
## Data display
|
|
196
|
+
|
|
197
|
+
### `DataTable`
|
|
198
|
+
|
|
199
|
+
Client-side table with search, sorting, row selection, pagination (TanStack Table v9).
|
|
200
|
+
|
|
201
|
+
Props: `columns`, `data`, `getRowId?` (needed for selection/active row), `searchable?`, `searchPlaceholder?`, `toolbar?` (controls after the search box), `selectable?`, `onSelectionChange?(rows)`, `onRowClick?(row)`, `activeRowId?` (highlight the row open in a detail panel), `pageSize?` (default 10, `0` = no pagination), `emptyMessage?`.
|
|
202
|
+
|
|
203
|
+
Define columns with the typed helper, at module scope (stable references matter):
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
import { createDataTableColumnHelper, DataTable, StatusBadge } from "harebear-ui"
|
|
207
|
+
|
|
208
|
+
type Customer = { id: string; name: string; status: "Active" | "Trial"; mrr: number }
|
|
209
|
+
const col = createDataTableColumnHelper<Customer>()
|
|
210
|
+
const columns = col.columns([
|
|
211
|
+
col.accessor("name", { header: "Name" }),
|
|
212
|
+
col.accessor("status", { header: "Status", cell: ({ getValue }) => <StatusBadge tone="success">{getValue()}</StatusBadge> }),
|
|
213
|
+
col.accessor("mrr", { header: "MRR", meta: { align: "right" }, cell: ({ getValue }) => `$${getValue()}` }),
|
|
214
|
+
])
|
|
215
|
+
|
|
216
|
+
<DataTable columns={columns} data={customers} getRowId={(r) => r.id} searchable selectable onRowClick={open} />
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
`meta: { align: "right" }` right-aligns a column. `enableSorting: false` turns sorting off for one column. For server-side data, build with `useTable` from `@tanstack/react-table` and the `Table` primitives; `dataTableFeatures` is exported if you want the same feature set.
|
|
220
|
+
|
|
221
|
+
Related exports: `createDataTableColumnHelper`, `dataTableFeatures`, types `DataTableColumnDef`, `DataTableFeatures`, `DataTableProps`.
|
|
222
|
+
|
|
223
|
+
### `TrendChart`, `TrendLegend`
|
|
224
|
+
|
|
225
|
+
Smoothed area chart with grid, axes and tooltip. Props: `data` (rows), `xKey`, `series: { key; label; color?; dashed? }[]` (dashed = comparison line, no fill), `height?` (default 240), `valueFormatter?`, `xFormatter?`, `hideYAxis?`. Colors default to `chart-1..5`. `TrendLegend` takes the same `series` and renders a matching legend (put it in `CardAction`).
|
|
226
|
+
|
|
227
|
+
### `BarList`
|
|
228
|
+
|
|
229
|
+
Ranked bars. Props: `items: { label; percent; value?; color? }[]`.
|
|
230
|
+
|
|
231
|
+
### `Sparkline`
|
|
232
|
+
|
|
233
|
+
Tiny trend line. Props: `data: number[]`, `color?`, `area?` (fill, default true), `min?`, `max?`. Size with `className` (default `h-9 w-full`). Also exports `smoothPath(points)`.
|
|
234
|
+
|
|
235
|
+
### `StatusBars`
|
|
236
|
+
|
|
237
|
+
Mini bar history (pings, uptime). Props: `data: (number | { value; tone?; label? })[]`, `max?`, `tone?` (default for plain numbers). Default size 96x26.
|
|
238
|
+
|
|
239
|
+
## AI and chat
|
|
240
|
+
|
|
241
|
+
A chat screen is: `ConversationList` in a sidebar, a `Card` with a header (`ModelPicker`), a `ChatThread` of `ChatMessage`s, and a `PromptInput` at the bottom. See `playground/screens/chat.tsx`.
|
|
242
|
+
|
|
243
|
+
### `ChatThread`
|
|
244
|
+
|
|
245
|
+
Scrollable log that sticks to the bottom as content streams in (unless the user scrolls up). Give it a bounded height (e.g. `flex-1` inside a fixed-height column). Props: `autoScroll?` (default true), `contentClassName?` (inner column, max-width 760px).
|
|
246
|
+
|
|
247
|
+
### `ChatMessage`
|
|
248
|
+
|
|
249
|
+
One turn. Props: `role: "user" | "assistant"` (matches AI SDK message roles), `avatar?` (assistant only, defaults to `AssistantAvatar`), `actions?` (assistant only, under the content), `children`.
|
|
250
|
+
User turns render as a right-aligned bubble with preserved newlines. Assistant turns render free-flowing: put `Prose`, `CodeBlock`, `ToolCall`, `TypingIndicator` inside.
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
;<ChatThread>
|
|
254
|
+
{messages.map((m) => (
|
|
255
|
+
<ChatMessage
|
|
256
|
+
key={m.id}
|
|
257
|
+
role={m.role}
|
|
258
|
+
actions={m.role === "assistant" ? <MessageActions copyText={m.text} onRegenerate={regen} /> : undefined}
|
|
259
|
+
>
|
|
260
|
+
{m.role === "user" ? (
|
|
261
|
+
m.text
|
|
262
|
+
) : (
|
|
263
|
+
<Prose>
|
|
264
|
+
<Markdown>{m.text}</Markdown>
|
|
265
|
+
</Prose>
|
|
266
|
+
)}
|
|
267
|
+
</ChatMessage>
|
|
268
|
+
))}
|
|
269
|
+
{status === "streaming" && (
|
|
270
|
+
<ChatMessage role="assistant">
|
|
271
|
+
<TypingIndicator />
|
|
272
|
+
</ChatMessage>
|
|
273
|
+
)}
|
|
274
|
+
</ChatThread>
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### `AssistantAvatar`
|
|
278
|
+
|
|
279
|
+
Tinted circle icon. Props: `icon?`, `className?`.
|
|
280
|
+
|
|
281
|
+
### `MessageActions`
|
|
282
|
+
|
|
283
|
+
Row of ghost icon buttons. Props: `copyText?` (shows copy), `onRegenerate?`, `onFeedback?(up|down)`, `feedback?` (pressed state), `children` (extra buttons).
|
|
284
|
+
|
|
285
|
+
### `PromptInput`, `PromptInputChip`
|
|
286
|
+
|
|
287
|
+
Composer. Props: `value`, `onValueChange`, `onSubmit(text)` (Enter sends trimmed text, Shift+Enter is a newline), `placeholder?`, `loading?` + `onStop?` (send becomes stop), `onAttach?` (shows paperclip), `tools?` (chips), `footer?` (disclaimer), `disabled?`, `autoFocus?`.
|
|
288
|
+
`PromptInputChip` is a pill toggle for the tools slot: `active`, `onClick`, children (icon + label).
|
|
289
|
+
|
|
290
|
+
### `ModelPicker`
|
|
291
|
+
|
|
292
|
+
Pill showing the active model with a status dot, opening a menu. Props: `models: { id; label?; description?; status? }[]`, `value`, `onValueChange`, `label?`, `disabled?`.
|
|
293
|
+
|
|
294
|
+
### `ConversationList`
|
|
295
|
+
|
|
296
|
+
Grouped thread list. Props: `groups: { label; items: { id; title }[] }[]`, `activeId?`, `onSelect?(id)`.
|
|
297
|
+
|
|
298
|
+
### `ToolCall`
|
|
299
|
+
|
|
300
|
+
Outlined chip for a tool call. Props: `status?` (`running` shows a spinner, `done`, `error`), `icon?`, `children` (summary).
|
|
301
|
+
|
|
302
|
+
### `TypingIndicator`
|
|
303
|
+
|
|
304
|
+
Three pulsing dots.
|
|
305
|
+
|
|
306
|
+
### `CodeBlock`, `InlineCode`, `Prose`
|
|
307
|
+
|
|
308
|
+
`CodeBlock`: `code`, `language?`, `hideCopy?`, `children?` (pre-highlighted markup, e.g. from shiki; no highlighter bundled).
|
|
309
|
+
`InlineCode`: monospace span.
|
|
310
|
+
`Prose`: typography for model output and markdown. Styles plain `p, ul, ol, li, strong, a, code, pre, h1-h4, blockquote, table` children, so it works with `react-markdown`.
|
|
311
|
+
|
|
312
|
+
## Hooks and utilities
|
|
313
|
+
|
|
314
|
+
| Export | Use |
|
|
315
|
+
| ------------------------------ | ------------------------------------------------------------- |
|
|
316
|
+
| `useCopyToClipboard(resetMs?)` | `{ copied, copy(text) }` for copy buttons. |
|
|
317
|
+
| `useIsMobile()` | `true` under 768px. |
|
|
318
|
+
| `cn(...classes)` | clsx + tailwind-merge. Use for every `className` you compose. |
|
|
319
|
+
|
|
320
|
+
## Tokens
|
|
321
|
+
|
|
322
|
+
Use these as Tailwind utilities (`bg-*`, `text-*`, `border-*`, `ring-*`, `fill-*`, `stroke-*`):
|
|
323
|
+
|
|
324
|
+
| Token | Use |
|
|
325
|
+
| ----------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
326
|
+
| `background` / `foreground` | Page background and body text. |
|
|
327
|
+
| `card` / `card-foreground` | Raised surfaces (cards, active nav item, popovers via `popover`). |
|
|
328
|
+
| `muted` / `muted-foreground` | Inputs, segmented controls, quiet panels; secondary text and labels. |
|
|
329
|
+
| `primary` / `primary-foreground` | Brand accent (from `--brand`). Primary buttons, links, chart line. |
|
|
330
|
+
| `primary-soft` | Tinted primary background for selected rows, soft badges, icon circles. Pair with `text-primary`. |
|
|
331
|
+
| `secondary`, `accent` | Same as muted; kept for shadcn compatibility. |
|
|
332
|
+
| `success`, `warning`, `destructive` | Status colors. Use `bg-success/12 text-success` for soft status fills. |
|
|
333
|
+
| `border`, `input`, `ring` | Hairlines, input borders, focus rings. |
|
|
334
|
+
| `chart-1` … `chart-5`, `chart-grid` | Data series and gridlines. |
|
|
335
|
+
| `sidebar-*` | Sidebar surfaces (default to the page tokens). |
|
|
336
|
+
|
|
337
|
+
Other theme values: `rounded-sm/md/lg/xl/2xl` scale from `--radius` (default 14px; cards use `xl`, buttons and inputs `md`), `shadow-card` (the one elevation), `font-sans` (Geist), `font-mono` (Geist Mono), `animate-typing`.
|
|
338
|
+
|
|
339
|
+
Override any token in your CSS after the import:
|
|
340
|
+
|
|
341
|
+
```css
|
|
342
|
+
@import "tailwindcss";
|
|
343
|
+
@import "harebear-ui/styles.css";
|
|
344
|
+
|
|
345
|
+
:root {
|
|
346
|
+
--brand: #0f8a7e;
|
|
347
|
+
--radius: 0.625rem;
|
|
348
|
+
}
|
|
349
|
+
.dark {
|
|
350
|
+
--background: #0b0b0d;
|
|
351
|
+
}
|
|
352
|
+
```
|
package/llms.txt
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# harebear-ui
|
|
2
|
+
|
|
3
|
+
> Opinionated, pre-themed React component library: shadcn/ui primitives restyled to one design system, plus admin, data, and AI chat components. React 19, Tailwind CSS v4, Radix, TypeScript. Ships its Tailwind theme.
|
|
4
|
+
|
|
5
|
+
## Setup in an app
|
|
6
|
+
|
|
7
|
+
1. `npm i harebear-ui` (peers: react, react-dom 19; tailwindcss 4).
|
|
8
|
+
2. `npx harebear-ui init` wires the CSS import and agent docs, or do it by hand: in the main CSS file, `@import "tailwindcss";` then `@import "harebear-ui/styles.css";`.
|
|
9
|
+
3. Wrap the app: `<ThemeProvider><TooltipProvider>{app}<Toaster /></TooltipProvider></ThemeProvider>`.
|
|
10
|
+
4. Import everything from the root: `import { Button, Card, DataTable } from "harebear-ui"`.
|
|
11
|
+
|
|
12
|
+
## Rules
|
|
13
|
+
|
|
14
|
+
- Use harebear-ui components before writing new UI. Primitives keep shadcn/ui names and props.
|
|
15
|
+
- Style with theme tokens only: bg-background, bg-card, bg-muted, text-muted-foreground, bg-primary, bg-primary-soft, text-success, text-warning, text-destructive, border-border, shadow-card, rounded-md/lg/xl. No hex colors or Tailwind palette colors.
|
|
16
|
+
- Status is a tone: success | warning | danger | info | neutral.
|
|
17
|
+
- Icons: lucide-react elements, e.g. `<SearchIcon />`. Icon-only buttons need aria-label.
|
|
18
|
+
- Change the brand with `<ThemeProvider accent="#hex" radius={14}>` or `--brand` / `--radius` in CSS.
|
|
19
|
+
|
|
20
|
+
## Docs
|
|
21
|
+
|
|
22
|
+
- [Component catalog](docs/COMPONENTS.md): every export with props and examples. In an installed app: node_modules/harebear-ui/docs/COMPONENTS.md
|
|
23
|
+
- [Agent skill](skills/harebear-ui/SKILL.md): Claude Code skill, installed by `npx harebear-ui init`.
|
|
24
|
+
- [Example screens](https://github.com/hmilbradt/harebear-ui/tree/main/playground/screens): admin dashboard, AI chat, data table + detail panel, status home page.
|
|
25
|
+
- [Source](https://github.com/hmilbradt/harebear-ui)
|
|
26
|
+
|
|
27
|
+
## Component index
|
|
28
|
+
|
|
29
|
+
Theme: ThemeProvider, useTheme, ThemeToggle, ThemeScript
|
|
30
|
+
Layout/admin: AppShell, AppBrand, PageHeader, StatCard, SearchInput, StatusDot, StatusBadge, UsageMeter, ActivityFeed, Timeline, KeyValueGrid, UserChip, Callout, LinkTile
|
|
31
|
+
Data: DataTable, createDataTableColumnHelper, TrendChart, TrendLegend, BarList, Sparkline, StatusBars
|
|
32
|
+
AI/chat: ChatThread, ChatMessage, AssistantAvatar, MessageActions, PromptInput, PromptInputChip, ModelPicker, ConversationList, ToolCall, TypingIndicator, CodeBlock, InlineCode, Prose
|
|
33
|
+
Primitives (shadcn/ui): Accordion, Alert, AlertDialog, AspectRatio, Avatar, Badge, Breadcrumb, Button, ButtonGroup, Calendar, Card, Carousel, Chart, Checkbox, Collapsible, Command, ContextMenu, Dialog, Drawer, DropdownMenu, Empty, Field, HoverCard, Input, InputGroup, InputOTP, Item, Kbd, Label, Menubar, NavigationMenu, Pagination, Popover, Progress, RadioGroup, Resizable, ScrollArea, Select, Separator, Sheet, Sidebar, Skeleton, Slider, Spinner, Switch, Table, Tabs, Textarea, Toaster, Toggle, ToggleGroup, Tooltip
|
|
34
|
+
Hooks/utils: useCopyToClipboard, useIsMobile, cn
|