@bitrise/bitkit-v2 0.3.210 → 0.3.211
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/docs/v1-to-v2-migration-guide.md +295 -0
- package/package.json +2 -1
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# Bitkit v1 → v2 Migration Guide
|
|
2
|
+
|
|
3
|
+
Practical learnings from migrating a React frontend from `@bitrise/bitkit` (Chakra UI v2) to `@bitrise/bitkit-v2` (Chakra UI v3).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Strategy: coexistence first, cutover last
|
|
8
|
+
|
|
9
|
+
Don't attempt a big-bang migration. Instead:
|
|
10
|
+
|
|
11
|
+
1. Install `@bitrise/bitkit-v2` alongside v1
|
|
12
|
+
2. Wrap `BitkitProvider` (v2) **inside** the existing v1 `<Provider>`. In practice, nesting them works without additional config.
|
|
13
|
+
3. Migrate file by file, component by component
|
|
14
|
+
4. Remove v1 `<Provider>` only when zero v1 imports remain
|
|
15
|
+
5. Remove `@bitrise/bitkit` from `package.json` last
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
// Transitional App.tsx
|
|
19
|
+
<Provider theme={customTheme}> {/* v1 — stays until all v1 imports gone */}
|
|
20
|
+
<BitkitProvider> {/* v2 */}
|
|
21
|
+
<App />
|
|
22
|
+
</BitkitProvider>
|
|
23
|
+
</Provider>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
> **Note on CSS conflicts**: If Chakra v3's preflight reset causes visual conflicts during coexistence, `BitkitProvider` can't help — it hardcodes its internal system with `preflight: true` and doesn't expose an override. The fallback is `ChakraProvider` with a custom system where `preflight: false`, but be aware that also drops Bitkit's bundled font imports and `BitkitToaster` — those would need to be re-added manually.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Migration order
|
|
31
|
+
|
|
32
|
+
Migrate in this order to minimize blockers:
|
|
33
|
+
|
|
34
|
+
1. **Primitives**: `Box`, `Text`, `Divider` — these are used everywhere, get them out of the way first
|
|
35
|
+
2. **Atomic components**: `Button`, `Badge`, `Tag`, `Spinner`, `Toast`
|
|
36
|
+
3. **Form components**: `Input`, `Textarea`, `Select`, `Checkbox`, `Switch`
|
|
37
|
+
4. **Layout & navigation**: `Sidebar`, `Breadcrumb`
|
|
38
|
+
5. **Composite components**: `Dialog`, `Tabs`, `Table`, `Card`, `Alert`
|
|
39
|
+
6. **Icons** (if migrating from `lucide-react` or similar)
|
|
40
|
+
7. **Dependency cleanup**: remove v1 and all now-unused peer deps
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Component mapping
|
|
45
|
+
|
|
46
|
+
### Primitives
|
|
47
|
+
|
|
48
|
+
| v1 | v2 |
|
|
49
|
+
|----|----|
|
|
50
|
+
| `Box` from `@bitrise/bitkit` | `Box` from `@chakra-ui/react/box` |
|
|
51
|
+
| `Text` from `@bitrise/bitkit` | `Text` from `@chakra-ui/react/text` |
|
|
52
|
+
| `Divider` | `Separator` from `@chakra-ui/react/separator` |
|
|
53
|
+
| `BoxProps`, `TextProps` | same, from `@chakra-ui/react/box` and `@chakra-ui/react/text` |
|
|
54
|
+
|
|
55
|
+
Chakra v2 → v3 prop changes on primitives:
|
|
56
|
+
- `noOfLines` → `lineClamp`
|
|
57
|
+
- `Box as="a" href="..."` doesn't work → use `chakra.a` from `@chakra-ui/react/styled-system`
|
|
58
|
+
- `Box as="button" onClick={...}` → use `chakra.button` from `@chakra-ui/react/styled-system`
|
|
59
|
+
|
|
60
|
+
### Buttons
|
|
61
|
+
|
|
62
|
+
| v1 | v2 |
|
|
63
|
+
|----|----|
|
|
64
|
+
| `Button` | `BitkitButton` |
|
|
65
|
+
| `IconButton` | `BitkitIconButton` |
|
|
66
|
+
| `leftIconName` | `icon` |
|
|
67
|
+
| `isDisabled` | `state="disabled"` |
|
|
68
|
+
| `isLoading` | `state="loading"` |
|
|
69
|
+
|
|
70
|
+
**Gotcha**: `BitkitButton` requires `children` to be a `string`. If a button contains complex layout (icon + text, conditional content, custom JSX), use `chakra.button` from `@chakra-ui/react/styled-system` instead of forcing it into `BitkitButton`.
|
|
71
|
+
|
|
72
|
+
### Badge / Tag
|
|
73
|
+
|
|
74
|
+
| v1 | v2 |
|
|
75
|
+
|----|----|
|
|
76
|
+
| `Badge colorScheme="positive"` | `BitkitBadge colorPalette="green"` |
|
|
77
|
+
| `Badge colorScheme="negative"` | `BitkitBadge colorPalette="red"` |
|
|
78
|
+
| `Badge colorScheme="warning"` | `BitkitBadge colorPalette="yellow"` |
|
|
79
|
+
| `Badge colorScheme="progress"` | `BitkitBadge colorPalette="purple"` |
|
|
80
|
+
| `Tag` | `BitkitTag` |
|
|
81
|
+
|
|
82
|
+
### Toast
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
// v1
|
|
86
|
+
const toast = useToast()
|
|
87
|
+
toast({ status: 'error', title: 'Oops', description: 'Something failed' })
|
|
88
|
+
|
|
89
|
+
// v2
|
|
90
|
+
createBitkitToast({ variant: 'critical', titleText: 'Oops', messageText: 'Something failed' })
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`status` → `variant`, and `'error'` → `'critical'`. Note: `createBitkitToast` is called directly with props — it's not a factory that returns a function.
|
|
94
|
+
|
|
95
|
+
### Dialogs
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
// v1
|
|
99
|
+
<Dialog isOpen={open} onClose={() => setOpen(false)}>
|
|
100
|
+
<DialogBody>...</DialogBody>
|
|
101
|
+
<DialogFooter>...</DialogFooter>
|
|
102
|
+
</Dialog>
|
|
103
|
+
|
|
104
|
+
// v2
|
|
105
|
+
<BitkitDialog open={open} onOpenChange={({ open }) => setOpen(open)}>
|
|
106
|
+
<BitkitDialog.Body>...</BitkitDialog.Body>
|
|
107
|
+
<BitkitDialog.Footer>
|
|
108
|
+
<BitkitDialog.Buttons>...</BitkitDialog.Buttons>
|
|
109
|
+
</BitkitDialog.Footer>
|
|
110
|
+
</BitkitDialog>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Key changes: `isOpen` → `open`, `onClose` → `onOpenChange` (receives `{ open: boolean }`).
|
|
114
|
+
|
|
115
|
+
### Tabs
|
|
116
|
+
|
|
117
|
+
The API changed fundamentally — from index-based to value-based:
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
// v1 (index-based)
|
|
121
|
+
<Tabs>
|
|
122
|
+
<TabList>
|
|
123
|
+
<Tab>First</Tab>
|
|
124
|
+
<Tab>Second</Tab>
|
|
125
|
+
</TabList>
|
|
126
|
+
<TabPanels>
|
|
127
|
+
<TabPanel>...</TabPanel>
|
|
128
|
+
<TabPanel>...</TabPanel>
|
|
129
|
+
</TabPanels>
|
|
130
|
+
</Tabs>
|
|
131
|
+
|
|
132
|
+
// v2 (value-based)
|
|
133
|
+
<BitkitTabs.Root defaultValue="first">
|
|
134
|
+
<BitkitTabs.List>
|
|
135
|
+
<BitkitTabs.Trigger value="first">First</BitkitTabs.Trigger>
|
|
136
|
+
<BitkitTabs.Trigger value="second">Second</BitkitTabs.Trigger>
|
|
137
|
+
</BitkitTabs.List>
|
|
138
|
+
<BitkitTabs.ContentGroup>
|
|
139
|
+
<BitkitTabs.Content value="first">...</BitkitTabs.Content>
|
|
140
|
+
<BitkitTabs.Content value="second">...</BitkitTabs.Content>
|
|
141
|
+
</BitkitTabs.ContentGroup>
|
|
142
|
+
</BitkitTabs.Root>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
This is one of the more involved migrations — every tab needs an explicit `value`.
|
|
146
|
+
|
|
147
|
+
### Table
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
// v1 — flat imports
|
|
151
|
+
import { Table, Thead, Tbody, Tr, Th, Td, TableContainer } from '@bitrise/bitkit'
|
|
152
|
+
|
|
153
|
+
// v2 — namespace
|
|
154
|
+
import { Table } from '@chakra-ui/react/table'
|
|
155
|
+
<Table.Root><Table.Header><Table.Row><Table.ColumnHeader>
|
|
156
|
+
<Table.Body><Table.Row><Table.Cell>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Forms
|
|
160
|
+
|
|
161
|
+
| v1 | v2 |
|
|
162
|
+
|----|----|
|
|
163
|
+
| `Input` | `BitkitTextInput` |
|
|
164
|
+
| `Textarea` | `BitkitTextArea` |
|
|
165
|
+
| `Select` | `BitkitNativeSelect` |
|
|
166
|
+
| `Checkbox` | `BitkitCheckbox` |
|
|
167
|
+
| `Toggle` (`Switch` in v1) | `BitkitSwitch` |
|
|
168
|
+
| `SearchInput` | `BitkitSearchInput` |
|
|
169
|
+
|
|
170
|
+
For password fields with an eye-toggle: use `BitkitField` + Chakra v3 `InputGroup` with `endElement`.
|
|
171
|
+
|
|
172
|
+
### Cards
|
|
173
|
+
|
|
174
|
+
| v1 | v2 |
|
|
175
|
+
|----|----|
|
|
176
|
+
| `Card` | `BitkitCard` |
|
|
177
|
+
| `ExpandableCard` | `BitkitExpandableCard` |
|
|
178
|
+
|
|
179
|
+
`BitkitCard` accepts `paddingSize` and `elevation` (boolean). Common `BitkitExpandableCard` props: `title`, `secdText`, `size`; use `defaultExpanded` for uncontrolled or `expanded`/`onChange` for controlled usage. It also supports `icon`, `suffix`, and other options — see the component API for the full list.
|
|
180
|
+
|
|
181
|
+
If your codebase has a local `card.tsx` wrapper around v1 Card (e.g. Shadcn-style `CardHeader`, `CardContent` etc.), remove the wrapper entirely and migrate to `BitkitCard` directly — keeping the wrapper layer just adds indirection you'll need to unwind later.
|
|
182
|
+
|
|
183
|
+
### Notifications / Alert
|
|
184
|
+
|
|
185
|
+
| v1 | v2 |
|
|
186
|
+
|----|----|
|
|
187
|
+
| `Notification` | `BitkitAlert` |
|
|
188
|
+
|
|
189
|
+
### Sidebar & Breadcrumb
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
// Sidebar v2
|
|
193
|
+
<BitkitSidebar>
|
|
194
|
+
<BitkitSidebar.Title>Title</BitkitSidebar.Title>
|
|
195
|
+
<BitkitSidebar.GroupHeading>Group</BitkitSidebar.GroupHeading>
|
|
196
|
+
<BitkitSidebar.Item icon={IconName} selected={...}>Label</BitkitSidebar.Item>
|
|
197
|
+
</BitkitSidebar>
|
|
198
|
+
|
|
199
|
+
// Breadcrumb v2
|
|
200
|
+
<BitkitBreadcrumb>
|
|
201
|
+
<BitkitBreadcrumb.Item href="#/path">Label</BitkitBreadcrumb.Item>
|
|
202
|
+
<BitkitBreadcrumb.CurrentItem>Current</BitkitBreadcrumb.CurrentItem>
|
|
203
|
+
</BitkitBreadcrumb>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**HashRouter gotcha**: `BitkitBreadcrumb` uses plain `href`. With HashRouter all links need the `#/` prefix (e.g. `href="#/sessions"`), otherwise navigation breaks silently.
|
|
207
|
+
|
|
208
|
+
**Version requirement**: `BitkitBreadcrumb` requires `@bitrise/bitkit-v2 >= 0.3.210`.
|
|
209
|
+
|
|
210
|
+
### textStyle tokens
|
|
211
|
+
|
|
212
|
+
Replace explicit `fontSize` / `fontWeight` / `lineHeight` props on `<Text>` with `textStyle` tokens:
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
// Before
|
|
216
|
+
<Text fontSize="14px" fontWeight="600" lineHeight="20px">...</Text>
|
|
217
|
+
|
|
218
|
+
// After
|
|
219
|
+
<Text textStyle="body/md/semibold">...</Text>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Common tokens: `body/sm/regular`, `body/md/regular`, `body/md/semibold`, `body/lg/semibold`, `heading/h3` … `heading/h1`. Do this alongside the component migration per file — don't leave it for a separate pass at the end, it accumulates quickly.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Action menus
|
|
227
|
+
|
|
228
|
+
If the codebase has a hand-rolled dropdown/action menu (state + ref + `useEffect` for click-outside), replace it with `BitkitActionMenu`:
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
<BitkitActionMenu.Root trigger={<button>...</button>}>
|
|
232
|
+
<BitkitActionMenu.Item onClick={...}>Edit</BitkitActionMenu.Item>
|
|
233
|
+
<BitkitActionMenu.Separator />
|
|
234
|
+
<BitkitActionMenu.Item onClick={...} danger>Delete</BitkitActionMenu.Item>
|
|
235
|
+
</BitkitActionMenu.Root>
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Color tokens: `text/*` vs `icon/*`
|
|
241
|
+
|
|
242
|
+
Use `text/*` tokens on `<Text>` (and other text elements), and `icon/*` tokens on `<Icon*>` components. Most pairs resolve to the same underlying color, so a mismatch won't be visible — but the semantics matter.
|
|
243
|
+
|
|
244
|
+
| `text/*` token | `icon/*` equivalent | Same color? |
|
|
245
|
+
|---|---|---|
|
|
246
|
+
| `text/secondary` | `icon/secondary` | ✓ |
|
|
247
|
+
| `text/tertiary` | `icon/tertiary` | ✓ |
|
|
248
|
+
| `text/link` | `icon/interactive` | ✓ (both → `sys.interactive`) |
|
|
249
|
+
|
|
250
|
+
**Gotcha**: `icon/link` does **not** exist. Use `icon/interactive` instead — it resolves to the same `sys.interactive` color as `text/link`.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Dependency cleanup
|
|
255
|
+
|
|
256
|
+
After the migration, audit `package.json` carefully — v1 pulled in transitive deps that may still be listed:
|
|
257
|
+
|
|
258
|
+
- `@emotion/react` — you may no longer need to list it directly in your app's `package.json`; `@bitrise/bitkit-v2` brings it transitively
|
|
259
|
+
- `lucide-react` — if icons are now from `@bitrise/bitkit-v2`
|
|
260
|
+
- `zustand` — if Bitkit's sidebar hook was the only consumer
|
|
261
|
+
- `@types/luxon`, `patch-package`, `postcss` — check if still used
|
|
262
|
+
|
|
263
|
+
Also check `scripts` in `package.json` for any `postinstall` entries referencing removed packages (e.g. `"postinstall": "patch-package"`) — these will silently break CI.
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Working efficiently (token / context budget)
|
|
268
|
+
|
|
269
|
+
Migrating a large repo component-by-component is token-intensive. What works well:
|
|
270
|
+
|
|
271
|
+
- **Grep first, cheap**: `grep -r "@bitrise/bitkit" src --include="*.tsx" -l` gives you the full scope before touching anything
|
|
272
|
+
- **You navigate, AI executes**: identify the interesting/complex files yourself, hand them over one at a time. Avoid "replace all X with Y across the entire repo" — it requires reading every file even for trivial changes
|
|
273
|
+
- **Codemods for mechanical swaps**: simple renames across many files (`Box` → `chakra.Box`, import path changes) are better done with `sed` or a codemod script; use AI for the cases that need judgment
|
|
274
|
+
- **Identify custom components early**: look for any local wrappers around v1 components or hand-rolled alternatives to v2 components (dropdowns, cards, dialogs). Plan to replace these, not wrap them again
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Pre-migration checklist
|
|
279
|
+
|
|
280
|
+
- [ ] `grep -r "@bitrise/bitkit" src` — inventory of files and components
|
|
281
|
+
- [ ] Identify local wrapper components around v1 Bitkit components
|
|
282
|
+
- [ ] Identify hand-rolled alternatives to v2 components (dropdowns, modals, etc.)
|
|
283
|
+
- [ ] Check `@bitrise/bitkit-v2` changelog for version requirements per component
|
|
284
|
+
- [ ] Check if HashRouter is in use (affects Breadcrumb `href`)
|
|
285
|
+
- [ ] Note any buttons with complex children (non-string) — these need `chakra.button`
|
|
286
|
+
|
|
287
|
+
## Post-migration checklist
|
|
288
|
+
|
|
289
|
+
- [ ] Zero `@bitrise/bitkit` imports in source
|
|
290
|
+
- [ ] `npm run build` passes
|
|
291
|
+
- [ ] `npm run lint` clean
|
|
292
|
+
- [ ] Remove `@bitrise/bitkit` from `package.json`
|
|
293
|
+
- [ ] Remove transitively-pulled peer deps that are no longer needed
|
|
294
|
+
- [ ] Check all `scripts` entries in `package.json` for references to removed packages
|
|
295
|
+
- [ ] Visual walkthrough: all pages, dialogs, tabs, forms, toasts, tables
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitrise/bitkit-v2",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.211",
|
|
5
5
|
"description": "Bitrise Design System Components built with Chakra UI V3",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"react",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"type": "module",
|
|
14
14
|
"files": [
|
|
15
15
|
"dist",
|
|
16
|
+
"docs",
|
|
16
17
|
"scripts/postinstall.cjs",
|
|
17
18
|
"README.md",
|
|
18
19
|
"package.json"
|