@hubbiparts/uikit 0.1.0 → 0.2.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/bin/hubbiparts-uikit.mjs +244 -0
- package/dist/style.css +1 -1
- package/package.json +12 -2
- package/skills/hubbiparts-uikit/SKILL.md +149 -0
- package/skills/hubbiparts-uikit/rules/contributing.md +49 -0
- package/skills/hubbiparts-uikit/rules/maintenance.md +74 -0
- package/skills/hubbiparts-uikit/rules/setup.md +90 -0
- package/skills/hubbiparts-uikit/rules/theming.md +135 -0
- package/skills/hubbiparts-uikit/rules/usage.md +183 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Usage & Composition
|
|
2
|
+
|
|
3
|
+
The kit is shadcn/ui on the **Radix** base. Everything in the shadcn Radix docs applies, with these package-specific rules.
|
|
4
|
+
|
|
5
|
+
## Imports
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
// Correct
|
|
9
|
+
import { Button, Card, CardContent, cn } from '@hubbiparts/uikit'
|
|
10
|
+
|
|
11
|
+
// Incorrect — deep import, local copy, or shadcn alias
|
|
12
|
+
import { Button } from '@hubbiparts/uikit/dist/components/ui/button'
|
|
13
|
+
import { Button } from '@/components/ui/button'
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Check a component exists in the installed version before importing it: `npx hubbiparts-uikit list`.
|
|
17
|
+
|
|
18
|
+
## Custom triggers: `asChild`
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
// Correct
|
|
22
|
+
<DialogTrigger asChild>
|
|
23
|
+
<Button variant="outline">Open</Button>
|
|
24
|
+
</DialogTrigger>
|
|
25
|
+
|
|
26
|
+
// Incorrect — nested <button> inside <button>
|
|
27
|
+
<DialogTrigger>
|
|
28
|
+
<Button variant="outline">Open</Button>
|
|
29
|
+
</DialogTrigger>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`Combobox` is the one Base UI component in the kit: it takes `items` and uses `ComboboxInput` / `ComboboxContent` / `ComboboxList` / `ComboboxItem`, not `asChild`. Check `npx hubbiparts-uikit docs combobox`.
|
|
33
|
+
|
|
34
|
+
## Groups and items
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
<Select>
|
|
38
|
+
<SelectTrigger><SelectValue placeholder="Catalog" /></SelectTrigger>
|
|
39
|
+
<SelectContent>
|
|
40
|
+
<SelectGroup>
|
|
41
|
+
<SelectItem value="oem">OEM</SelectItem>
|
|
42
|
+
<SelectItem value="partner">Partner</SelectItem>
|
|
43
|
+
</SelectGroup>
|
|
44
|
+
</SelectContent>
|
|
45
|
+
</Select>
|
|
46
|
+
|
|
47
|
+
<Command>
|
|
48
|
+
<CommandInput placeholder="Search" />
|
|
49
|
+
<CommandList>
|
|
50
|
+
<CommandGroup heading="Parts">
|
|
51
|
+
<CommandItem value="filter">Oil filter</CommandItem>
|
|
52
|
+
</CommandGroup>
|
|
53
|
+
</CommandList>
|
|
54
|
+
</Command>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Overlays always have a title
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
<Sheet>
|
|
61
|
+
<SheetTrigger asChild><Button variant="outline">Details</Button></SheetTrigger>
|
|
62
|
+
<SheetContent>
|
|
63
|
+
<SheetHeader>
|
|
64
|
+
<SheetTitle>Part details</SheetTitle>
|
|
65
|
+
<SheetDescription>Review without leaving the catalog.</SheetDescription>
|
|
66
|
+
</SheetHeader>
|
|
67
|
+
</SheetContent>
|
|
68
|
+
</Sheet>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Hidden title: `<DialogTitle className="sr-only">Search</DialogTitle>`. Never add `z-index` to overlays.
|
|
72
|
+
|
|
73
|
+
## Forms
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
// Correct
|
|
77
|
+
<FieldGroup>
|
|
78
|
+
<Field data-invalid={!!errors.plate}>
|
|
79
|
+
<FieldLabel htmlFor="plate">Plate</FieldLabel>
|
|
80
|
+
<Input id="plate" aria-invalid={!!errors.plate} className="font-mono uppercase" />
|
|
81
|
+
<FieldDescription>Mercosul or legacy format.</FieldDescription>
|
|
82
|
+
{errors.plate && <FieldError>{errors.plate}</FieldError>}
|
|
83
|
+
</Field>
|
|
84
|
+
</FieldGroup>
|
|
85
|
+
|
|
86
|
+
// Incorrect
|
|
87
|
+
<div className="space-y-2">
|
|
88
|
+
<label>Plate</label>
|
|
89
|
+
<input className="border rounded px-2" />
|
|
90
|
+
<p className="text-red-500">Invalid</p>
|
|
91
|
+
</div>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- Buttons/icons inside inputs: `InputGroup` + `InputGroupInput` + `InputGroupAddon`, never a raw `Input` inside `InputGroup`.
|
|
95
|
+
- 2–7 exclusive options: `ToggleGroup`, not a row of `Button`s with manual active state.
|
|
96
|
+
- Related checkboxes/radios: `FieldSet` + `FieldLegend`.
|
|
97
|
+
- Disabled: `data-disabled` on `Field`, `disabled` on the control.
|
|
98
|
+
|
|
99
|
+
## Buttons, loading and icons
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import { Search } from 'lucide-react'
|
|
103
|
+
|
|
104
|
+
<Button>
|
|
105
|
+
<Search data-icon="inline-start" />
|
|
106
|
+
Search by plate
|
|
107
|
+
</Button>
|
|
108
|
+
|
|
109
|
+
<Button disabled={pending}>
|
|
110
|
+
{pending && <Spinner data-icon="inline-start" />}
|
|
111
|
+
Save
|
|
112
|
+
</Button>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
- No `isLoading` prop exists.
|
|
116
|
+
- No `size-4` / `w-4 h-4` on icons inside kit components — the component sizes them.
|
|
117
|
+
- Icon-only buttons: `size="icon"` plus `aria-label`.
|
|
118
|
+
|
|
119
|
+
## Cards
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
<Card>
|
|
123
|
+
<CardHeader>
|
|
124
|
+
<CardTitle>Inventory</CardTitle>
|
|
125
|
+
<CardDescription>Updated 2 min ago</CardDescription>
|
|
126
|
+
</CardHeader>
|
|
127
|
+
<CardContent>…</CardContent>
|
|
128
|
+
<CardFooter><Button variant="outline">Open</Button></CardFooter>
|
|
129
|
+
</Card>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Feedback
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
import { toast } from 'sonner'
|
|
136
|
+
|
|
137
|
+
toast.success('Catalog synchronized')
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
- Callouts: `Alert` + `AlertTitle` + `AlertDescription`.
|
|
141
|
+
- Empty states: `Empty` + `EmptyHeader` + `EmptyMedia` + `EmptyTitle` + `EmptyDescription`.
|
|
142
|
+
- Loading placeholders: `Skeleton`, not `animate-pulse` divs.
|
|
143
|
+
- Status: `Badge` variants, not colored spans.
|
|
144
|
+
- Dividers: `Separator`, not `<hr>` or `border-t` divs.
|
|
145
|
+
|
|
146
|
+
## Sidebar layouts
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
<SidebarProvider>
|
|
150
|
+
<Sidebar collapsible="icon">
|
|
151
|
+
<SidebarHeader>…</SidebarHeader>
|
|
152
|
+
<SidebarContent>
|
|
153
|
+
<SidebarGroup>
|
|
154
|
+
<SidebarGroupLabel>Catalog</SidebarGroupLabel>
|
|
155
|
+
<SidebarMenu>
|
|
156
|
+
<SidebarMenuItem>
|
|
157
|
+
<SidebarMenuButton isActive tooltip="Parts">Parts</SidebarMenuButton>
|
|
158
|
+
</SidebarMenuItem>
|
|
159
|
+
</SidebarMenu>
|
|
160
|
+
</SidebarGroup>
|
|
161
|
+
</SidebarContent>
|
|
162
|
+
<SidebarRail />
|
|
163
|
+
</Sidebar>
|
|
164
|
+
<SidebarInset>
|
|
165
|
+
<header><SidebarTrigger /></header>
|
|
166
|
+
<main>…</main>
|
|
167
|
+
</SidebarInset>
|
|
168
|
+
</SidebarProvider>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`useSidebar()` is exported for custom toggles. Needs `TooltipProvider` above it.
|
|
172
|
+
|
|
173
|
+
## Composition-only patterns
|
|
174
|
+
|
|
175
|
+
- **Data Table** — `Table` + sorting/filtering/pagination state (e.g. TanStack Table in the project). Keep table state in the feature, not in the kit.
|
|
176
|
+
- **Date Picker** — `Popover` + `PopoverTrigger asChild` (`Button`) + `PopoverContent` + `Calendar`.
|
|
177
|
+
- **Typography** — semantic HTML + `font-display` / `font-sans` / `font-mono` tokens.
|
|
178
|
+
|
|
179
|
+
## When the kit lacks something
|
|
180
|
+
|
|
181
|
+
1. Compose it from kit components in a feature folder (e.g. `src/features/parts/PlateSearch.tsx`), not in `components/ui`.
|
|
182
|
+
2. Tell the user it is a kit contribution candidate (see [contributing.md](./contributing.md)).
|
|
183
|
+
3. Never copy a shadcn component into the consumer when the kit already ships it.
|