@aircall/ds 0.14.0 → 0.15.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.
Files changed (34) hide show
  1. package/README.md +31 -0
  2. package/dist/globals.css +1 -1
  3. package/dist/index.d.ts +28 -28
  4. package/dist/index.js +1 -1
  5. package/package.json +12 -2
  6. package/skills/aircall-ds/migrate-icons/SKILL.md +346 -0
  7. package/skills/aircall-ds/migrate-tractor/SKILL.md +314 -0
  8. package/skills/aircall-ds/migrate-tractor/accordion/SKILL.md +276 -0
  9. package/skills/aircall-ds/migrate-tractor/alert/SKILL.md +225 -0
  10. package/skills/aircall-ds/migrate-tractor/avatar/SKILL.md +272 -0
  11. package/skills/aircall-ds/migrate-tractor/badge/SKILL.md +274 -0
  12. package/skills/aircall-ds/migrate-tractor/button/SKILL.md +277 -0
  13. package/skills/aircall-ds/migrate-tractor/card/SKILL.md +278 -0
  14. package/skills/aircall-ds/migrate-tractor/combobox/SKILL.md +346 -0
  15. package/skills/aircall-ds/migrate-tractor/data-table/SKILL.md +333 -0
  16. package/skills/aircall-ds/migrate-tractor/dialog/SKILL.md +206 -0
  17. package/skills/aircall-ds/migrate-tractor/divider/SKILL.md +226 -0
  18. package/skills/aircall-ds/migrate-tractor/dropdown-menu/SKILL.md +266 -0
  19. package/skills/aircall-ds/migrate-tractor/dropzone/SKILL.md +338 -0
  20. package/skills/aircall-ds/migrate-tractor/form-and-field/SKILL.md +325 -0
  21. package/skills/aircall-ds/migrate-tractor/gauge/SKILL.md +248 -0
  22. package/skills/aircall-ds/migrate-tractor/input/SKILL.md +261 -0
  23. package/skills/aircall-ds/migrate-tractor/item/SKILL.md +298 -0
  24. package/skills/aircall-ds/migrate-tractor/link/SKILL.md +263 -0
  25. package/skills/aircall-ds/migrate-tractor/popover/SKILL.md +214 -0
  26. package/skills/aircall-ds/migrate-tractor/select/SKILL.md +245 -0
  27. package/skills/aircall-ds/migrate-tractor/sheet-vs-drawer/SKILL.md +272 -0
  28. package/skills/aircall-ds/migrate-tractor/skeleton/SKILL.md +190 -0
  29. package/skills/aircall-ds/migrate-tractor/styling/SKILL.md +421 -0
  30. package/skills/aircall-ds/migrate-tractor/tabs/SKILL.md +250 -0
  31. package/skills/aircall-ds/migrate-tractor/toast/SKILL.md +322 -0
  32. package/skills/aircall-ds/migrate-tractor/tooltip/SKILL.md +204 -0
  33. package/skills/aircall-ds/migrate-tractor/tree/SKILL.md +346 -0
  34. package/skills/aircall-ds/setup/SKILL.md +347 -0
