@aircall/ds 0.13.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.
- package/README.md +31 -0
- package/dist/globals.css +1 -1
- package/dist/index.d.ts +94 -33
- package/dist/index.js +292 -42
- package/package.json +16 -3
- package/skills/aircall-ds/migrate-icons/SKILL.md +346 -0
- package/skills/aircall-ds/migrate-tractor/SKILL.md +314 -0
- package/skills/aircall-ds/migrate-tractor/accordion/SKILL.md +276 -0
- package/skills/aircall-ds/migrate-tractor/alert/SKILL.md +225 -0
- package/skills/aircall-ds/migrate-tractor/avatar/SKILL.md +272 -0
- package/skills/aircall-ds/migrate-tractor/badge/SKILL.md +274 -0
- package/skills/aircall-ds/migrate-tractor/button/SKILL.md +277 -0
- package/skills/aircall-ds/migrate-tractor/card/SKILL.md +278 -0
- package/skills/aircall-ds/migrate-tractor/combobox/SKILL.md +346 -0
- package/skills/aircall-ds/migrate-tractor/data-table/SKILL.md +333 -0
- package/skills/aircall-ds/migrate-tractor/dialog/SKILL.md +206 -0
- package/skills/aircall-ds/migrate-tractor/divider/SKILL.md +226 -0
- package/skills/aircall-ds/migrate-tractor/dropdown-menu/SKILL.md +266 -0
- package/skills/aircall-ds/migrate-tractor/dropzone/SKILL.md +338 -0
- package/skills/aircall-ds/migrate-tractor/form-and-field/SKILL.md +325 -0
- package/skills/aircall-ds/migrate-tractor/gauge/SKILL.md +248 -0
- package/skills/aircall-ds/migrate-tractor/input/SKILL.md +261 -0
- package/skills/aircall-ds/migrate-tractor/item/SKILL.md +298 -0
- package/skills/aircall-ds/migrate-tractor/link/SKILL.md +263 -0
- package/skills/aircall-ds/migrate-tractor/popover/SKILL.md +214 -0
- package/skills/aircall-ds/migrate-tractor/select/SKILL.md +245 -0
- package/skills/aircall-ds/migrate-tractor/sheet-vs-drawer/SKILL.md +272 -0
- package/skills/aircall-ds/migrate-tractor/skeleton/SKILL.md +190 -0
- package/skills/aircall-ds/migrate-tractor/styling/SKILL.md +421 -0
- package/skills/aircall-ds/migrate-tractor/tabs/SKILL.md +250 -0
- package/skills/aircall-ds/migrate-tractor/toast/SKILL.md +322 -0
- package/skills/aircall-ds/migrate-tractor/tooltip/SKILL.md +204 -0
- package/skills/aircall-ds/migrate-tractor/tree/SKILL.md +346 -0
- package/skills/aircall-ds/setup/SKILL.md +347 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: aircall-ds/migrate-icons
|
|
3
|
+
description: >
|
|
4
|
+
Migrate icons from @aircall/icons to @aircall/react-icons — the old→new name map,
|
|
5
|
+
color/size → Tailwind, custom & brand icons. Works standalone (an icons-only swap)
|
|
6
|
+
or inside a Tractor migration (also drops Tractor's <Icon> wrapper). Load when a file
|
|
7
|
+
imports any named icon from @aircall/icons, or Icon from @aircall/tractor.
|
|
8
|
+
type: sub-skill
|
|
9
|
+
library: aircall-ds
|
|
10
|
+
library_version: "0.13.0"
|
|
11
|
+
requires:
|
|
12
|
+
- aircall-ds/setup
|
|
13
|
+
sources:
|
|
14
|
+
- "aircall/hydra:docs/migration-guides/tractor-to-ds/06-react-icons.md"
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
Migrate icons from `@aircall/icons` to `@aircall/react-icons`. This is **independent of
|
|
18
|
+
the Tractor migration** — run it on its own for an icons-only swap, or as part of
|
|
19
|
+
`aircall-ds/migrate-tractor`. The name / color / size mappings below apply whether an
|
|
20
|
+
icon is rendered directly (`<SomeIcon />`) or through Tractor's `<Icon component={…} />`
|
|
21
|
+
wrapper; when it was wrapped in Tractor's `<Icon>`, also remove that wrapper (see §1 and §7).
|
|
22
|
+
|
|
23
|
+
> **Upgrade `@aircall/react-icons` to `>= 0.4.0` as part of this migration.** `@aircall/ds`
|
|
24
|
+
> itself imports flags (`CountryFlag` → `FlagUs`, …) from it; an older version (≤ 0.3.0)
|
|
25
|
+
> breaks the ds bundle at build time, not just your own icon imports. `pnpm add @aircall/react-icons@latest`.
|
|
26
|
+
|
|
27
|
+
## 1. What changes
|
|
28
|
+
|
|
29
|
+
| Tractor part | @aircall/react-icons part |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| `import { Icon } from '@aircall/tractor'` | _(removed — no wrapper needed)_ |
|
|
32
|
+
| `import { SomeIcon } from '@aircall/icons'` | `import { NewName } from '@aircall/react-icons'` |
|
|
33
|
+
| `<Icon component={SomeIcon} size={N} color="primary.500" />` | `<NewName className="size-N text-primary" />` |
|
|
34
|
+
| `color="…"` (Tractor token) | `text-*` Tailwind class (see color table) |
|
|
35
|
+
| `size={N}` (number) | `size-N` Tailwind class (`size-4`=16px, `size-5`=20px, `size-6`=24px) |
|
|
36
|
+
|
|
37
|
+
`@aircall/react-icons` re-exports all lucide icons plus a set of Aircall custom icons. Never import from `lucide-react` directly.
|
|
38
|
+
|
|
39
|
+
## 2. Color mapping
|
|
40
|
+
|
|
41
|
+
| Tractor `color` value | Tailwind class |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| `primary.500` | `text-primary` |
|
|
44
|
+
| `critical.500` | `text-destructive` |
|
|
45
|
+
| `success.500` | `text-success` |
|
|
46
|
+
| `warning.500` | `text-warning` |
|
|
47
|
+
| `informative.500` | `text-info` |
|
|
48
|
+
| `text.base` | `text-foreground` |
|
|
49
|
+
| `text.secondary` | `text-muted-foreground` |
|
|
50
|
+
|
|
51
|
+
## 3. Size mapping
|
|
52
|
+
|
|
53
|
+
| Tractor `size` | Tailwind class | px |
|
|
54
|
+
| --- | --- | --- |
|
|
55
|
+
| `16` | `size-4` | 16px |
|
|
56
|
+
| `20` | `size-5` | 20px |
|
|
57
|
+
| `24` | `size-6` | 24px |
|
|
58
|
+
|
|
59
|
+
## 4. Icon name mapping (selected)
|
|
60
|
+
|
|
61
|
+
This is a representative sample. For the full table consult the icon name tables in the migration guide.
|
|
62
|
+
|
|
63
|
+
### Phone & Calls
|
|
64
|
+
|
|
65
|
+
| Old (`@aircall/icons`) | New (`@aircall/react-icons`) | Source |
|
|
66
|
+
| --- | --- | --- |
|
|
67
|
+
| `CallFilled`, `CallOutlined`, `CallCircleFilled` | `Phone` | lucide |
|
|
68
|
+
| `HangUpFilled` | `PhoneDecline` | custom |
|
|
69
|
+
| `HangUpOutlined` | `PhoneOff` | lucide |
|
|
70
|
+
| `MissedInboundFilled` | `PhoneMissed` | lucide |
|
|
71
|
+
| `TransferFilled`, `TransferredOutlined` | `Forward` | lucide |
|
|
72
|
+
| `VoicemailOutlined` | `Voicemail` | lucide |
|
|
73
|
+
| `VoicemailDrop` | `VoicemailDrop` | custom |
|
|
74
|
+
| `RingingFilled`, `CircledPhoneCallingFilled` | `PhoneCall` | lucide |
|
|
75
|
+
| `KeypadFilled`, `KeypadOutlined` | `Keypad` | custom |
|
|
76
|
+
| `ConferenceFilled`, `ConferenceOutlined` | `Conference` | custom |
|
|
77
|
+
|
|
78
|
+
### Actions
|
|
79
|
+
|
|
80
|
+
| Old (`@aircall/icons`) | New (`@aircall/react-icons`) | Source |
|
|
81
|
+
| --- | --- | --- |
|
|
82
|
+
| `CloseOutlined`, `CloseCircleFilled` | `X` | lucide |
|
|
83
|
+
| `CheckOutlined`, `TickOutlined` | `Check` | lucide |
|
|
84
|
+
| `SearchOutlined` | `Search` | lucide |
|
|
85
|
+
| `EditFilled`, `EditOutlined` | `Pencil` | lucide |
|
|
86
|
+
| `TrashFilled`, `TrashOutlined` | `Trash2` | lucide |
|
|
87
|
+
| `CopyFilled`, `CopyOutlined` | `Copy` | lucide |
|
|
88
|
+
| `FilterOutlined`, `FilterFilled` | `ListFilter` | lucide |
|
|
89
|
+
| `AddCircleFilled`, `PlusCircleFilled` | `Plus` | lucide |
|
|
90
|
+
|
|
91
|
+
### Arrows & Navigation
|
|
92
|
+
|
|
93
|
+
| Old (`@aircall/icons`) | New (`@aircall/react-icons`) | Source |
|
|
94
|
+
| --- | --- | --- |
|
|
95
|
+
| `ChevronDownOutlined`, `ArrowDownFilled` | `ChevronDown` | lucide |
|
|
96
|
+
| `ChevronLeftOutlined` | `ChevronLeft` | lucide |
|
|
97
|
+
| `ChevronRightOutlined`, `ArrowRightFilled` | `ChevronRight` | lucide |
|
|
98
|
+
| `ChevronUpOutlined`, `ArrowUpFilled` | `ChevronUp` | lucide |
|
|
99
|
+
| `SendFilled`, `SendOutlined` | `Send` | lucide |
|
|
100
|
+
| `RefreshOutlined` | `RefreshCw` | lucide |
|
|
101
|
+
|
|
102
|
+
### Audio & Video
|
|
103
|
+
|
|
104
|
+
| Old (`@aircall/icons`) | New (`@aircall/react-icons`) | Source |
|
|
105
|
+
| --- | --- | --- |
|
|
106
|
+
| `PlayFilled`, `PlayOutlined` | `Play` | lucide |
|
|
107
|
+
| `PauseFilled`, `PauseOutlined`, `HoldFilled` | `Pause` | lucide |
|
|
108
|
+
| `MicOnFilled`, `MicOnOutlined` | `Mic` | lucide |
|
|
109
|
+
| `MicOffFilled`, `MicOffOutlined` | `MicOff` | lucide |
|
|
110
|
+
| `SoundHighFilled`, `SoundHighOutlined` | `Volume2` | lucide |
|
|
111
|
+
| `HeadsetFilled`, `HeadsetOutlined` | `Headset` | lucide |
|
|
112
|
+
| `ReplayFilled`, `ReplayOutlined` | `Replay` | custom |
|
|
113
|
+
|
|
114
|
+
### Users & Contacts
|
|
115
|
+
|
|
116
|
+
| Old (`@aircall/icons`) | New (`@aircall/react-icons`) | Source |
|
|
117
|
+
| --- | --- | --- |
|
|
118
|
+
| `UserFilled`, `UserOutlined` | `UserRound` | lucide |
|
|
119
|
+
| `PeopleFilled`, `PeopleOutlined` | `UsersRound` | lucide |
|
|
120
|
+
| `ContactsFilled`, `ContactsOutlined` | `ContactRound` | lucide |
|
|
121
|
+
| `AssignedFilled`, `AssignedOutlined` | `Assigned` | custom |
|
|
122
|
+
| `CompanyFilled`, `CompanyOutlined` | `Building` | lucide |
|
|
123
|
+
|
|
124
|
+
### Feedback & Status
|
|
125
|
+
|
|
126
|
+
| Old (`@aircall/icons`) | New (`@aircall/react-icons`) | Source |
|
|
127
|
+
| --- | --- | --- |
|
|
128
|
+
| `InformationFilled`, `InformationOutlined` | `Info` | lucide |
|
|
129
|
+
| `WarningFilled`, `WarningOutlined` | `AlertTriangle` | lucide |
|
|
130
|
+
| `NotificationOnFilled`, `NotificationOnOutlined` | `Bell` | lucide |
|
|
131
|
+
| `StarOutlined` | `Star` | lucide |
|
|
132
|
+
| `StarFilled` | `StarFilled` | custom |
|
|
133
|
+
|
|
134
|
+
### Messages & SMS
|
|
135
|
+
|
|
136
|
+
| Old (`@aircall/icons`) | New (`@aircall/react-icons`) | Source |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| `MessageFilled`, `SmsInboundFilled` | `MessageSquare` | lucide |
|
|
139
|
+
| `EmailFilled`, `MailOutlined` | `Mail` | lucide |
|
|
140
|
+
| `InboxFilled`, `InboxOutlined` | `Inbox` | lucide |
|
|
141
|
+
| `ChatFilled`, `ChatOutlined` | `MessagesSquare` | lucide |
|
|
142
|
+
|
|
143
|
+
### System & Settings
|
|
144
|
+
|
|
145
|
+
| Old (`@aircall/icons`) | New (`@aircall/react-icons`) | Source |
|
|
146
|
+
| --- | --- | --- |
|
|
147
|
+
| `SettingsFilled`, `SettingsOutlined` | `Settings` | lucide |
|
|
148
|
+
| `MenuVerticalFilled`, `MenuVerticalOutlined` | `MoreVertical` | lucide |
|
|
149
|
+
| `MenuHorizontalFilled`, `MenuHorizontalOutlined` | `MoreHorizontal` | lucide |
|
|
150
|
+
| `SpinnerOutlined` | `Loader2` | lucide |
|
|
151
|
+
|
|
152
|
+
### Analytics & AI
|
|
153
|
+
|
|
154
|
+
| Old (`@aircall/icons`) | New (`@aircall/react-icons`) | Source |
|
|
155
|
+
| --- | --- | --- |
|
|
156
|
+
| `SparklesFilled`, `LivePromptFilled`, `MagicFilled` | `AiAssist` | custom |
|
|
157
|
+
| `AIAgent`, `VirtualAgentFilled` | `AiAgents` | custom |
|
|
158
|
+
| `MonitoringFilled`, `AnalyticsFilled` | `BarChartBig` | lucide |
|
|
159
|
+
| `ActivityFilled`, `BoltFilled` | `Zap` | lucide |
|
|
160
|
+
|
|
161
|
+
## 5. Icons with no equivalent
|
|
162
|
+
|
|
163
|
+
A small number of old icons have no direct mapping. Handle them as noted:
|
|
164
|
+
|
|
165
|
+
| Old icon | Action |
|
|
166
|
+
| --- | --- |
|
|
167
|
+
| `PlayPauseFilled`, `PlayPauseOutlined` | Use `Play` or `Pause` contextually — no combined equivalent |
|
|
168
|
+
| `Speed100XFilled`, `Speed125XFilled`, `Speed150XFilled`, `Speed200XFilled` | Render as text or a custom badge — no icon equivalent |
|
|
169
|
+
| `AIMessageFilled` | No equivalent — treat as custom SVG until a replacement ships |
|
|
170
|
+
| `OnboardingFilled` | Use `Flag` or `Rocket` as a placeholder; confirm with design |
|
|
171
|
+
|
|
172
|
+
## 6. Brand / platform icons (not in @aircall/react-icons)
|
|
173
|
+
|
|
174
|
+
Keep these as separate inline SVGs or local wrappers — they are not in `@aircall/react-icons`:
|
|
175
|
+
|
|
176
|
+
- **Aircall brand**: `AircallIcon`, `AircallLogo`, `AircallLogoFull`, logo-mark variants
|
|
177
|
+
- **OS / platform**: `AppleFilled`, `AndroidFilled`, `WindowsFilled`, `MacFilled`
|
|
178
|
+
- **Browsers**: `ChromeFilled`, `EdgeFilled`, `FirefoxFilled`
|
|
179
|
+
- **Messaging**: `WhatsappFilled`, `WhatsappOutlined` — use the existing `WhatsAppIcon.tsx` in `packages/aw-ui`
|
|
180
|
+
- **Text badges**: `BetaOutlined` — keep as a custom SVG or badge component
|
|
181
|
+
|
|
182
|
+
## 7. Before / After examples
|
|
183
|
+
|
|
184
|
+
### 7a. Basic icon with color and size
|
|
185
|
+
|
|
186
|
+
**Before (Tractor + @aircall/icons):**
|
|
187
|
+
```tsx
|
|
188
|
+
import { Icon } from '@aircall/tractor';
|
|
189
|
+
import { CallFilled } from '@aircall/icons';
|
|
190
|
+
|
|
191
|
+
<Icon component={CallFilled} size={24} color="primary.500" />
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**After (@aircall/react-icons + Tailwind):**
|
|
195
|
+
```tsx
|
|
196
|
+
import { Phone } from '@aircall/react-icons';
|
|
197
|
+
|
|
198
|
+
<Phone className="size-6 text-primary" />
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### 7b. Icon inside a button (critical color)
|
|
202
|
+
|
|
203
|
+
**Before (Tractor + @aircall/icons):**
|
|
204
|
+
```tsx
|
|
205
|
+
import { Icon } from '@aircall/tractor';
|
|
206
|
+
import { TrashFilled } from '@aircall/icons';
|
|
207
|
+
import { Button } from '@aircall/tractor';
|
|
208
|
+
|
|
209
|
+
<Button variant="danger" size="small">
|
|
210
|
+
<Icon component={TrashFilled} size={16} color="critical.500" />
|
|
211
|
+
Delete
|
|
212
|
+
</Button>
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**After (@aircall/ds + @aircall/react-icons):**
|
|
216
|
+
```tsx
|
|
217
|
+
import { Trash2 } from '@aircall/react-icons';
|
|
218
|
+
import { Button } from '@aircall/ds';
|
|
219
|
+
|
|
220
|
+
<Button variant="destructive" size="lg">
|
|
221
|
+
<Trash2 />
|
|
222
|
+
Delete
|
|
223
|
+
</Button>
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
> When an icon sits inside a DS `Button`, omit the `size-*` class — the Button's `[&_svg]:size-4` rule sizes it automatically.
|
|
227
|
+
|
|
228
|
+
### 7c. Icon with muted color (secondary text)
|
|
229
|
+
|
|
230
|
+
**Before (Tractor + @aircall/icons):**
|
|
231
|
+
```tsx
|
|
232
|
+
import { Icon } from '@aircall/tractor';
|
|
233
|
+
import { ClockFilled } from '@aircall/icons';
|
|
234
|
+
|
|
235
|
+
<Icon component={ClockFilled} size={20} color="text.secondary" />
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**After (@aircall/react-icons + Tailwind):**
|
|
239
|
+
```tsx
|
|
240
|
+
import { Clock } from '@aircall/react-icons';
|
|
241
|
+
|
|
242
|
+
<Clock className="size-5 text-muted-foreground" />
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### 7d. Custom Aircall icon
|
|
246
|
+
|
|
247
|
+
**Before (Tractor + @aircall/icons):**
|
|
248
|
+
```tsx
|
|
249
|
+
import { Icon } from '@aircall/tractor';
|
|
250
|
+
import { VoicemailDrop } from '@aircall/icons';
|
|
251
|
+
|
|
252
|
+
<Icon component={VoicemailDrop} size={24} />
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**After (@aircall/react-icons):**
|
|
256
|
+
```tsx
|
|
257
|
+
import { VoicemailDrop } from '@aircall/react-icons';
|
|
258
|
+
|
|
259
|
+
<VoicemailDrop className="size-6" />
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
> Aircall custom icons are also re-exported from `@aircall/react-icons`. The import source changes but the component name stays the same for custom icons that survived into the new package.
|
|
263
|
+
|
|
264
|
+
## 8. Common mistakes
|
|
265
|
+
|
|
266
|
+
### Mistake 1: Keeping the Tractor `<Icon>` wrapper
|
|
267
|
+
|
|
268
|
+
```tsx
|
|
269
|
+
// WRONG — @aircall/ds has no Icon component; wrapper is unused
|
|
270
|
+
import { Icon } from '@aircall/tractor';
|
|
271
|
+
import { Phone } from '@aircall/react-icons';
|
|
272
|
+
|
|
273
|
+
<Icon component={Phone} size={24} color="primary.500" />
|
|
274
|
+
|
|
275
|
+
// CORRECT — use the icon component directly with Tailwind classes
|
|
276
|
+
import { Phone } from '@aircall/react-icons';
|
|
277
|
+
|
|
278
|
+
<Phone className="size-6 text-primary" />
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**Mechanism:** `@aircall/react-icons` exports standard SVG React components. The Tractor `Icon` wrapper was a thin adapter that forwarded `size` and `color` as `width`/`height`/`fill` attributes. Without it, those props are simply ignored — or worse, they pass unknown attributes to the SVG element.
|
|
282
|
+
|
|
283
|
+
Source: `@aircall/react-icons` re-exports lucide + Aircall icons as plain SVG components with no wrapper.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
### Mistake 2: Using the old `@aircall/icons` name unchanged
|
|
288
|
+
|
|
289
|
+
```tsx
|
|
290
|
+
// WRONG — old name does not exist in @aircall/react-icons; TS compile error
|
|
291
|
+
import { CallFilled } from '@aircall/react-icons';
|
|
292
|
+
|
|
293
|
+
// CORRECT — lucide consolidates filled/outlined variants; use the new name
|
|
294
|
+
import { Phone } from '@aircall/react-icons';
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Mechanism:** `@aircall/react-icons` intentionally consolidates `*Filled`/`*Outlined` variants into a single icon name (e.g. `CallFilled` + `CallOutlined` → `Phone`). The visual distinction (filled vs stroke) is gone by design — lucide icons are all stroke-outlined. Importing the old name compiles to `undefined` and renders nothing.
|
|
298
|
+
|
|
299
|
+
Source: `@aircall/react-icons` re-exports lucide + Aircall icons; custom icons live in `packages/react-icons/src/generated/custom`.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
### Mistake 3: Using a `color` or `size` number prop instead of Tailwind classes
|
|
304
|
+
|
|
305
|
+
```tsx
|
|
306
|
+
// WRONG — color and size number are Tractor Icon props, not valid SVG props
|
|
307
|
+
import { Mic } from '@aircall/react-icons';
|
|
308
|
+
|
|
309
|
+
<Mic size={24} color="primary.500" />
|
|
310
|
+
|
|
311
|
+
// CORRECT — use Tailwind utility classes
|
|
312
|
+
import { Mic } from '@aircall/react-icons';
|
|
313
|
+
|
|
314
|
+
<Mic className="size-6 text-primary" />
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
**Mechanism:** lucide-react icons accept a `size` prop and a `color` prop via the lucide component API — but `@aircall/react-icons` wraps them in a way that Tailwind classes are the intended styling mechanism. Using Tractor color tokens like `"primary.500"` as a CSS value produces an invalid color string that browsers ignore silently, and the icon renders in the inherited color instead of the intended one.
|
|
318
|
+
|
|
319
|
+
Source: `@aircall/react-icons` re-exports lucide + Aircall icons; Tailwind design tokens (`text-primary`, `text-destructive`, etc.) are the authoritative color system in `@aircall/ds`.
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
### Mistake 4: Importing icons directly from `lucide-react`
|
|
324
|
+
|
|
325
|
+
```tsx
|
|
326
|
+
// WRONG — bypasses the Aircall icon layer; icon swaps or overrides won't apply
|
|
327
|
+
import { Phone } from 'lucide-react';
|
|
328
|
+
|
|
329
|
+
// CORRECT — always route through @aircall/react-icons
|
|
330
|
+
import { Phone } from '@aircall/react-icons';
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Mechanism:** `@aircall/react-icons` is the single source of truth for all icons — it re-exports lucide icons and adds Aircall custom icons. Importing from `lucide-react` directly means any future override, version pin, or custom replacement in `@aircall/react-icons` won't be picked up. It also breaks tree-shaking assumptions and makes it harder to audit icon usage across the codebase.
|
|
334
|
+
|
|
335
|
+
Source: `@aircall/react-icons` re-exports lucide + Aircall icons as the canonical icon surface for Aircall apps.
|
|
336
|
+
|
|
337
|
+
## 9. Migration checklist
|
|
338
|
+
|
|
339
|
+
- [ ] Swap `@aircall/icons` → `@aircall/react-icons` in `package.json`
|
|
340
|
+
- [ ] Remove `import { Icon } from '@aircall/tractor'` — no wrapper needed
|
|
341
|
+
- [ ] Rename icons per the tables above (many `*Filled`/`*Outlined` pairs merge into one name)
|
|
342
|
+
- [ ] Replace `color="…"` with `className="text-*"` using the color table
|
|
343
|
+
- [ ] Replace `size={N}` with `className="size-N"` (or omit when inside a DS `Button`)
|
|
344
|
+
- [ ] Run `pnpm tsc --noEmit` — missing exports surface as TS compile errors
|
|
345
|
+
- [ ] Keep brand/platform icons (Aircall logo, OS, browser, WhatsApp) as separate assets
|
|
346
|
+
- [ ] For icons marked "validate usage", confirm the new shape is visually correct in context
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: aircall-ds/migrate-tractor
|
|
3
|
+
description: >
|
|
4
|
+
Migrate a file from @aircall/tractor to @aircall/ds. Load FIRST when converting
|
|
5
|
+
Tractor components (Modal, Banner, Select, Button, Typography, Flex, Tooltip, Tag,
|
|
6
|
+
Dropdown, Form, …) to @aircall/ds. Carries the cross-cutting rules (import form,
|
|
7
|
+
prop renames, the render prop, data-attribute shape) and a lookup table mapping
|
|
8
|
+
each Tractor component to its @aircall/ds target and the recipe skill to load next.
|
|
9
|
+
type: core
|
|
10
|
+
library: aircall-ds
|
|
11
|
+
library_version: "0.13.0"
|
|
12
|
+
requires:
|
|
13
|
+
- aircall-ds/setup
|
|
14
|
+
sources:
|
|
15
|
+
- "aircall/hydra:docs/migration-guides/tractor-to-ds/01-global-rules.md"
|
|
16
|
+
- "aircall/hydra:docs/migration-guides/tractor-to-ds/04-lookup.md"
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# Migrating from @aircall/tractor to @aircall/ds
|
|
20
|
+
|
|
21
|
+
Load this skill first for any Tractor → DS migration. It gives the cross-cutting
|
|
22
|
+
rules that apply to every component and a lookup table to find the DS replacement.
|
|
23
|
+
Then load the component-specific recipe skill from the `recipe to load` column.
|
|
24
|
+
|
|
25
|
+
## How to run this migration (end-to-end)
|
|
26
|
+
|
|
27
|
+
This skill and its recipes cover *converting code*. The full migration is a repeatable
|
|
28
|
+
loop — do it incrementally, one file/screen at a time, shipping each green:
|
|
29
|
+
|
|
30
|
+
0. **Set up once** — load `@aircall/ds#aircall-ds/setup` and do the wiring before any
|
|
31
|
+
conversion: install `@aircall/ds` + `@aircall/react-icons` (>= 0.4.0), import the
|
|
32
|
+
precompiled `globals.css`, mount the root providers (incl. `DsI18nProvider` under
|
|
33
|
+
react-i18next + `NotificationQueueProvider`), keep `TractorProvider` mounted for
|
|
34
|
+
cohabitation, and add the jsdom test shims (selector guard for DS popups +
|
|
35
|
+
Switch-via-hidden-checkbox). DS and Tractor run side by side until the last Tractor
|
|
36
|
+
import is gone. (This skill `requires` setup so it loads automatically — but do the
|
|
37
|
+
install/provider/jest wiring first.)
|
|
38
|
+
1. **Inventory** — list the file's `@aircall/tractor` and `@aircall/icons` imports. Each
|
|
39
|
+
maps to a row in the lookup table below, or to `@aircall/ds#aircall-ds/migrate-icons`
|
|
40
|
+
for icons.
|
|
41
|
+
2. **Migrate** — apply the cross-cutting rules (§1–§3), then load the per-component recipe
|
|
42
|
+
from the `recipe to load` column for each component; use `migrate-icons` for icons.
|
|
43
|
+
3. **Verify green** — `tsc --noEmit`, the test suite (DS popups/Switch need the setup jsdom
|
|
44
|
+
shims), and biome/lint. Re-screenshot if the screen changed visually.
|
|
45
|
+
4. **Repeat** per file/screen until no `@aircall/tractor` / `@aircall/icons` imports remain,
|
|
46
|
+
then drop them from `package.json`.
|
|
47
|
+
|
|
48
|
+
## 1. Imports
|
|
49
|
+
|
|
50
|
+
Always import from the top-level package only:
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { Button, Dialog, Input } from '@aircall/ds';
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Subpath imports (`@aircall/ds/components/button`) work only inside the hydra monorepo
|
|
57
|
+
and break in external apps. Use the root form everywhere.
|
|
58
|
+
|
|
59
|
+
## 2. Drop styled-components
|
|
60
|
+
|
|
61
|
+
Remove `styled()` wrappers, `fromTheme`, `getColor`/`getSpace`/`getRadii`/`getShadow`,
|
|
62
|
+
and `useTheme()`. Replace them with Tailwind classes on the DS component's `className`
|
|
63
|
+
or a plain `<div>`:
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
// Before
|
|
67
|
+
const Styled = styled(Button)`font-size: ${fromTheme('typography.variants.body.fontSize')};`;
|
|
68
|
+
<Box mx={2} my={4} bg="primary.500" />
|
|
69
|
+
|
|
70
|
+
// After
|
|
71
|
+
<Button className="text-sm" />
|
|
72
|
+
<div className="mx-2 my-4 bg-primary" />
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The migration is progressive — Tractor and DS can coexist. Remove `TractorProvider`
|
|
76
|
+
only when the last `@aircall/tractor` import is gone.
|
|
77
|
+
|
|
78
|
+
## 3. Standard prop renames
|
|
79
|
+
|
|
80
|
+
These apply to every component that had them in Tractor:
|
|
81
|
+
|
|
82
|
+
| Tractor | DS |
|
|
83
|
+
| --- | --- |
|
|
84
|
+
| `isOpen` | `open` |
|
|
85
|
+
| `onClose` | `onOpenChange` (receives `boolean`) |
|
|
86
|
+
| `onChange` (value-based: Select, Tabs, RadioGroup, Slider, ToggleGroup) | `onValueChange` |
|
|
87
|
+
| `onChange` (boolean: Checkbox, Switch) | `onCheckedChange` |
|
|
88
|
+
| `validationStatus="error"` | `aria-invalid={true}` |
|
|
89
|
+
| `variant="critical"` | `variant="destructive"` (Button) |
|
|
90
|
+
| `as="…"` | `render={<Element />}` |
|
|
91
|
+
|
|
92
|
+
> `onValueChange` for Select receives `(value: string | null, event)` — `null` when
|
|
93
|
+
> cleared. Widen your handler to accept `null`.
|
|
94
|
+
|
|
95
|
+
## 4. The `render` prop (replaces `asChild`)
|
|
96
|
+
|
|
97
|
+
When a Trigger or Close must render as a custom element, pass it to `render`:
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
<DialogTrigger render={<Button variant="outline" />}>Open</DialogTrigger>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Affected: Trigger/Close on Dialog, Sheet, Popover, Tooltip, DropdownMenu, Collapsible,
|
|
104
|
+
Drawer, plus `Button`, `Badge`, `Item`, `PaginationLink`, and Sidebar subcomponents.
|
|
105
|
+
|
|
106
|
+
Drawer is Base UI (via Coss UI) — same `render` rule applies. Its body wrapper is
|
|
107
|
+
`DrawerPopup` (not `DrawerContent`), and Tractor's `direction` becomes `position`.
|
|
108
|
+
|
|
109
|
+
## 5. Labels live inside Groups
|
|
110
|
+
|
|
111
|
+
For `DropdownMenu` and `Select`, `Label` must be a child of a `*Group`:
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
<DropdownMenuContent>
|
|
115
|
+
<DropdownMenuGroup>
|
|
116
|
+
<DropdownMenuLabel>Account</DropdownMenuLabel>
|
|
117
|
+
<DropdownMenuItem>Profile</DropdownMenuItem>
|
|
118
|
+
</DropdownMenuGroup>
|
|
119
|
+
</DropdownMenuContent>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 6. Data attributes in Tailwind classes
|
|
123
|
+
|
|
124
|
+
DS uses single-key data attributes for state (not Radix `[state=…]` form):
|
|
125
|
+
|
|
126
|
+
| Use | Not |
|
|
127
|
+
| --- | --- |
|
|
128
|
+
| `data-open:animate-in` | `data-[state=open]:animate-in` |
|
|
129
|
+
| `data-checked:bg-primary` | `data-[state=checked]:bg-primary` |
|
|
130
|
+
| `data-disabled:opacity-50` | `data-[disabled]:opacity-50` |
|
|
131
|
+
|
|
132
|
+
**Orientation is the exception** — it's a value attribute, not a flag. Style with
|
|
133
|
+
`data-[orientation=horizontal]:` / `data-[orientation=vertical]:` (Tabs, Slider,
|
|
134
|
+
Separator).
|
|
135
|
+
|
|
136
|
+
**Collapsible asymmetry:** Root uses `data-open` / `data-closed`; Trigger uses
|
|
137
|
+
`data-panel-open` (no closed counterpart).
|
|
138
|
+
|
|
139
|
+
## 7. Size baselines
|
|
140
|
+
|
|
141
|
+
> These are recommended starting points. Verify with design — pixel sizes have shifted
|
|
142
|
+
> between Tractor and DS, so a verbatim same-size match isn't always possible.
|
|
143
|
+
|
|
144
|
+
**Button** (DS heights: `sm`=24px, `default`=32px, `lg`=40px):
|
|
145
|
+
|
|
146
|
+
| Tractor | DS | Diff |
|
|
147
|
+
| --- | --- | --- |
|
|
148
|
+
| `xSmall` (28px) | `size="default"` (32px) | +4px |
|
|
149
|
+
| `small` (40px) | `size="lg"` (40px) | exact |
|
|
150
|
+
| `regular` (48px, default) | `size="lg"` (40px) | -8px |
|
|
151
|
+
| `large` (56px) | `className="h-14"` | no built-in size |
|
|
152
|
+
|
|
153
|
+
**Icon Button** (DS sizes: `icon-sm`=24px, `icon`=32px, `icon-lg`=40px):
|
|
154
|
+
|
|
155
|
+
| Tractor IconButton | DS |
|
|
156
|
+
| --- | --- |
|
|
157
|
+
| Default (24px) | `size="icon"` |
|
|
158
|
+
| Smaller than default | `size="icon-sm"` |
|
|
159
|
+
| Larger than default | `size="icon-lg"` |
|
|
160
|
+
|
|
161
|
+
**Select Trigger** has two sizes: `default` (40px) and `sm` (32px). Use `default`
|
|
162
|
+
for any Tractor `regular` / `small`.
|
|
163
|
+
|
|
164
|
+
**Avatar** (DS sizes: `xs`=20px, `sm`=24px, `default`=32px, `lg`=40px, `xl`=48px):
|
|
165
|
+
|
|
166
|
+
| Tractor | DS |
|
|
167
|
+
| --- | --- |
|
|
168
|
+
| `small` (24px) | `sm` |
|
|
169
|
+
| `regular` (32px) | `default` |
|
|
170
|
+
| `large` (48px) | `xl` |
|
|
171
|
+
| `xLarge` (64px) | `xl` (-16px, no 64px size) |
|
|
172
|
+
|
|
173
|
+
**Toggle / ToggleGroupItem**: same heights as Button (`sm`/`default`/`lg`).
|
|
174
|
+
|
|
175
|
+
**No `size` prop:** Input, Textarea, Switch, Checkbox, RadioGroup, Slider. Drop the
|
|
176
|
+
Tractor `size` prop entirely.
|
|
177
|
+
|
|
178
|
+
## 8. Variant naming
|
|
179
|
+
|
|
180
|
+
Tractor used `variant` + `mode`. DS uses a single `variant`.
|
|
181
|
+
|
|
182
|
+
| Tractor | DS |
|
|
183
|
+
| --- | --- |
|
|
184
|
+
| `critical` | `destructive` (Button) or `error` (Alert) |
|
|
185
|
+
| `informative` | `info` (Alert) |
|
|
186
|
+
| `primary` + `mode="fill"` | `default` (Button) |
|
|
187
|
+
| `primary` + `mode="outline"` | `outline` (Button) |
|
|
188
|
+
| `primary` + `mode="ghost"` | `ghost` (Button) |
|
|
189
|
+
| `primary` + `mode="link"` | `link` (Button) |
|
|
190
|
+
|
|
191
|
+
Each DS component has its own variant set — check the lookup table below.
|
|
192
|
+
|
|
193
|
+
## 9. Icons
|
|
194
|
+
|
|
195
|
+
`@aircall/icons` → `@aircall/react-icons`. The `<Icon component={X} />` wrapper is
|
|
196
|
+
gone; import the icon directly:
|
|
197
|
+
|
|
198
|
+
```tsx
|
|
199
|
+
// Before
|
|
200
|
+
import { AddOutlined, Icon } from '@aircall/tractor';
|
|
201
|
+
<Icon component={AddOutlined} mr={2} />
|
|
202
|
+
|
|
203
|
+
// After
|
|
204
|
+
import { AddCircleFill } from '@aircall/react-icons';
|
|
205
|
+
<AddCircleFill className="mr-2 size-4" />
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Some names differ significantly (e.g. `InfoCircleFilled` → `InformationCircleFill`,
|
|
209
|
+
`PlayFilled` → `ControlPlayFill`).
|
|
210
|
+
|
|
211
|
+
## 10. Forms & validation
|
|
212
|
+
|
|
213
|
+
A Tractor `Form`/`FormItem` that collects and submits data migrates to **`@aircall/blocks` `useForm` + the `Form*Field` wrappers** — do NOT keep field values in React `useState`, and do NOT hand-wire the ds `Field`/`Input` primitives. The form owns state, validation, dirty/`canSubmit`/`isSubmitting`, and errors (which drive `SubmitButton`/`CardSaveBar`). Use the bare ds `Field` primitives only for non-form display. See `@aircall/ds#aircall-ds/migrate-tractor/form-and-field` and `@aircall/blocks#aircall-blocks/migrate-dashboard/form-wizard`.
|
|
214
|
+
|
|
215
|
+
Field-level validation state is `aria-invalid` — DS components style themselves from it:
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
<Input aria-invalid={hasError} />
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## 11. Cleanup items
|
|
222
|
+
|
|
223
|
+
- **Base font size**: Tractor used 14px. DS uses 16px. Remove any `font-size: 14px`
|
|
224
|
+
on `html` or `body` — DS's `globals.css` already sets the correct base.
|
|
225
|
+
- **SVG workarounds**: Remove any `svg { display: block; line-height: 0; }` global CSS.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Component lookup table
|
|
230
|
+
|
|
231
|
+
Grep your code for `@aircall/tractor` imports. For each component, find the row below.
|
|
232
|
+
Then load the listed recipe skill (if `available`) for the detailed swap.
|
|
233
|
+
|
|
234
|
+
| Tractor component | @aircall/ds target | recipe to load | status |
|
|
235
|
+
| --- | --- | --- | --- |
|
|
236
|
+
| `Accordion` (+ `AccordionSection`) | `Accordion` + `AccordionItem` + `AccordionTrigger` + `AccordionContent` | `@aircall/ds#aircall-ds/migrate-tractor/accordion` | available |
|
|
237
|
+
| `ActionMenu` | `DropdownMenu` (compound) | `@aircall/ds#aircall-ds/migrate-tractor/dropdown-menu` | available |
|
|
238
|
+
| `AudioPlayer` | — (no DS equivalent yet) | — | not-yet |
|
|
239
|
+
| `Avatar` (+ `QuickAvatar`) | `Avatar` + `AvatarImage` + `AvatarFallback` | `@aircall/ds#aircall-ds/migrate-tractor/avatar` | available |
|
|
240
|
+
| `Badge` | `AvatarBadge` (status dot on avatar); `Badge` (label/tag style) | `@aircall/ds#aircall-ds/migrate-tractor/badge` | available |
|
|
241
|
+
| `Banner` (+ `BannerHeading`/`BannerIcon`/`BannerSuffix`) | `Alert` (rounded card) / `Banner` (inline full-width) | `@aircall/ds#aircall-ds/migrate-tractor/alert` | available |
|
|
242
|
+
| `BannerButton` | `Button` inside `BannerAction` | `@aircall/ds#aircall-ds/migrate-tractor/alert` | available |
|
|
243
|
+
| `Box` | native `<div>` + Tailwind classes | `@aircall/ds#aircall-ds/migrate-tractor/styling` | available |
|
|
244
|
+
| `Button` | `Button` | `@aircall/ds#aircall-ds/migrate-tractor/button` | available |
|
|
245
|
+
| `Checkbox` | `Checkbox` + `<Label>` | — | not-yet |
|
|
246
|
+
| `ComboBox` | `Combobox` (compound) | `@aircall/ds#aircall-ds/migrate-tractor/combobox` | available |
|
|
247
|
+
| `CounterBadge` | `CounterBadge` | `@aircall/ds#aircall-ds/migrate-tractor/badge` | available |
|
|
248
|
+
| `DatePicker` | `Calendar` + your own `Popover` trigger | — | not-yet |
|
|
249
|
+
| `Divider` | `Separator` | `@aircall/ds#aircall-ds/migrate-tractor/divider` | available |
|
|
250
|
+
| `Drawer` | `Drawer` (compound, `DrawerPopup` body) | `@aircall/ds#aircall-ds/migrate-tractor/sheet-vs-drawer` | available |
|
|
251
|
+
| `Dropdown` | `DropdownMenu` (compound) | `@aircall/ds#aircall-ds/migrate-tractor/dropdown-menu` | available |
|
|
252
|
+
| `Flex` | native `<div className="flex …">` + Tailwind | `@aircall/ds#aircall-ds/migrate-tractor/styling` | available |
|
|
253
|
+
| `FlagIcon` | `CountryFlag` (prop: `countryIsoCode`) | — | not-yet |
|
|
254
|
+
| `Form` | native `<form>` + `Field` per row | `@aircall/ds#aircall-ds/migrate-tractor/form-and-field` | available |
|
|
255
|
+
| `FormItem` | `Field` + `FieldLabel` + `FieldDescription` + `FieldError` | `@aircall/ds#aircall-ds/migrate-tractor/form-and-field` | available |
|
|
256
|
+
| `Gauge` | `Gauge` (8-segment audio meter) | `@aircall/ds#aircall-ds/migrate-tractor/gauge` | available |
|
|
257
|
+
| `Grid` | native `<div className="grid …">` + Tailwind | `@aircall/ds#aircall-ds/migrate-tractor/styling` | available |
|
|
258
|
+
| `Icon` | direct icon import from `@aircall/react-icons` | `@aircall/ds#aircall-ds/migrate-icons` | available |
|
|
259
|
+
| `IconButton` | `Button` with `size` `icon` / `icon-sm` / `icon-lg` | `@aircall/ds#aircall-ds/migrate-tractor/button` | available |
|
|
260
|
+
| `Link` | `Link` | `@aircall/ds#aircall-ds/migrate-tractor/link` | available |
|
|
261
|
+
| `List` (+ `ListItem`) | `ItemGroup` + `Item` + `ItemMedia`/`ItemContent`/`ItemActions` | `@aircall/ds#aircall-ds/migrate-tractor/item` | available |
|
|
262
|
+
| `Menu` (+ `MenuItem`) | standalone list → `ItemGroup` + `Item`; **inside a `Dropdown`/`ActionMenu`** → `DropdownMenuContent` + `DropdownMenuItem` | `@aircall/ds#aircall-ds/migrate-tractor/item` (standalone) or `@aircall/ds#aircall-ds/migrate-tractor/dropdown-menu` (in a Dropdown) | available |
|
|
263
|
+
| `Modal` | `Dialog` (compound) | `@aircall/ds#aircall-ds/migrate-tractor/dialog` | available |
|
|
264
|
+
| `PasswordInput` | `InputGroup` recipe | `@aircall/ds#aircall-ds/migrate-tractor/input` | available |
|
|
265
|
+
| `Popover` | `Popover` + `PopoverTrigger` + `PopoverContent` | `@aircall/ds#aircall-ds/migrate-tractor/popover` | available |
|
|
266
|
+
| `Progress` | `Progress` (compound: `ProgressTrack` + `ProgressIndicator`) | — | not-yet |
|
|
267
|
+
| `QuickAvatar` | `Avatar` (same as Avatar row) | `@aircall/ds#aircall-ds/migrate-tractor/avatar` | available |
|
|
268
|
+
| `Radio` + `RadioGroup` | `RadioGroup` + `RadioGroupItem` | — | not-yet |
|
|
269
|
+
| `SegmentedControl` | `Tabs` (with panel) or `ToggleGroup` (visual only) | `@aircall/ds#aircall-ds/migrate-tractor/tabs` | available |
|
|
270
|
+
| `Select` + `SelectOption` | `Select` (compound: `SelectTrigger` + `SelectValue` + `SelectContent` + `SelectGroup` + `SelectItem`) | `@aircall/ds#aircall-ds/migrate-tractor/select` | available |
|
|
271
|
+
| `SidenavDropdown` | `Sidebar` + `Collapsible` (compose) | — | not-yet |
|
|
272
|
+
| `SidenavItem` | `Sidebar*` family | — | not-yet |
|
|
273
|
+
| `Skeleton` | `Skeleton` — size via Tailwind (`className="h-4 w-32"`) | `@aircall/ds#aircall-ds/migrate-tractor/skeleton` | available |
|
|
274
|
+
| `Slider` | `Slider` (`onValueChange`, value is `number[]`, no `size`) | — | not-yet |
|
|
275
|
+
| `Spacer` | `<div className="flex flex-col gap-*">` or `FieldGroup` | `@aircall/ds#aircall-ds/migrate-tractor/styling` | available |
|
|
276
|
+
| `SpinnerOutlined` | `Spinner` (sizes: `sm`/`default`/`lg`/`xl`, always animated) | — | not-yet |
|
|
277
|
+
| `Tab` (+ `Tab.Item`/`TabList`/`TabPanel`) | `Tabs` + `TabsTrigger` + `TabsList` + `TabsContent` | `@aircall/ds#aircall-ds/migrate-tractor/tabs` | available |
|
|
278
|
+
| `Table` (+ `ActionBar`) | `DataTable` (data-driven) or `Table` primitive (static) | `@aircall/ds#aircall-ds/migrate-tractor/data-table` | available |
|
|
279
|
+
| `Tag` | `Badge` (`color` + `tone` props; `legacyColor` for custom hex) | `@aircall/ds#aircall-ds/migrate-tractor/badge` | available |
|
|
280
|
+
| `Textarea` | `Textarea` (no `size`, use `aria-invalid`) | — | not-yet |
|
|
281
|
+
| `TextFieldInput` | `Input` (no `sizing`, 40px fixed, use `aria-invalid`) | `@aircall/ds#aircall-ds/migrate-tractor/input` | available |
|
|
282
|
+
| `Toggle` | `Switch` (`onCheckedChange`, no `size`) | — | not-yet |
|
|
283
|
+
| `ToggleGroup` / `TabToggle` | `ToggleGroup` (`multiple` boolean; value always `string[]`) | — | not-yet |
|
|
284
|
+
| `Tooltip` | `Tooltip` (compound) + `TooltipProvider` at app root | `@aircall/ds#aircall-ds/migrate-tractor/tooltip` | available |
|
|
285
|
+
| `Tree` | `DataTree` (data-driven) or `Tree` primitive | `@aircall/ds#aircall-ds/migrate-tractor/tree` | available |
|
|
286
|
+
| `TreeSelect` | no turn-key equivalent — `DataTree` inside a `Popover` | `@aircall/ds#aircall-ds/migrate-tractor/tree` | available |
|
|
287
|
+
| `Typography` | native HTML + Tailwind text classes | `@aircall/ds#aircall-ds/migrate-tractor/styling` | available |
|
|
288
|
+
| `useToast` | `toast` from `sonner` + `<Toaster />` at app root | `@aircall/ds#aircall-ds/migrate-tractor/toast` | available |
|
|
289
|
+
| `WhatsAppTemplatePreview` | — (no DS equivalent) | — | not-yet |
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## Facts easy to get wrong
|
|
294
|
+
|
|
295
|
+
These APIs do not exist in DS. Do not propose them.
|
|
296
|
+
|
|
297
|
+
- `<Input sizing="lg" />` — Input has **no** `sizing`/`size` prop. It is 40px, period.
|
|
298
|
+
- `<Textarea size="…" />` — no size prop.
|
|
299
|
+
- `<Switch size="…" />` — no size prop.
|
|
300
|
+
- `<Checkbox size="…" />` — no size prop.
|
|
301
|
+
- `<RadioGroup size="…" />` — no size prop.
|
|
302
|
+
- `<Slider size="…" />` — no size prop.
|
|
303
|
+
- `<Tabs size="…" />` / `<TabsList variant="…" />` — no such props.
|
|
304
|
+
- `<Badge variant="destructive" | "success" | "warning" | "info" />` — Badge has only
|
|
305
|
+
`default`, `secondary`, `outline`. For semantic colors use `Alert`, `CounterBadge`,
|
|
306
|
+
or `className` with a semantic token.
|
|
307
|
+
- `<Alert variant="destructive" />` — Alert's error variant is `error`, not
|
|
308
|
+
`destructive`. Full set: `default` / `info` / `success` / `warning` / `error`.
|
|
309
|
+
- `<CounterBadge count={…} max={…} />` — no `count`/`max` props. Pass the already-
|
|
310
|
+
capped value as children. Variants: `default` / `secondary` / `ghost`.
|
|
311
|
+
- `<TooltipProvider delayDuration={…} />` — Base UI prop is `delay`, default `0`.
|
|
312
|
+
`delayDuration` is silently ignored.
|
|
313
|
+
- Subpath imports like `@aircall/ds/components/<name>` — never propose. Always use
|
|
314
|
+
`import { X } from '@aircall/ds'`.
|