@reinvented/design 0.1.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/DESIGN_GUIDE.md +148 -0
- package/README.md +39 -162
- package/docs/components/alert-dialog.md +32 -0
- package/docs/components/avatar.md +14 -0
- package/docs/components/badge.md +24 -0
- package/docs/components/button.md +69 -0
- package/docs/components/card.md +49 -0
- package/docs/components/dialog.md +46 -0
- package/docs/components/dropdown-menu.md +32 -0
- package/docs/components/index.md +69 -0
- package/docs/components/input.md +34 -0
- package/docs/components/remaining-components.md +253 -0
- package/docs/components/scroll-area.md +17 -0
- package/docs/components/select.md +31 -0
- package/docs/components/separator.md +14 -0
- package/docs/components/sheet.md +32 -0
- package/docs/components/skeleton.md +20 -0
- package/docs/components/table.md +33 -0
- package/docs/components/tabs.md +23 -0
- package/docs/conventions.md +74 -0
- package/docs/layouts/dashboard.md +70 -0
- package/docs/layouts/detail-page.md +83 -0
- package/docs/layouts/index.md +45 -0
- package/docs/layouts/list-page.md +107 -0
- package/docs/layouts/settings-page.md +79 -0
- package/docs/layouts/step-wizard.md +73 -0
- package/docs/patterns/index.md +39 -0
- package/docs/rules.md +43 -0
- package/docs/visual-polish.md +141 -0
- package/package.json +40 -61
- package/src/components/ui/accordion/Accordion.vue +13 -0
- package/src/components/ui/accordion/AccordionContent.vue +20 -0
- package/src/components/ui/accordion/AccordionItem.vue +15 -0
- package/src/components/ui/accordion/AccordionTrigger.vue +25 -0
- package/src/components/ui/accordion/index.ts +4 -0
- package/src/components/ui/alert/Alert.vue +38 -0
- package/src/components/ui/alert/AlertDescription.vue +12 -0
- package/src/components/ui/alert/AlertTitle.vue +12 -0
- package/src/components/ui/alert/index.ts +3 -0
- package/src/components/ui/alert-dialog/AlertDialog.vue +13 -0
- package/src/components/ui/alert-dialog/AlertDialogAction.vue +21 -0
- package/src/components/ui/alert-dialog/AlertDialogCancel.vue +21 -0
- package/src/components/ui/alert-dialog/AlertDialogContent.vue +39 -0
- package/src/components/ui/alert-dialog/AlertDialogDescription.vue +15 -0
- package/src/components/ui/alert-dialog/AlertDialogFooter.vue +12 -0
- package/src/components/ui/alert-dialog/AlertDialogHeader.vue +12 -0
- package/src/components/ui/alert-dialog/AlertDialogTitle.vue +15 -0
- package/src/components/ui/alert-dialog/AlertDialogTrigger.vue +11 -0
- package/src/components/ui/alert-dialog/index.ts +9 -0
- package/src/components/ui/avatar/Avatar.vue +14 -0
- package/src/components/ui/avatar/index.ts +1 -0
- package/src/components/ui/badge/Badge.vue +27 -0
- package/src/components/ui/badge/index.ts +1 -0
- package/src/components/ui/breadcrumb/Breadcrumb.vue +6 -0
- package/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +12 -0
- package/src/components/ui/breadcrumb/BreadcrumbItem.vue +6 -0
- package/src/components/ui/breadcrumb/BreadcrumbLink.vue +20 -0
- package/src/components/ui/breadcrumb/BreadcrumbList.vue +6 -0
- package/src/components/ui/breadcrumb/BreadcrumbPage.vue +6 -0
- package/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +11 -0
- package/src/components/ui/breadcrumb/index.ts +7 -0
- package/src/components/ui/button/Button.vue +65 -0
- package/src/components/ui/button/index.ts +1 -0
- package/src/components/ui/card/Card.vue +13 -0
- package/src/components/ui/card/CardContent.vue +7 -0
- package/src/components/ui/card/CardDescription.vue +7 -0
- package/src/components/ui/card/CardFooter.vue +7 -0
- package/src/components/ui/card/CardHeader.vue +9 -0
- package/src/components/ui/card/CardTitle.vue +7 -0
- package/src/components/ui/card/index.ts +6 -0
- package/src/components/ui/checkbox/Checkbox.vue +25 -0
- package/src/components/ui/checkbox/index.ts +1 -0
- package/src/components/ui/collapsible/Collapsible.vue +13 -0
- package/src/components/ui/collapsible/index.ts +2 -0
- package/src/components/ui/command/Command.vue +16 -0
- package/src/components/ui/command/CommandEmpty.vue +5 -0
- package/src/components/ui/command/CommandGroup.vue +22 -0
- package/src/components/ui/command/CommandInput.vue +21 -0
- package/src/components/ui/command/CommandItem.vue +22 -0
- package/src/components/ui/command/CommandList.vue +17 -0
- package/src/components/ui/command/CommandSeparator.vue +5 -0
- package/src/components/ui/command/index.ts +7 -0
- package/src/components/ui/context-menu/ContextMenuContent.vue +24 -0
- package/src/components/ui/context-menu/ContextMenuItem.vue +16 -0
- package/src/components/ui/context-menu/ContextMenuLabel.vue +9 -0
- package/src/components/ui/context-menu/ContextMenuSeparator.vue +9 -0
- package/src/components/ui/context-menu/ContextMenuSubContent.vue +14 -0
- package/src/components/ui/context-menu/index.ts +9 -0
- package/src/components/ui/dialog/Dialog.vue +14 -0
- package/src/components/ui/dialog/DialogClose.vue +12 -0
- package/src/components/ui/dialog/DialogContent.vue +48 -0
- package/src/components/ui/dialog/DialogDescription.vue +23 -0
- package/src/components/ui/dialog/DialogFooter.vue +12 -0
- package/src/components/ui/dialog/DialogHeader.vue +12 -0
- package/src/components/ui/dialog/DialogScrollContent.vue +47 -0
- package/src/components/ui/dialog/DialogTitle.vue +23 -0
- package/src/components/ui/dialog/DialogTrigger.vue +12 -0
- package/src/components/ui/dialog/index.ts +9 -0
- package/src/components/ui/dropdown-menu/DropdownMenu.vue +13 -0
- package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +28 -0
- package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +33 -0
- package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +11 -0
- package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +27 -0
- package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +23 -0
- package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +13 -0
- package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +27 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +13 -0
- package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +12 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +13 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +27 -0
- package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +23 -0
- package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +11 -0
- package/src/components/ui/dropdown-menu/index.ts +14 -0
- package/src/components/ui/form/FormControl.vue +3 -0
- package/src/components/ui/form/FormDescription.vue +6 -0
- package/src/components/ui/form/FormItem.vue +6 -0
- package/src/components/ui/form/FormLabel.vue +10 -0
- package/src/components/ui/form/FormMessage.vue +10 -0
- package/src/components/ui/form/index.ts +9 -0
- package/src/components/ui/hover-card/HoverCard.vue +13 -0
- package/src/components/ui/hover-card/HoverCardContent.vue +26 -0
- package/src/components/ui/hover-card/HoverCardTrigger.vue +11 -0
- package/src/components/ui/hover-card/index.ts +3 -0
- package/src/components/ui/input/Input.vue +23 -0
- package/src/components/ui/input/index.ts +1 -0
- package/src/components/ui/label/Label.vue +18 -0
- package/src/components/ui/label/index.ts +1 -0
- package/src/components/ui/lib/utils.ts +2 -0
- package/src/components/ui/menubar/MenubarContent.vue +15 -0
- package/src/components/ui/menubar/MenubarItem.vue +13 -0
- package/src/components/ui/menubar/MenubarTrigger.vue +13 -0
- package/src/components/ui/menubar/index.ts +5 -0
- package/src/components/ui/navigation-menu/NavigationMenuContent.vue +14 -0
- package/src/components/ui/navigation-menu/NavigationMenuTrigger.vue +15 -0
- package/src/components/ui/navigation-menu/index.ts +4 -0
- package/src/components/ui/pagination/PaginationContent.vue +13 -0
- package/src/components/ui/pagination/PaginationEllipsis.vue +12 -0
- package/src/components/ui/pagination/PaginationNext.vue +14 -0
- package/src/components/ui/pagination/PaginationPrev.vue +14 -0
- package/src/components/ui/pagination/index.ts +6 -0
- package/src/components/ui/popover/Popover.vue +13 -0
- package/src/components/ui/popover/PopoverContent.vue +27 -0
- package/src/components/ui/popover/PopoverTrigger.vue +11 -0
- package/src/components/ui/popover/index.ts +3 -0
- package/src/components/ui/progress/Progress.vue +21 -0
- package/src/components/ui/progress/index.ts +1 -0
- package/src/components/ui/radio-group/RadioGroup.vue +16 -0
- package/src/components/ui/radio-group/RadioGroupItem.vue +24 -0
- package/src/components/ui/radio-group/index.ts +2 -0
- package/src/components/ui/scroll-area/ScrollArea.vue +13 -0
- package/src/components/ui/scroll-area/index.ts +1 -0
- package/src/components/ui/select/Select.vue +13 -0
- package/src/components/ui/select/SelectContent.vue +40 -0
- package/src/components/ui/select/SelectGroup.vue +15 -0
- package/src/components/ui/select/SelectItem.vue +30 -0
- package/src/components/ui/select/SelectLabel.vue +15 -0
- package/src/components/ui/select/SelectSeparator.vue +13 -0
- package/src/components/ui/select/SelectTrigger.vue +23 -0
- package/src/components/ui/select/SelectValue.vue +11 -0
- package/src/components/ui/select/index.ts +8 -0
- package/src/components/ui/separator/Separator.vue +16 -0
- package/src/components/ui/separator/index.ts +1 -0
- package/src/components/ui/sheet/Sheet.vue +13 -0
- package/src/components/ui/sheet/SheetClose.vue +11 -0
- package/src/components/ui/sheet/SheetContent.vue +65 -0
- package/src/components/ui/sheet/SheetDescription.vue +15 -0
- package/src/components/ui/sheet/SheetFooter.vue +12 -0
- package/src/components/ui/sheet/SheetHeader.vue +12 -0
- package/src/components/ui/sheet/SheetTitle.vue +15 -0
- package/src/components/ui/sheet/SheetTrigger.vue +11 -0
- package/src/components/ui/sheet/index.ts +8 -0
- package/src/components/ui/skeleton/Skeleton.vue +9 -0
- package/src/components/ui/skeleton/index.ts +1 -0
- package/src/components/ui/slider/Slider.vue +26 -0
- package/src/components/ui/slider/index.ts +1 -0
- package/src/components/ui/switch/Switch.vue +24 -0
- package/src/components/ui/switch/index.ts +1 -0
- package/src/components/ui/table/Table.vue +13 -0
- package/src/components/ui/table/TableBody.vue +6 -0
- package/src/components/ui/table/TableCaption.vue +6 -0
- package/src/components/ui/table/TableCell.vue +6 -0
- package/src/components/ui/table/TableFooter.vue +6 -0
- package/src/components/ui/table/TableHead.vue +6 -0
- package/src/components/ui/table/TableHeader.vue +6 -0
- package/src/components/ui/table/TableRow.vue +6 -0
- package/src/components/ui/table/index.ts +8 -0
- package/src/components/ui/tabs/Tabs.vue +13 -0
- package/src/components/ui/tabs/TabsContent.vue +21 -0
- package/src/components/ui/tabs/TabsList.vue +21 -0
- package/src/components/ui/tabs/TabsTrigger.vue +21 -0
- package/src/components/ui/tabs/index.ts +4 -0
- package/src/components/ui/textarea/Textarea.vue +29 -0
- package/src/components/ui/textarea/index.ts +1 -0
- package/src/components/ui/toggle/Toggle.vue +40 -0
- package/src/components/ui/toggle/index.ts +1 -0
- package/src/components/ui/toggle-group/ToggleGroup.vue +16 -0
- package/src/components/ui/toggle-group/ToggleGroupItem.vue +21 -0
- package/src/components/ui/toggle-group/index.ts +2 -0
- package/src/components/ui/tooltip/Tooltip.vue +13 -0
- package/src/components/ui/tooltip/TooltipContent.vue +27 -0
- package/src/components/ui/tooltip/TooltipProvider.vue +12 -0
- package/src/components/ui/tooltip/TooltipTrigger.vue +11 -0
- package/src/components/ui/tooltip/index.ts +4 -0
- package/src/env.d.ts +7 -0
- package/src/index.ts +63 -0
- package/src/lib/utils.ts +7 -0
- package/src/patterns/DetailView.vue +46 -0
- package/src/patterns/EmptyState.vue +27 -0
- package/src/patterns/FormView.vue +34 -0
- package/src/patterns/ListView.vue +45 -0
- package/src/styles/index.css +4 -0
- package/src/styles/tokens.css +144 -0
- package/tailwind.config.js +108 -0
- package/tsconfig.json +21 -0
- package/dist/index.css +0 -1890
- package/dist/index.d.ts +0 -406
- package/dist/index.js +0 -1721
- package/dist/index.js.map +0 -1
- package/tailwind.config.ts +0 -174
package/DESIGN_GUIDE.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Reinvented Design Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
The Reinvented design system uses **Shadcn-vue** components with custom **Radix-vue** primitives,
|
|
5
|
+
**Tailwind CSS** for styling, and **Lucide** icons. All UI surfaces share this consistent foundation.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Typography
|
|
10
|
+
|
|
11
|
+
| Token | Size | Weight | Use |
|
|
12
|
+
|---------------|--------|----------|------------------------|
|
|
13
|
+
| `text-xs` | 12px | 400 | Timestamps, captions |
|
|
14
|
+
| `text-sm` | 14px | 400–500 | Body text, labels |
|
|
15
|
+
| `text-base` | 16px | 400 | Default body |
|
|
16
|
+
| `text-lg` | 18px | 600 | Section headings |
|
|
17
|
+
| `text-xl` | 20px | 600 | Page subtitles |
|
|
18
|
+
| `text-2xl` | 24px | 700 | Page titles |
|
|
19
|
+
| `text-3xl` | 30px | 700 | Hero text |
|
|
20
|
+
|
|
21
|
+
**Font:** Inter (loaded via Google Fonts).
|
|
22
|
+
**Line height:** Use `leading-tight` (1.25) for headings, `leading-normal` (1.5) for body.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Colors
|
|
27
|
+
|
|
28
|
+
Our brand color is **purple** (`hsl(252 100% 63%)`).
|
|
29
|
+
|
|
30
|
+
| Token | Light | Dark | Use |
|
|
31
|
+
|-----------------|-------------------|-------------------|------------------------|
|
|
32
|
+
| `primary` | Purple 63% | Purple 69% | Buttons, links, focus |
|
|
33
|
+
| `secondary` | Zinc 96% | Zinc 16% | Secondary actions |
|
|
34
|
+
| `muted` | Zinc 96% | Zinc 16% | Backgrounds, disabled |
|
|
35
|
+
| `destructive` | Red 60% | Red 31% | Delete, errors |
|
|
36
|
+
| `success` | Green 36% | Green 45% | Confirmations |
|
|
37
|
+
| `warning` | Amber 50% | Amber 55% | Alerts |
|
|
38
|
+
| `info` | Blue 60% | Blue 65% | Information |
|
|
39
|
+
|
|
40
|
+
**Usage rules:**
|
|
41
|
+
- Never hardcode colors — always use `hsl(var(--token))`
|
|
42
|
+
- Use `text-muted-foreground` for secondary text (not arbitrary gray)
|
|
43
|
+
- Apply `bg-card` for card surfaces, `bg-background` for page backgrounds
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Spacing
|
|
48
|
+
|
|
49
|
+
Based on **4px increments**. Use Tailwind utilities:
|
|
50
|
+
|
|
51
|
+
| Class | Value | Use |
|
|
52
|
+
|----------|-------|----------------------------|
|
|
53
|
+
| `gap-1` | 4px | Icon-to-text gap |
|
|
54
|
+
| `gap-2` | 8px | Between small elements |
|
|
55
|
+
| `gap-3` | 12px | Between form fields |
|
|
56
|
+
| `gap-4` | 16px | Section spacing |
|
|
57
|
+
| `gap-6` | 24px | Between major sections |
|
|
58
|
+
| `p-4` | 16px | Standard padding |
|
|
59
|
+
| `p-6` | 24px | Card padding |
|
|
60
|
+
| `px-4` | 16px | Page horizontal padding |
|
|
61
|
+
|
|
62
|
+
**Rules:**
|
|
63
|
+
- Always use spacing tokens, never arbitrary values
|
|
64
|
+
- Vertical rhythm: Use `gap-4` or `gap-6` for stacking sections
|
|
65
|
+
- Horizontal rhythm: Use `gap-2` or `gap-3` for inline elements
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Icons
|
|
70
|
+
|
|
71
|
+
- **Library:** Lucide Vue Next (`lucide-vue-next`)
|
|
72
|
+
- **NO emojis** anywhere in the UI
|
|
73
|
+
- Default icon size: `16px` (`w-4 h-4`)
|
|
74
|
+
- In buttons/nav: `w-4 h-4`
|
|
75
|
+
- In empty states: `w-12 h-12` with `text-muted-foreground`
|
|
76
|
+
- Always use `stroke-width="2"` (Lucide default)
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Shadows & Borders
|
|
81
|
+
|
|
82
|
+
| Token | CSS | Use |
|
|
83
|
+
|-------------|-------------------------------|----------------------------|
|
|
84
|
+
| `shadow-sm` | Subtle 1px shadow | Cards, buttons |
|
|
85
|
+
| `shadow-md` | Medium depth | Dropdowns, popovers |
|
|
86
|
+
| `shadow-lg` | Strong depth | Modals, dialogs |
|
|
87
|
+
| `rounded-md`| `calc(var(--radius) - 2px)` | Inputs, small elements |
|
|
88
|
+
| `rounded-lg`| `var(--radius)` (10px) | Cards, containers |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Component Guidelines
|
|
93
|
+
|
|
94
|
+
### When to use existing components
|
|
95
|
+
Always check `@reinvented/design` first:
|
|
96
|
+
```ts
|
|
97
|
+
import { Button, Card, Input, Avatar, Badge } from '@reinvented/design'
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Using Radix primitives
|
|
101
|
+
For Dialog, DropdownMenu, Tabs, Tooltip, PopoverSelect, etc.:
|
|
102
|
+
```ts
|
|
103
|
+
import { Dialog, DialogTrigger, DialogContent, DialogTitle } from '@reinvented/design'
|
|
104
|
+
```
|
|
105
|
+
Style them using `cn()` and Tailwind:
|
|
106
|
+
```vue
|
|
107
|
+
<DialogContent :class="cn('fixed inset-0 z-50 flex items-center justify-center')">
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Building new components
|
|
111
|
+
1. Create in `packages/ds/src/components/ui/<name>/`
|
|
112
|
+
2. Use `cn()` for class merging
|
|
113
|
+
3. Accept `class` prop for customization
|
|
114
|
+
4. Use design tokens (never hardcode colors)
|
|
115
|
+
5. Export from barrel (`src/index.ts`)
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Page Patterns
|
|
120
|
+
|
|
121
|
+
Import from `@reinvented/design/patterns/*`:
|
|
122
|
+
|
|
123
|
+
| Pattern | Use |
|
|
124
|
+
|--------------|----------------------------------------------|
|
|
125
|
+
| `ListView` | Lists with search, filters, items |
|
|
126
|
+
| `DetailView` | Detail pages with hero, tabs, content |
|
|
127
|
+
| `FormView` | Forms with validation and submit |
|
|
128
|
+
| `EmptyState` | Centered empty state with icon and CTA |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Dark Mode
|
|
133
|
+
|
|
134
|
+
- Controlled via `.dark` class on `<html>` or `<body>`
|
|
135
|
+
- All tokens automatically switch in dark mode
|
|
136
|
+
- Test both modes when building surfaces
|
|
137
|
+
- Use `dark:` prefix sparingly — prefer CSS variable-driven theming
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Do NOT
|
|
142
|
+
|
|
143
|
+
- Use `alert()`, `confirm()`, or `prompt()` — use Dialog/AlertDialog
|
|
144
|
+
- Use emojis — use Lucide icons
|
|
145
|
+
- Hardcode colors — use CSS variables
|
|
146
|
+
- Use arbitrary Tailwind values (e.g., `text-[#333]`) — use tokens
|
|
147
|
+
- Create split-screen layouts — use single-column responsive design
|
|
148
|
+
- Use `@apply` excessively — prefer utility classes in templates
|
package/README.md
CHANGED
|
@@ -1,179 +1,56 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Reinvented Design System
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The opinionated visual foundation for all Reinvented apps. Components, patterns, layouts, conventions, rules, and documentation.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
- **Dark-first** — Nearly-black backgrounds (`#0a0a0b`) with subtle surface elevation, not obvious cards
|
|
8
|
-
- **Restrained palette** — Mostly grays with one accent color (violet-blue `#5b6af0`), used sparingly on interactive elements
|
|
9
|
-
- **Muted borders** — No heavy shadows in dark mode; borders at 4–16% white opacity
|
|
10
|
-
- **Tight typography** — Inter font, compact scale (11px–36px), 4 main text styles
|
|
11
|
-
- **Smooth animations** — Subtle fade-in, slide-up, scale-in transitions (200ms default)
|
|
12
|
-
- **Consistency-first** — Composition components with locked styling prevent visual drift
|
|
13
|
-
|
|
14
|
-
## Installation
|
|
5
|
+
## Quick Start
|
|
15
6
|
|
|
16
7
|
```bash
|
|
17
|
-
|
|
8
|
+
npm install @reinvented/design
|
|
18
9
|
```
|
|
19
10
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
11
|
+
```vue
|
|
12
|
+
<script setup>
|
|
13
|
+
import { Button, Card, Input, Badge, Dialog } from '@reinvented/design'
|
|
14
|
+
</script>
|
|
24
15
|
```
|
|
25
16
|
|
|
26
|
-
##
|
|
17
|
+
## Stack
|
|
27
18
|
|
|
28
|
-
|
|
19
|
+
- **Components**: [Shadcn-vue](https://www.shadcn-vue.com/) (all components, styled with our tokens)
|
|
20
|
+
- **Primitives**: [Radix Vue](https://www.radix-vue.com/) (accessible headless components)
|
|
21
|
+
- **Styling**: [Tailwind CSS](https://tailwindcss.com/) with design tokens
|
|
22
|
+
- **Icons**: [Lucide Vue Next](https://lucide.dev/) (no emojis, ever)
|
|
23
|
+
- **Typography**: Inter (via Google Fonts)
|
|
29
24
|
|
|
30
|
-
|
|
31
|
-
import { Button, Input, Card, Badge, Dialog } from "@reinvented/design";
|
|
25
|
+
## Structure
|
|
32
26
|
|
|
33
|
-
<Button variant="primary" size="md">Save</Button>
|
|
34
|
-
<Button variant="ghost" size="sm">Cancel</Button>
|
|
35
|
-
<Input label="Email" placeholder="you@example.com" error="Required" />
|
|
36
|
-
<Badge variant="success">Active</Badge>
|
|
37
27
|
```
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
<ListItem
|
|
53
|
-
leading={<UserIcon size={16} />}
|
|
54
|
-
title="John Doe"
|
|
55
|
-
description="john@example.com"
|
|
56
|
-
trailing={<Badge>Admin</Badge>}
|
|
57
|
-
onClick={() => navigate("/users/1")}
|
|
58
|
-
/>
|
|
59
|
-
|
|
60
|
-
<EmptyState
|
|
61
|
-
icon={<InboxIcon size={32} />}
|
|
62
|
-
title="No items yet"
|
|
63
|
-
description="Create your first item to get started"
|
|
64
|
-
action={<Button>Create</Button>}
|
|
65
|
-
/>
|
|
28
|
+
src/
|
|
29
|
+
components/ui/ All styled components
|
|
30
|
+
patterns/ Reusable compositions (ListView, DetailView, etc.)
|
|
31
|
+
layouts/ Page-level layout components with slots
|
|
32
|
+
lib/ Utilities (cn, etc.)
|
|
33
|
+
styles/ Tokens, CSS variables
|
|
34
|
+
docs/
|
|
35
|
+
rules.md Hard design rules
|
|
36
|
+
conventions.md Opinionated UX decisions
|
|
37
|
+
visual-polish.md Animations, transitions, polish guidelines
|
|
38
|
+
components/ Per-component usage guides
|
|
39
|
+
patterns/ Per-pattern docs with skeleton code
|
|
40
|
+
layouts/ Per-layout docs with skeleton code
|
|
41
|
+
examples/ Full skeleton examples
|
|
66
42
|
```
|
|
67
43
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
```tsx
|
|
71
|
-
import { AppShell, TopBar, SideRail, SideRailItem, PageContainer } from "@reinvented/design";
|
|
44
|
+
## Documentation
|
|
72
45
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
>
|
|
82
|
-
<PageContainer>
|
|
83
|
-
{/* Page content */}
|
|
84
|
-
</PageContainer>
|
|
85
|
-
</AppShell>
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Icons
|
|
89
|
-
|
|
90
|
-
```tsx
|
|
91
|
-
import { DynamicIcon, Settings, ChevronRight } from "@reinvented/design";
|
|
92
|
-
|
|
93
|
-
// Static icon
|
|
94
|
-
<Settings size={16} />
|
|
95
|
-
|
|
96
|
-
// Dynamic icon by name string (for app manager)
|
|
97
|
-
<DynamicIcon name="Settings" size={16} />
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### Hooks
|
|
101
|
-
|
|
102
|
-
```tsx
|
|
103
|
-
import { useTheme, useMediaQuery } from "@reinvented/design";
|
|
104
|
-
|
|
105
|
-
const { theme, toggleTheme, isDark } = useTheme();
|
|
106
|
-
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Utilities
|
|
110
|
-
|
|
111
|
-
```tsx
|
|
112
|
-
import { cn } from "@reinvented/design";
|
|
113
|
-
|
|
114
|
-
<div className={cn("text-fg-primary", isActive && "text-accent")} />
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### Command Palette
|
|
118
|
-
|
|
119
|
-
```tsx
|
|
120
|
-
import { CommandPalette, CommandGroup, CommandItem, CommandEmpty } from "@reinvented/design";
|
|
121
|
-
|
|
122
|
-
<CommandPalette placeholder="Search or jump to…">
|
|
123
|
-
<CommandEmpty>No results found.</CommandEmpty>
|
|
124
|
-
<CommandGroup heading="Actions">
|
|
125
|
-
<CommandItem onSelect={() => navigate("/settings")}>Settings</CommandItem>
|
|
126
|
-
</CommandGroup>
|
|
127
|
-
</CommandPalette>
|
|
128
|
-
// Opens with Cmd+K / Ctrl+K
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
## Token Reference
|
|
132
|
-
|
|
133
|
-
| Token | Dark Value | Purpose |
|
|
134
|
-
|-------|-----------|---------|
|
|
135
|
-
| `--bg-base` | `#0a0a0b` | App background |
|
|
136
|
-
| `--bg-surface` | `#111113` | Cards, panels |
|
|
137
|
-
| `--bg-elevated` | `#191a1f` | Dropdowns, popovers |
|
|
138
|
-
| `--fg-primary` | `#ededef` | Primary text |
|
|
139
|
-
| `--fg-secondary` | `#a1a1a6` | Secondary text |
|
|
140
|
-
| `--fg-muted` | `#6e6e76` | Placeholder, hints |
|
|
141
|
-
| `--accent` | `#5b6af0` | Interactive elements |
|
|
142
|
-
| `--border-default` | `rgba(255,255,255,0.08)` | Standard borders |
|
|
143
|
-
|
|
144
|
-
## Component Catalog
|
|
145
|
-
|
|
146
|
-
### Primitives
|
|
147
|
-
Button, Input, Badge, Avatar, Card, Label, Dialog, DropdownMenu, Toast, Separator, ScrollArea, Select, Switch, Checkbox, Tabs, Tooltip, Skeleton, Sheet
|
|
148
|
-
|
|
149
|
-
### Composition (locked)
|
|
150
|
-
ContentCard, PageHeader, ListItem, FormSection, ActionBar, EmptyState
|
|
151
|
-
|
|
152
|
-
### Layout
|
|
153
|
-
AppShell, TopBar, SideRail, BottomBar, PageContainer
|
|
154
|
-
|
|
155
|
-
### Feedback & Overlays
|
|
156
|
-
Spinner, ErrorBoundary, CommandPalette
|
|
157
|
-
|
|
158
|
-
## Tailwind Config
|
|
159
|
-
|
|
160
|
-
Consuming apps should extend the design system's Tailwind config:
|
|
161
|
-
|
|
162
|
-
```ts
|
|
163
|
-
// tailwind.config.ts in your app
|
|
164
|
-
import designConfig from "@reinvented/design/tailwind";
|
|
165
|
-
|
|
166
|
-
export default {
|
|
167
|
-
presets: [designConfig],
|
|
168
|
-
content: [
|
|
169
|
-
"./src/**/*.{ts,tsx}",
|
|
170
|
-
"../../packages/design/src/**/*.{ts,tsx}",
|
|
171
|
-
],
|
|
172
|
-
};
|
|
173
|
-
```
|
|
46
|
+
- **[Rules](docs/rules.md)** — Non-negotiable design constraints
|
|
47
|
+
- **[Conventions](docs/conventions.md)** — Opinionated UX decisions
|
|
48
|
+
- **[Visual Polish](docs/visual-polish.md)** — Animation and polish guide
|
|
49
|
+
- **[Components](docs/components/index.md)** — Component usage guides
|
|
50
|
+
- **[Patterns](docs/patterns/index.md)** — Reusable UI patterns
|
|
51
|
+
- **[Layouts](docs/layouts/index.md)** — Page layout recipes
|
|
52
|
+
- **[Design Guide](DESIGN_GUIDE.md)** — Tokens, typography, colors, spacing
|
|
174
53
|
|
|
175
|
-
##
|
|
54
|
+
## Contributing
|
|
176
55
|
|
|
177
|
-
|
|
178
|
-
2. Export it from `src/index.ts`
|
|
179
|
-
3. Run `pnpm build` to verify
|
|
56
|
+
Agents and humans can propose changes via PRs. See [conventions](docs/conventions.md) for design principles.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# AlertDialog
|
|
2
|
+
## When to Use
|
|
3
|
+
- Destructive action confirmation (delete, remove, irreversible changes)
|
|
4
|
+
|
|
5
|
+
## Skeleton Code
|
|
6
|
+
```vue
|
|
7
|
+
<script setup>
|
|
8
|
+
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, Button } from '@reinvented/design'
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<AlertDialog>
|
|
13
|
+
<AlertDialogTrigger as-child>
|
|
14
|
+
<Button variant="destructive">Delete</Button>
|
|
15
|
+
</AlertDialogTrigger>
|
|
16
|
+
<AlertDialogContent>
|
|
17
|
+
<AlertDialogHeader>
|
|
18
|
+
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
|
|
19
|
+
<AlertDialogDescription>This action cannot be undone.</AlertDialogDescription>
|
|
20
|
+
</AlertDialogHeader>
|
|
21
|
+
<AlertDialogFooter>
|
|
22
|
+
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
23
|
+
<AlertDialogAction>Delete Item</AlertDialogAction>
|
|
24
|
+
</AlertDialogFooter>
|
|
25
|
+
</AlertDialogContent>
|
|
26
|
+
</AlertDialog>
|
|
27
|
+
</template>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Gotchas
|
|
31
|
+
- Action button text must describe what it does ("Delete Task", not "OK")
|
|
32
|
+
- Cancel is always the default focused element
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Avatar
|
|
2
|
+
## Skeleton Code
|
|
3
|
+
```vue
|
|
4
|
+
<script setup>
|
|
5
|
+
import { Avatar } from '@reinvented/design'
|
|
6
|
+
</script>
|
|
7
|
+
<template>
|
|
8
|
+
<Avatar src="/user.jpg" alt="User name" />
|
|
9
|
+
<Avatar>JD</Avatar> <!-- Fallback initials -->
|
|
10
|
+
</template>
|
|
11
|
+
```
|
|
12
|
+
## Gotchas
|
|
13
|
+
- Always provide `alt` text for accessibility
|
|
14
|
+
- Fallback shows slot content when `src` fails to load
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Badge
|
|
2
|
+
## Variants
|
|
3
|
+
| Variant | Use for |
|
|
4
|
+
|---------|---------|
|
|
5
|
+
| `default` | Neutral status |
|
|
6
|
+
| `secondary` | Subtle labels |
|
|
7
|
+
| `destructive` | Error/danger status |
|
|
8
|
+
| `outline` | Bordered labels |
|
|
9
|
+
|
|
10
|
+
## Skeleton Code
|
|
11
|
+
```vue
|
|
12
|
+
<script setup>
|
|
13
|
+
import { Badge } from '@reinvented/design'
|
|
14
|
+
</script>
|
|
15
|
+
<template>
|
|
16
|
+
<Badge>Active</Badge>
|
|
17
|
+
<Badge variant="destructive">Error</Badge>
|
|
18
|
+
<Badge variant="secondary">Draft</Badge>
|
|
19
|
+
<Badge variant="outline">v1.2</Badge>
|
|
20
|
+
</template>
|
|
21
|
+
```
|
|
22
|
+
## Gotchas
|
|
23
|
+
- Use for status indicators, never for interactive actions (use Button for that)
|
|
24
|
+
- Keep text short (1-2 words)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Button
|
|
2
|
+
|
|
3
|
+
## Variants
|
|
4
|
+
| Variant | Use for |
|
|
5
|
+
|---------|---------|
|
|
6
|
+
| `default` | Primary actions |
|
|
7
|
+
| `secondary` | Secondary actions |
|
|
8
|
+
| `destructive` | Delete, remove, cancel |
|
|
9
|
+
| `outline` | Tertiary actions |
|
|
10
|
+
| `ghost` | Toolbar actions, icon-only buttons |
|
|
11
|
+
| `link` | Inline text actions |
|
|
12
|
+
| `success` | Positive confirmation actions |
|
|
13
|
+
|
|
14
|
+
## Sizes
|
|
15
|
+
| Size | Use for |
|
|
16
|
+
|------|---------|
|
|
17
|
+
| `default` | Standard buttons |
|
|
18
|
+
| `xs` | Compact UI, inline actions |
|
|
19
|
+
| `sm` | Compact UI, table rows |
|
|
20
|
+
| `lg` | Hero CTAs, empty state actions |
|
|
21
|
+
| `xl` | Landing page CTAs |
|
|
22
|
+
| `icon` | Icon-only square buttons |
|
|
23
|
+
|
|
24
|
+
## Skeleton Code
|
|
25
|
+
|
|
26
|
+
```vue
|
|
27
|
+
<script setup>
|
|
28
|
+
import { Button } from '@reinvented/design'
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<Button>Default</Button>
|
|
33
|
+
<Button variant="secondary">Secondary</Button>
|
|
34
|
+
<Button variant="destructive">Delete</Button>
|
|
35
|
+
<Button variant="outline">Outline</Button>
|
|
36
|
+
<Button variant="ghost">Ghost</Button>
|
|
37
|
+
<Button size="sm">Small</Button>
|
|
38
|
+
<Button size="icon"><Trash2 class="w-4 h-4" /></Button>
|
|
39
|
+
</template>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## With Loading State
|
|
43
|
+
|
|
44
|
+
```vue
|
|
45
|
+
<script setup>
|
|
46
|
+
import { ref } from 'vue'
|
|
47
|
+
import { Button } from '@reinvented/design'
|
|
48
|
+
import { Loader2 } from 'lucide-vue-next'
|
|
49
|
+
|
|
50
|
+
const saving = ref(false)
|
|
51
|
+
async function handleSave() {
|
|
52
|
+
saving.value = true
|
|
53
|
+
try { await saveMutation() }
|
|
54
|
+
finally { saving.value = false }
|
|
55
|
+
}
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<template>
|
|
59
|
+
<Button :disabled="saving" @click="handleSave">
|
|
60
|
+
<Loader2 v-if="saving" class="w-4 h-4 mr-2 animate-spin" />
|
|
61
|
+
{{ saving ? 'Saving...' : 'Save' }}
|
|
62
|
+
</Button>
|
|
63
|
+
</template>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Gotchas
|
|
67
|
+
- Always provide `aria-label` for icon-only buttons
|
|
68
|
+
- Use `type="button"` to prevent form submission unless intended
|
|
69
|
+
- Use `as="a"` prop to render as a link element with button styling
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Card
|
|
2
|
+
|
|
3
|
+
## Sub-components
|
|
4
|
+
| Component | Use for |
|
|
5
|
+
|-----------|---------|
|
|
6
|
+
| `Card` | Container wrapper |
|
|
7
|
+
| `CardHeader` | Title + description area |
|
|
8
|
+
| `CardTitle` | Main heading |
|
|
9
|
+
| `CardDescription` | Subtitle or description |
|
|
10
|
+
| `CardContent` | Main content area |
|
|
11
|
+
| `CardFooter` | Actions area |
|
|
12
|
+
|
|
13
|
+
## Skeleton Code
|
|
14
|
+
|
|
15
|
+
```vue
|
|
16
|
+
<script setup>
|
|
17
|
+
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, Button } from '@reinvented/design'
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<template>
|
|
21
|
+
<Card>
|
|
22
|
+
<CardHeader>
|
|
23
|
+
<CardTitle>Card Title</CardTitle>
|
|
24
|
+
<CardDescription>Card description text</CardDescription>
|
|
25
|
+
</CardHeader>
|
|
26
|
+
<CardContent>
|
|
27
|
+
<p>Card content goes here</p>
|
|
28
|
+
</CardContent>
|
|
29
|
+
<CardFooter>
|
|
30
|
+
<Button>Action</Button>
|
|
31
|
+
</CardFooter>
|
|
32
|
+
</Card>
|
|
33
|
+
</template>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Clickable Card
|
|
37
|
+
|
|
38
|
+
```vue
|
|
39
|
+
<template>
|
|
40
|
+
<Card class="transition-shadow duration-150 hover:shadow-md cursor-pointer" @click="navigate">
|
|
41
|
+
<!-- content -->
|
|
42
|
+
</Card>
|
|
43
|
+
</template>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Gotchas
|
|
47
|
+
- Don't nest cards inside cards
|
|
48
|
+
- Use `CardFooter` for actions, not `CardContent`
|
|
49
|
+
- Apply hover styles via `class` prop, not custom CSS
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Dialog
|
|
2
|
+
## When to Use
|
|
3
|
+
- Simple create/edit forms (≤ 5 fields)
|
|
4
|
+
- Confirmations
|
|
5
|
+
- Quick actions that keep page context
|
|
6
|
+
|
|
7
|
+
When NOT to use: Forms with 8+ fields (use full page), rich content editing (use full page).
|
|
8
|
+
|
|
9
|
+
## Sub-components
|
|
10
|
+
`Dialog`, `DialogTrigger`, `DialogContent`, `DialogHeader`, `DialogFooter`, `DialogTitle`, `DialogDescription`, `DialogClose`, `DialogScrollContent`
|
|
11
|
+
|
|
12
|
+
## Skeleton Code
|
|
13
|
+
```vue
|
|
14
|
+
<script setup>
|
|
15
|
+
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, Button, Input, Label } from '@reinvented/design'
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<Dialog>
|
|
20
|
+
<DialogTrigger as-child>
|
|
21
|
+
<Button>Create Item</Button>
|
|
22
|
+
</DialogTrigger>
|
|
23
|
+
<DialogContent>
|
|
24
|
+
<DialogHeader>
|
|
25
|
+
<DialogTitle>Create New Item</DialogTitle>
|
|
26
|
+
<DialogDescription>Fill in the details below.</DialogDescription>
|
|
27
|
+
</DialogHeader>
|
|
28
|
+
<div class="grid gap-4 py-4">
|
|
29
|
+
<div class="space-y-2">
|
|
30
|
+
<Label for="name">Name</Label>
|
|
31
|
+
<Input id="name" placeholder="Item name" />
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
<DialogFooter>
|
|
35
|
+
<Button variant="outline">Cancel</Button>
|
|
36
|
+
<Button>Save</Button>
|
|
37
|
+
</DialogFooter>
|
|
38
|
+
</DialogContent>
|
|
39
|
+
</Dialog>
|
|
40
|
+
</template>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Gotchas
|
|
44
|
+
- Use `as-child` on `DialogTrigger` to avoid nested buttons
|
|
45
|
+
- For long content, use `DialogScrollContent` instead of `DialogContent`
|
|
46
|
+
- Always include `DialogTitle` for accessibility (even if visually hidden)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# DropdownMenu
|
|
2
|
+
## When to Use
|
|
3
|
+
- Action menus on items (edit, delete, share)
|
|
4
|
+
- User profile menus
|
|
5
|
+
- More options (...) buttons
|
|
6
|
+
|
|
7
|
+
## Skeleton Code
|
|
8
|
+
```vue
|
|
9
|
+
<script setup>
|
|
10
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, Button } from '@reinvented/design'
|
|
11
|
+
import { MoreHorizontal, Pencil, Trash2 } from 'lucide-vue-next'
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<DropdownMenu>
|
|
16
|
+
<DropdownMenuTrigger as-child>
|
|
17
|
+
<Button variant="ghost" size="icon"><MoreHorizontal class="w-4 h-4" /></Button>
|
|
18
|
+
</DropdownMenuTrigger>
|
|
19
|
+
<DropdownMenuContent align="end">
|
|
20
|
+
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
|
21
|
+
<DropdownMenuSeparator />
|
|
22
|
+
<DropdownMenuItem><Pencil class="mr-2 h-4 w-4" /> Edit</DropdownMenuItem>
|
|
23
|
+
<DropdownMenuItem class="text-destructive"><Trash2 class="mr-2 h-4 w-4" /> Delete</DropdownMenuItem>
|
|
24
|
+
</DropdownMenuContent>
|
|
25
|
+
</DropdownMenu>
|
|
26
|
+
</template>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Gotchas
|
|
30
|
+
- Use `align="end"` for right-aligned menus
|
|
31
|
+
- Use `as-child` on trigger to compose with existing buttons
|
|
32
|
+
- Destructive items should use `class="text-destructive"`
|