@@ -0,0 +1,272 @@
1
+ ---
2
+ name: aircall-ds/migrate-tractor/sheet-vs-drawer
3
+ description: >
4
+ Migrate Tractor Drawer (desktop side panel) to @aircall/ds Sheet or Drawer.
5
+ Covers SheetContent side prop, DrawerPopup vs DrawerContent confusion, and
6
+ the render prop pattern for Trigger/Close. Load when a file imports Drawer
7
+ from @aircall/tractor.
8
+ type: sub-skill
9
+ library: aircall-ds
10
+ library_version: "0.13.0"
11
+ requires:
12
+ - aircall-ds/setup
13
+ - aircall-ds/migrate-tractor
14
+ sources:
15
+ - "aircall/hydra:docs/migration-guides/tractor-to-ds/recipes/sheet-vs-drawer.md"
16
+ ---
17
+
18
+ This skill builds on aircall-ds/migrate-tractor. Apply all cross-cutting rules from that skill (prop renames, `render` prop, data attributes) before the sheet-vs-drawer-specific steps below.
19
+
20
+ ## 1. Which component to use
21
+
22
+ DS ships two distinct side-panel components. The Tractor `Drawer` maps to **`Sheet`** for desktop side panels — not to DS's `Drawer`. DS's own `Drawer` is reserved for mobile-style panels with swipe-to-dismiss edge gestures.
23
+
24
+ | Use case | DS component | Built on |
25
+ | --- | --- | --- |
26
+ | Persistent side panel (navigation, filters, settings) | `Sheet` | Base UI Dialog |
27
+ | Mobile-style swipe-to-dismiss edge panel | `Drawer` | Base UI Drawer (Coss UI) |
28
+
29
+ When in doubt, use `Sheet`.
30
+
31
+ ## 2. Component mapping — Tractor Drawer → DS Sheet
32
+
33
+ | Tractor | @aircall/ds |
34
+ | --- | --- |
35
+ | `Drawer` (root + state) | `Sheet` |
36
+ | `DrawerHeader` | `SheetHeader` |
37
+ | `DrawerTitle` | `SheetTitle` |
38
+ | `DrawerBody` / body content | plain children inside `SheetContent` |
39
+ | `DrawerFooter` | `SheetFooter` |
40
+ | — | `SheetContent` (the panel popup; carries the `side` prop) |
41
+ | — | `SheetTrigger` (uncontrolled open trigger) |
42
+ | — | `SheetClose` (any element that closes the sheet) |
43
+ | — | `SheetDescription` (optional accessible subtitle) |
44
+
45
+ ## 3. Component mapping — DS Drawer parts (swipe use case only)
46
+
47
+ | DS Drawer part | Role |
48
+ | --- | --- |
49
+ | `Drawer` | Root state owner; accepts `position` and `open`/`onOpenChange` |
50
+ | `DrawerPopup` | The panel surface — **use this, not `DrawerContent`** |
51
+ | `DrawerHeader` | Header section inside `DrawerPopup` |
52
+ | `DrawerTitle` | Accessible title inside `DrawerHeader` |
53
+ | `DrawerFooter` | Footer section inside `DrawerPopup` |
54
+ | `DrawerClose` | Any element that closes the drawer |
55
+ | `DrawerTrigger` | Uncontrolled open trigger |
56
+
57
+ ## 4. Before / After — Sheet (desktop side panel)
58
+
59
+ ### Before (Tractor)
60
+
61
+ ```tsx
62
+ import { Drawer, DrawerHeader, DrawerTitle, DrawerBody, DrawerFooter, Button } from '@aircall/tractor';
63
+
64
+ <Drawer isOpen={isOpen} onClose={() => setIsOpen(false)} position="right">
65
+ <DrawerHeader>
66
+ <DrawerTitle>Filters</DrawerTitle>
67
+ </DrawerHeader>
68
+ <DrawerBody>
69
+ <p>Refine the call list.</p>
70
+ </DrawerBody>
71
+ <DrawerFooter>
72
+ <Button variant="outline" onClick={() => setIsOpen(false)}>Cancel</Button>
73
+ <Button onClick={onApply}>Apply</Button>
74
+ </DrawerFooter>
75
+ </Drawer>
76
+ ```
77
+
78
+ ### After (DS Sheet)
79
+
80
+ ```tsx
81
+ import {
82
+ Sheet,
83
+ SheetClose,
84
+ SheetContent,
85
+ SheetDescription,
86
+ SheetFooter,
87
+ SheetHeader,
88
+ SheetTitle,
89
+ Button
90
+ } from '@aircall/ds';
91
+
92
+ <Sheet open={isOpen} onOpenChange={setIsOpen}>
93
+ <SheetContent side="right">
94
+ <SheetHeader>
95
+ <SheetTitle>Filters</SheetTitle>
96
+ <SheetDescription>Refine the call list.</SheetDescription>
97
+ </SheetHeader>
98
+
99
+ <p className="text-sm">Refine the call list.</p>
100
+
101
+ <SheetFooter>
102
+ <SheetClose render={<Button variant="outline" size="lg" />}>
103
+ Cancel
104
+ </SheetClose>
105
+ <Button size="lg" onClick={onApply}>Apply</Button>
106
+ </SheetFooter>
107
+ </SheetContent>
108
+ </Sheet>
109
+ ```
110
+
111
+ Key changes:
112
+ - `isOpen` → `open`; `onClose()` → `onOpenChange(boolean)`
113
+ - Tractor `position="right"` → `SheetContent side="right"` (prop moved to the panel part)
114
+ - `DrawerBody` is removed — body content is plain children inside `SheetContent`
115
+ - `SheetClose` wraps any button that closes the sheet; pass the DS `Button` via `render` and put the label as children of `SheetClose`
116
+ - `SheetContent` renders a default "×" close button; hide it with `showCloseButton={false}` when you want to force explicit footer actions
117
+
118
+ ### Uncontrolled with a trigger
119
+
120
+ ```tsx
121
+ import { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetFooter, SheetClose, Button } from '@aircall/ds';
122
+
123
+ <Sheet>
124
+ <SheetTrigger render={<Button size="lg" />}>Open filters</SheetTrigger>
125
+ <SheetContent side="right">
126
+ <SheetHeader>
127
+ <SheetTitle>Filters</SheetTitle>
128
+ </SheetHeader>
129
+ <p className="text-sm">Adjust your filters.</p>
130
+ <SheetFooter>
131
+ <SheetClose render={<Button variant="outline" size="lg" />}>Close</SheetClose>
132
+ </SheetFooter>
133
+ </SheetContent>
134
+ </Sheet>
135
+ ```
136
+
137
+ ## 5. Before / After — Drawer (swipe-to-dismiss, mobile)
138
+
139
+ ### After (DS Drawer)
140
+
141
+ ```tsx
142
+ import {
143
+ Drawer,
144
+ DrawerClose,
145
+ DrawerFooter,
146
+ DrawerHeader,
147
+ DrawerPopup,
148
+ DrawerTitle,
149
+ DrawerTrigger,
150
+ Button
151
+ } from '@aircall/ds';
152
+
153
+ <Drawer open={isOpen} onOpenChange={setIsOpen} position="right">
154
+ <DrawerPopup>
155
+ <DrawerHeader>
156
+ <DrawerTitle>Action sheet</DrawerTitle>
157
+ </DrawerHeader>
158
+ <div className="p-4">
159
+ <p className="text-sm">Swipe to dismiss.</p>
160
+ </div>
161
+ <DrawerFooter>
162
+ <DrawerClose render={<Button size="lg" />}>Done</DrawerClose>
163
+ </DrawerFooter>
164
+ </DrawerPopup>
165
+ </Drawer>
166
+ ```
167
+
168
+ ---
169
+
170
+ ## 6. Common mistakes
171
+
172
+ ### Mistake 1 — Using `position` on `SheetContent` instead of `side`
173
+
174
+ ```tsx
175
+ // ❌ Wrong — position is a Tractor prop; SheetContent has no position prop
176
+ <SheetContent position="right">…</SheetContent>
177
+
178
+ // ✅ Correct — the edge is controlled by side on SheetContent
179
+ <SheetContent side="right">…</SheetContent>
180
+ ```
181
+
182
+ `SheetContent` accepts `side?: 'top' | 'right' | 'bottom' | 'left'`. The Tractor `position` prop is silently dropped; the sheet defaults to `side="right"` so the bug is invisible until a non-right position is needed.
183
+
184
+ Source: `packages/ds/src/components/sheet.tsx`
185
+
186
+ ---
187
+
188
+ ### Mistake 2 — Using `DrawerContent` as the panel wrapper instead of `DrawerPopup`
189
+
190
+ ```tsx
191
+ // ❌ Wrong — DrawerContent is a thin inner drag-interaction primitive, not the panel
192
+ import { Drawer, DrawerContent } from '@aircall/ds';
193
+
194
+ <Drawer open={isOpen} onOpenChange={setIsOpen}>
195
+ <DrawerContent>
196
+ <p>Body</p>
197
+ </DrawerContent>
198
+ </Drawer>
199
+
200
+ // ✅ Correct — DrawerPopup is the full panel surface with backdrop, viewport, and styling
201
+ import { Drawer, DrawerPopup } from '@aircall/ds';
202
+
203
+ <Drawer open={isOpen} onOpenChange={setIsOpen}>
204
+ <DrawerPopup>
205
+ <p>Body</p>
206
+ </DrawerPopup>
207
+ </Drawer>
208
+ ```
209
+
210
+ `DrawerContent` is a Base UI primitive that enables text selection within drag targets — it is not a panel container. `DrawerPopup` composes the backdrop, viewport, and panel surface and is the correct high-level wrapper.
211
+
212
+ Source: `packages/ds/src/components/drawer.tsx`
213
+
214
+ ---
215
+
216
+ ### Mistake 3 — Using `asChild` on SheetTrigger or SheetClose instead of `render`
217
+
218
+ ```tsx
219
+ // ❌ Wrong — asChild is a Radix pattern; DS uses Base UI's render prop
220
+ <SheetClose asChild>
221
+ <Button variant="outline" size="lg">Cancel</Button>
222
+ </SheetClose>
223
+
224
+ // ✅ Correct — pass the DS Button via render; label goes as children of SheetClose
225
+ <SheetClose render={<Button variant="outline" size="lg" />}>
226
+ Cancel
227
+ </SheetClose>
228
+ ```
229
+
230
+ DS is built on Base UI, which uses a `render` prop instead of Radix's `asChild`. `asChild` is silently ignored — `SheetClose` still renders its own default element, the Button is never mounted, and the close handler is lost.
231
+
232
+ Source: `packages/ds/src/components/sheet.tsx`
233
+
234
+ ---
235
+
236
+ ### Mistake 4 — Mapping Tractor Drawer to DS Drawer for a desktop side panel
237
+
238
+ ```tsx
239
+ // ❌ Wrong — DS Drawer is for swipe-to-dismiss mobile panels, not desktop side panels
240
+ import { Drawer, DrawerPopup } from '@aircall/ds';
241
+
242
+ <Drawer open={isOpen} onOpenChange={setIsOpen} position="right">
243
+ <DrawerPopup>…</DrawerPopup>
244
+ </Drawer>
245
+
246
+ // ✅ Correct — Tractor Drawer (desktop) maps to DS Sheet
247
+ import { Sheet, SheetContent } from '@aircall/ds';
248
+
249
+ <Sheet open={isOpen} onOpenChange={setIsOpen}>
250
+ <SheetContent side="right">…</SheetContent>
251
+ </Sheet>
252
+ ```
253
+
254
+ The naming is intentionally different: Tractor's `Drawer` was a general side panel. DS splits the concept in two — `Sheet` for persistent desktop panels and `Drawer` for mobile swipe gestures. Using DS `Drawer` for desktop panels adds unnecessary drag/swipe infrastructure and may produce unexpected dismiss behavior on touch devices.
255
+
256
+ Source: `packages/ds/src/components/sheet.tsx`
257
+
258
+ ---
259
+
260
+ ### Mistake 5 — Using `onClose` instead of `onOpenChange`
261
+
262
+ ```tsx
263
+ // ❌ Wrong — onClose is a Tractor prop; DS ignores it silently
264
+ <Sheet open={isOpen} onClose={() => setIsOpen(false)}>…</Sheet>
265
+
266
+ // ✅ Correct — onOpenChange receives the new boolean state
267
+ <Sheet open={isOpen} onOpenChange={setIsOpen}>…</Sheet>
268
+ ```
269
+
270
+ `onOpenChange` fires with `false` when the sheet closes (backdrop click, Escape, or `SheetClose`). The Tractor `onClose()` callback is not forwarded and the sheet becomes uncontrollable — it opens but never closes.
271
+
272
+ Source: `packages/ds/src/components/sheet.tsx`
@@ -0,0 +1,190 @@
1
+ ---
2
+ name: aircall-ds/migrate-tractor/skeleton
3
+ description: >
4
+ Migrate Tractor Skeleton to the @aircall/ds Skeleton. Load when a file
5
+ imports Skeleton from @aircall/tractor. Covers the removal of shape/animation/mode
6
+ props and the className-based sizing pattern that replaces Tractor's BoxProps.
7
+ type: sub-skill
8
+ library: aircall-ds
9
+ library_version: "0.13.0"
10
+ requires:
11
+ - aircall-ds/setup
12
+ - aircall-ds/migrate-tractor
13
+ sources:
14
+ - "aircall/hydra:packages/ds/src/components/skeleton.tsx"
15
+ ---
16
+
17
+ This skill builds on aircall-ds/migrate-tractor.
18
+
19
+ ## 1. Component mapping
20
+
21
+ Tractor `Skeleton` was a styled `Box` wrapper with `shape`, `animation`, `mode`, and `animationDelay` props. DS `Skeleton` is a plain `div` with a fixed pulse animation and rounded corners — sizing and shape are controlled entirely through `className`.
22
+
23
+ | Tractor part | DS replacement | Notes |
24
+ | --- | --- | --- |
25
+ | `<Skeleton>` | `<Skeleton>` | Direct replacement — drop Tractor-specific props |
26
+ | `shape="squareRounded"` | _(default)_ | DS always renders with `rounded-md`; no prop needed |
27
+ | `shape="circle"` | `className="rounded-full"` | Override the default `rounded-md` with `rounded-full` |
28
+ | `shape="square"` | `className="rounded-none"` | Override with `rounded-none` |
29
+ | `shape="squircle"` | `className="rounded-xl"` | Closest equivalent; pick visually |
30
+ | `animation="shimmer"` | _(not available)_ | DS has one animation (`animate-pulse`); no shimmer variant |
31
+ | `animation="wave"` | _(default)_ | DS default pulse covers this |
32
+ | `animationDelay` | `className="[animation-delay:200ms]"` | Use an arbitrary Tailwind value |
33
+ | `mode="dark"` | `className="bg-muted/60"` | DS uses `bg-muted`; adjust opacity for dark contexts |
34
+ | BoxProps (`w`, `h`, `width`, `height`) | `className="w-… h-…"` | Pass Tailwind sizing utilities via `className` |
35
+
36
+ ## 2. Verified DS export (`packages/ds/src/index.ts`)
37
+
38
+ ```
39
+ Skeleton
40
+ ```
41
+
42
+ ## 3. Imports
43
+
44
+ ```tsx
45
+ import { Skeleton } from '@aircall/ds';
46
+ ```
47
+
48
+ ## 4. Before / After examples
49
+
50
+ ### 4a. Default squareRounded skeleton (text line placeholder)
51
+
52
+ **Before (Tractor):**
53
+ ```tsx
54
+ import { Skeleton } from '@aircall/tractor';
55
+
56
+ <Skeleton shape="squareRounded" w="200px" h="16px" />
57
+ ```
58
+
59
+ **After (DS):**
60
+ ```tsx
61
+ import { Skeleton } from '@aircall/ds';
62
+
63
+ <Skeleton className="w-[200px] h-4" />
64
+ ```
65
+
66
+ The DS default already applies `rounded-md`, so `shape="squareRounded"` requires no prop. Width and height move to Tailwind utilities in `className`.
67
+
68
+ ### 4b. Circle skeleton (avatar placeholder)
69
+
70
+ **Before (Tractor):**
71
+ ```tsx
72
+ import { Skeleton } from '@aircall/tractor';
73
+
74
+ <Skeleton shape="circle" w="40px" h="40px" />
75
+ ```
76
+
77
+ **After (DS):**
78
+ ```tsx
79
+ import { Skeleton } from '@aircall/ds';
80
+
81
+ <Skeleton className="size-10 rounded-full" />
82
+ ```
83
+
84
+ `shape="circle"` maps to `rounded-full`. Use `size-10` (40px) for an exact match, or `size-8` / `size-12` for other avatar sizes.
85
+
86
+ ### 4c. Card skeleton layout (multiple lines)
87
+
88
+ **Before (Tractor):**
89
+ ```tsx
90
+ import { Skeleton } from '@aircall/tractor';
91
+
92
+ <div>
93
+ <Skeleton shape="circle" w="48px" h="48px" />
94
+ <Skeleton shape="squareRounded" w="120px" h="14px" animationDelay />
95
+ <Skeleton shape="squareRounded" w="80px" h="14px" animationDelay />
96
+ </div>
97
+ ```
98
+
99
+ **After (DS):**
100
+ ```tsx
101
+ import { Skeleton } from '@aircall/ds';
102
+
103
+ <div>
104
+ <Skeleton className="size-12 rounded-full" />
105
+ <Skeleton className="w-[120px] h-3.5 [animation-delay:200ms]" />
106
+ <Skeleton className="w-20 h-3.5 [animation-delay:200ms]" />
107
+ </div>
108
+ ```
109
+
110
+ ### 4d. Square skeleton (image placeholder)
111
+
112
+ **Before (Tractor):**
113
+ ```tsx
114
+ import { Skeleton } from '@aircall/tractor';
115
+
116
+ <Skeleton shape="square" w="64px" h="64px" />
117
+ ```
118
+
119
+ **After (DS):**
120
+ ```tsx
121
+ import { Skeleton } from '@aircall/ds';
122
+
123
+ <Skeleton className="size-16 rounded-none" />
124
+ ```
125
+
126
+ ## 5. Common Mistakes
127
+
128
+ ### Mistake 1 — Passing `shape` as a prop to the DS Skeleton
129
+
130
+ **Wrong:**
131
+ ```tsx
132
+ import { Skeleton } from '@aircall/ds';
133
+
134
+ <Skeleton shape="circle" w="40px" h="40px" />
135
+ ```
136
+
137
+ **Correct:**
138
+ ```tsx
139
+ import { Skeleton } from '@aircall/ds';
140
+
141
+ <Skeleton className="size-10 rounded-full" />
142
+ ```
143
+
144
+ DS `Skeleton` extends `React.ComponentProps<'div'>` — it has no `shape` prop. Passing `shape` forwards an unknown attribute to the DOM (a React warning) and the element renders as the default `rounded-md` rectangle, not a circle.
145
+
146
+ Source: `packages/ds/src/components/skeleton.tsx`
147
+
148
+ ---
149
+
150
+ ### Mistake 2 — Using BoxProps (`w`, `h`) instead of `className` for sizing
151
+
152
+ **Wrong:**
153
+ ```tsx
154
+ import { Skeleton } from '@aircall/ds';
155
+
156
+ <Skeleton w="200px" h="16px" />
157
+ ```
158
+
159
+ **Correct:**
160
+ ```tsx
161
+ import { Skeleton } from '@aircall/ds';
162
+
163
+ <Skeleton className="w-[200px] h-4" />
164
+ ```
165
+
166
+ Tractor `Skeleton` extended `BoxProps` from `@xstyled/styled-components`, so `w` and `h` were valid styled-system props. DS `Skeleton` is a plain `div` — `w` and `h` are not recognized and will be forwarded as invalid HTML attributes, producing DOM warnings and no visual effect on sizing.
167
+
168
+ Source: `packages/ds/src/components/skeleton.tsx`
169
+
170
+ ---
171
+
172
+ ### Mistake 3 — Expecting a `animation="shimmer"` variant
173
+
174
+ **Wrong:**
175
+ ```tsx
176
+ import { Skeleton } from '@aircall/ds';
177
+
178
+ <Skeleton animation="shimmer" className="w-32 h-4" />
179
+ ```
180
+
181
+ **Correct:**
182
+ ```tsx
183
+ import { Skeleton } from '@aircall/ds';
184
+
185
+ <Skeleton className="w-32 h-4" />
186
+ ```
187
+
188
+ DS `Skeleton` has exactly one animation: `animate-pulse` (a CSS opacity pulse). There is no shimmer or wave variant. The `animation` prop does not exist on the DS component — passing it forwards the string to the DOM and triggers a React invalid-prop warning. Use the single DS animation as-is, or override with an arbitrary Tailwind animation utility if a shimmer effect is required for a specific design.
189
+
190
+ Source: `packages/ds/src/components/skeleton.tsx`