@tamagui/cli 2.7.7 → 3.0.0-beta.1097.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/dist/add.cjs +76 -87
- package/dist/build.cjs +425 -278
- package/dist/cli.cjs +361 -340
- package/dist/generate-prompt.cjs +484 -362
- package/dist/generate.cjs +45 -54
- package/dist/index.cjs +1 -1
- package/dist/migrate.cjs +437 -0
- package/dist/setup-prompt.cjs +216 -0
- package/dist/to-tailwind-default-config.cjs +789 -0
- package/dist/to-tailwind.cjs +213 -0
- package/dist/update-template.cjs +43 -52
- package/dist/update.cjs +14 -18
- package/dist/upgrade.cjs +417 -401
- package/dist/utils.cjs +84 -101
- package/metro.cjs +1 -0
- package/metro.d.ts +1 -0
- package/metro.mjs +1 -0
- package/package.json +43 -13
- package/src/build.ts +594 -362
- package/src/cli.ts +113 -12
- package/src/generate-prompt.ts +428 -329
- package/src/migrate.ts +422 -0
- package/src/setup-prompt.ts +192 -0
- package/src/to-tailwind-default-config.ts +767 -0
- package/src/to-tailwind.ts +313 -0
- package/src/upgrade.ts +30 -33
- package/src/utils.ts +11 -9
- package/types/add.d.ts +1 -1
- package/types/add.d.ts.map +1 -1
- package/types/build.d.ts +2 -1
- package/types/build.d.ts.map +1 -1
- package/types/generate-prompt.d.ts +6 -2
- package/types/generate-prompt.d.ts.map +1 -1
- package/types/migrate.d.ts +7 -0
- package/types/migrate.d.ts.map +1 -0
- package/types/setup-prompt.d.ts +5 -0
- package/types/setup-prompt.d.ts.map +1 -0
- package/types/to-tailwind-default-config.d.ts +53 -0
- package/types/to-tailwind-default-config.d.ts.map +1 -0
- package/types/to-tailwind.d.ts +16 -0
- package/types/to-tailwind.d.ts.map +1 -0
- package/types/upgrade.d.ts.map +1 -1
- package/types/utils.d.ts.map +1 -1
- package/vite.cjs +1 -0
- package/vite.d.ts +1 -0
- package/vite.mjs +1 -0
package/src/migrate.ts
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
type MigrationFrom = 'v1' | 'v2'
|
|
2
|
+
|
|
3
|
+
export function printMigrationPrompt({ from }: { from?: string }) {
|
|
4
|
+
process.stdout.write(getMigrationPrompt({ from }))
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function getMigrationPrompt({ from }: { from?: string } = {}) {
|
|
8
|
+
const source = normalizeFrom(from)
|
|
9
|
+
|
|
10
|
+
if (source === 'v1') {
|
|
11
|
+
return `${promptHeader('v1', 'v3')}
|
|
12
|
+
|
|
13
|
+
${v1ToV2Prompt}
|
|
14
|
+
|
|
15
|
+
After the v1 to v2 pass is complete, apply the v2 to v3 pass below.
|
|
16
|
+
|
|
17
|
+
${v2ToV3Prompt}
|
|
18
|
+
`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return `${promptHeader('v2', 'v3')}
|
|
22
|
+
|
|
23
|
+
${v2ToV3Prompt}
|
|
24
|
+
`
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function normalizeFrom(from: string | undefined): MigrationFrom {
|
|
28
|
+
const value = (from || 'v2').toLowerCase().replace(/^from-?/, '')
|
|
29
|
+
|
|
30
|
+
if (value === '1' || value === 'v1') return 'v1'
|
|
31
|
+
if (value === '2' || value === 'v2') return 'v2'
|
|
32
|
+
|
|
33
|
+
throw new Error('Usage: tamagui migrate --from v2 | --from v1')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function promptHeader(from: string, to: string) {
|
|
37
|
+
return `You are migrating a Tamagui app from ${from} to ${to}.
|
|
38
|
+
|
|
39
|
+
Work like a careful coding agent:
|
|
40
|
+
|
|
41
|
+
- Read the app's Tamagui config, package manager, bundler, and component usage before editing.
|
|
42
|
+
- Keep changes scoped to the migration.
|
|
43
|
+
- Run the codemods listed below, then review the diff by hand.
|
|
44
|
+
- Do not publish packages, rotate secrets, or change production infrastructure.
|
|
45
|
+
- Validate with typecheck/build and at least one real app run or browser/native smoke test.
|
|
46
|
+
- Report any behavior that cannot be migrated mechanically.`
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const v2ToV3Prompt = `## v2 -> v3 migration prompt
|
|
50
|
+
|
|
51
|
+
### 0. Choose the intermediate checkpoint before editing
|
|
52
|
+
|
|
53
|
+
The Tamagui package version and the config version are separate. Tamagui V3
|
|
54
|
+
supports Config v5; upgrading the runtime does not require Config v6.
|
|
55
|
+
|
|
56
|
+
- Coming from V2: first reach V3 packages and APIs with the app's existing token, theme, font, media, and animation values. Keep custom config values. If an old config entry is no longer exported, preserve its resolved values in an app-owned config; do not substitute v6 defaults.
|
|
57
|
+
- Coming from Config v5 or v5-subtle: keep that config during the V3 API upgrade. Keep the 12-step adaptive colors, spacing, radii, font scales, and breakpoint meanings. Do not remap them to the v6 scale.
|
|
58
|
+
- Already running V3 with Config v5: this intermediate checkpoint is valid. Inventory remaining V2 APIs before applying codemods; do not repeat completed work or treat Config v5 as an upgrade failure.
|
|
59
|
+
- Do not combine this pass with wholesale \`html.*\` adoption, Tailwind conversion, new skins, or a theme redesign unless separately requested.
|
|
60
|
+
|
|
61
|
+
Record the starting package/config versions and representative light/dark,
|
|
62
|
+
responsive, and native screenshots. Name the intended checkpoint in the plan:
|
|
63
|
+
"V3 API, existing design values." Visual changes during this pass need an
|
|
64
|
+
explanation or a fix, not automatic screenshot acceptance.
|
|
65
|
+
|
|
66
|
+
The checkpoint is complete when the required API migration, report review,
|
|
67
|
+
typecheck/build, and real app checks in step 15 pass. Leave Config v6 and other
|
|
68
|
+
optional design changes in a separate follow-up; do not start them just because
|
|
69
|
+
the V3 API work is finished.
|
|
70
|
+
|
|
71
|
+
### 1. Update dependencies
|
|
72
|
+
|
|
73
|
+
- Bump every \`tamagui\` and \`@tamagui/*\` package together to v3.
|
|
74
|
+
- Keep \`@tamagui/core\`, \`@tamagui/web\`, and \`tamagui\` deduped in the lockfile.
|
|
75
|
+
- Run:
|
|
76
|
+
|
|
77
|
+
\`\`\`bash
|
|
78
|
+
npx tamagui check
|
|
79
|
+
\`\`\`
|
|
80
|
+
|
|
81
|
+
### 2. Migrate tokens and conditional styles
|
|
82
|
+
|
|
83
|
+
V3 accepts bare token/theme names and flat clauses only. Run the transactional
|
|
84
|
+
flat-values codemod from your project root, dry run first:
|
|
85
|
+
|
|
86
|
+
\`\`\`bash
|
|
87
|
+
npx @tamagui/codemod-flat-values --report flat-values-report.md ./src
|
|
88
|
+
npx @tamagui/codemod-flat-values --write \\
|
|
89
|
+
--report flat-values-report.md \\
|
|
90
|
+
--json flat-values-report.json \\
|
|
91
|
+
./src
|
|
92
|
+
\`\`\`
|
|
93
|
+
|
|
94
|
+
For example, this V2 input:
|
|
95
|
+
|
|
96
|
+
\`\`\`tsx
|
|
97
|
+
<View bg="$background" hoverStyle={{ bg: '$backgroundHover' }} $sm={{ p: '$6' }} p="$4" />
|
|
98
|
+
\`\`\`
|
|
99
|
+
|
|
100
|
+
becomes:
|
|
101
|
+
|
|
102
|
+
\`\`\`tsx
|
|
103
|
+
<View bg="background hover:background-hover" p="4 sm:6" />
|
|
104
|
+
\`\`\`
|
|
105
|
+
|
|
106
|
+
Resolve every report row and rerun until the app has no V2 authoring. Do not
|
|
107
|
+
add a compatibility setting or restore condition-object parsing.
|
|
108
|
+
|
|
109
|
+
### 3. Preserve config values while migrating required APIs
|
|
110
|
+
|
|
111
|
+
- Existing Config v5 applications should keep \`@tamagui/config/v5\` or \`/v5-subtle\` while migrating incrementally. These are frozen static compatibility packs, so they preserve the V5 token and theme values but will not receive new theme-builder features.
|
|
112
|
+
- Import animations from \`@tamagui/config/animations-css\`, \`animations-rn\`, \`animations-reanimated\`, or \`animations-motion\`.
|
|
113
|
+
- Apps using Sheet or animated-number hooks with the CSS driver must import \`createAnimations\` from \`@tamagui/animations-css/extras\`. The root entry omits those hooks.
|
|
114
|
+
- Remove \`@tamagui/theme-builder\` and V5 builder imports from packages that no longer export them. Static \`@tamagui/themes/v5\`, \`/v5-subtle\`, and \`/v5-tokens\` imports remain supported.
|
|
115
|
+
- An app that GENERATES its v5 themes (\`createV5Theme\`, \`subtleChildrenThemes\`, \`createPalettes\`) has two ways to stay on v5 for this migration: run the builder once and serialize the result to a static literal, or import the same builders from \`@tamagui/config-v5\` (and \`@tamagui/config-v5/builder\`), the opt-in package that carries them. Take one of those when the themes are built from values the app only knows at runtime; the optional v6 recipe move in the appendix is a separate migration.
|
|
116
|
+
- Component names no longer select uppercase theme segments automatically. Replace component themes with explicit normal theme or \`level2\` boundaries in component skins.
|
|
117
|
+
|
|
118
|
+
Do not apply the v6 color remap or recipe conversion in the optional appendix
|
|
119
|
+
while keeping Config v5. Reserved API/theme-key spelling changes still apply;
|
|
120
|
+
preserve the resolved values behind the renamed keys.
|
|
121
|
+
|
|
122
|
+
### 4. Migrate Sheet anatomy
|
|
123
|
+
|
|
124
|
+
The flat-values codemod from step 2 rewrites every provable \`Sheet.Frame\` to
|
|
125
|
+
\`Sheet.Container\` with a \`Sheet.Background\` first child carrying the surface
|
|
126
|
+
props, and reports spreads and \`styled(Sheet.Frame, …)\` targets for review.
|
|
127
|
+
Check each rewritten callsite against these rules:
|
|
128
|
+
|
|
129
|
+
- Replace \`Sheet.Frame\` with \`Sheet.Container\` plus \`Sheet.Background\`.
|
|
130
|
+
- Keep layout props such as \`padding\`, \`gap\`, \`height\`, \`maxHeight\`, and flex props on \`Sheet.Container\`.
|
|
131
|
+
- Move visual surface props such as \`bg\`, \`borderRadius\`, \`elevation\`, and \`shadow*\` to \`Sheet.Background\`.
|
|
132
|
+
- Keep \`Sheet.Overlay\` as a direct child of \`Sheet\`.
|
|
133
|
+
- Add explicit clipping if old \`Sheet.Frame\` overflow clipping mattered.
|
|
134
|
+
- \`disableHideBottomOverflow\` belongs on \`Sheet.Background\`.
|
|
135
|
+
|
|
136
|
+
Before:
|
|
137
|
+
|
|
138
|
+
\`\`\`tsx
|
|
139
|
+
<Sheet>
|
|
140
|
+
<Sheet.Overlay />
|
|
141
|
+
<Sheet.Frame padding="$4" bg="$background" borderTopRadius="$6">
|
|
142
|
+
<Sheet.ScrollView>{children}</Sheet.ScrollView>
|
|
143
|
+
</Sheet.Frame>
|
|
144
|
+
</Sheet>
|
|
145
|
+
\`\`\`
|
|
146
|
+
|
|
147
|
+
After:
|
|
148
|
+
|
|
149
|
+
\`\`\`tsx
|
|
150
|
+
<Sheet>
|
|
151
|
+
<Sheet.Overlay />
|
|
152
|
+
<Sheet.Container padding="4">
|
|
153
|
+
<Sheet.Background bg="background" borderTopRadius="6" />
|
|
154
|
+
<Sheet.ScrollView>{children}</Sheet.ScrollView>
|
|
155
|
+
</Sheet.Container>
|
|
156
|
+
</Sheet>
|
|
157
|
+
\`\`\`
|
|
158
|
+
|
|
159
|
+
### 5. Remove deprecated v2 APIs
|
|
160
|
+
|
|
161
|
+
Search:
|
|
162
|
+
|
|
163
|
+
\`\`\`bash
|
|
164
|
+
rg "focusable|fullscreen|themeInverse|<Theme inverse|Sheet\\.Frame|styleable\\(|inlineWhenUnflattened|\\$true|getTokenRelative|stepTokenUpOrDown|forceRemoveScrollEnabled|sizeAdjust|getExpandedShorthands|usePropsAndStyle|useProps|useStyle"
|
|
165
|
+
\`\`\`
|
|
166
|
+
|
|
167
|
+
Replace:
|
|
168
|
+
|
|
169
|
+
- \`focusable\` -> \`tabIndex\`.
|
|
170
|
+
- \`fullscreen\` -> explicit \`position\` and \`inset\` props.
|
|
171
|
+
- \`themeInverse\` -> \`theme="inverse"\`.
|
|
172
|
+
- \`<Theme inverse>\` -> \`<Theme name="inverse">\`.
|
|
173
|
+
- \`Sheet.Frame\` -> \`Sheet.Container\` plus \`Sheet.Background\`.
|
|
174
|
+
- \`Component.styleable(fn)\` -> \`createStyledHOC(Component, fn)\` (same behavior, standalone function).
|
|
175
|
+
- forwardRef wrapper statics -> direct refs and normal composition.
|
|
176
|
+
- \`inlineWhenUnflattened\` -> remove it.
|
|
177
|
+
- deprecated UI kit aliases -> current component names.
|
|
178
|
+
- old platform style keys -> flat \`web:\`, \`native:\`, \`ios:\`, and \`android:\` clauses.
|
|
179
|
+
- \`forceRemoveScrollEnabled\` -> \`disableRemoveScroll\` with inverted intent.
|
|
180
|
+
- \`createCheckbox\` \`sizeAdjust\` -> explicit sizing math or component styles.
|
|
181
|
+
- \`getExpandedShorthands\` -> \`getExpandedShorthand(key, props)\` when behavior code needs one authored prop and must accept its configured shorthand.
|
|
182
|
+
- \`useProps\`, \`useStyle\`, and \`usePropsAndStyle\` -> keep conditional values on styled Tamagui components; use \`splitStyleProps\` only when a wrapper must partition authored props.
|
|
183
|
+
|
|
184
|
+
V2 could spread one style across its base prop, pseudo-style objects, media
|
|
185
|
+
objects, and platform objects. The removed hooks gathered those separate
|
|
186
|
+
objects into resolved props and styles. V3 keeps every base and conditional
|
|
187
|
+
clause for a style on that style's single property, for example
|
|
188
|
+
\`opacity="1 hover:0.7 sm:0.8"\`. The styled component interprets that value,
|
|
189
|
+
so a wrapper should pass it through instead of flattening the component's
|
|
190
|
+
styles in JavaScript.
|
|
191
|
+
|
|
192
|
+
\`splitStyleProps(props)\` returns \`[styleProps, regularProps]\` in one pass.
|
|
193
|
+
Pass \`{ expandShorthands: true }\` to canonicalize selected keys. Its optional
|
|
194
|
+
filter map selects only those canonical keys, leaving rejected style props in
|
|
195
|
+
the second object. The filter may instead be a callback receiving
|
|
196
|
+
\`(key, value, originalKey, isStyleProp)\`.
|
|
197
|
+
|
|
198
|
+
\`getExpandedShorthand(key, props)\` only chooses the longhand or configured
|
|
199
|
+
shorthand for one property. It does not resolve tokens or select the active
|
|
200
|
+
clause. Neither does \`splitStyleProps\`. Use \`useMedia()\` or \`useTheme()\`
|
|
201
|
+
when behavior itself needs active responsive or theme state.
|
|
202
|
+
|
|
203
|
+
### 6. Replace true tokens
|
|
204
|
+
|
|
205
|
+
- Default v3 configs no longer export the legacy \`$true\` token key.
|
|
206
|
+
- The codemod writes \`$true\` on style props as \`4\` and reports a \`legacy-true-token\` warning; confirm the app's config aliased it there.
|
|
207
|
+
- On \`size\`, \`elevation\`, and \`iconSize\` it writes the boolean \`true\`, which resolves to the component default size.
|
|
208
|
+
- Token definitions and custom variants are not edited; search them for the alias by hand.
|
|
209
|
+
- Do not change unrelated boolean props or boolean variant values.
|
|
210
|
+
|
|
211
|
+
### 7. Replace token stepping
|
|
212
|
+
|
|
213
|
+
Removed from \`@tamagui/get-token\`:
|
|
214
|
+
|
|
215
|
+
- \`stepTokenUpOrDown\`
|
|
216
|
+
- \`getTokenRelative\`
|
|
217
|
+
- the second options argument to \`getSize\`, \`getSpace\`, and \`getRadius\`
|
|
218
|
+
- \`shift\`, \`bounds\`, and \`excludeHalfSteps\`
|
|
219
|
+
|
|
220
|
+
Before:
|
|
221
|
+
|
|
222
|
+
\`\`\`tsx
|
|
223
|
+
const padding = getSize(size, { shift: -2 })
|
|
224
|
+
\`\`\`
|
|
225
|
+
|
|
226
|
+
After:
|
|
227
|
+
|
|
228
|
+
\`\`\`tsx
|
|
229
|
+
const padding = getVariableValue(getSize(size)) * 0.6
|
|
230
|
+
\`\`\`
|
|
231
|
+
|
|
232
|
+
Use explicit token keys when you need a named smaller or larger token. Use numeric multiplication when proportional sizing is intended.
|
|
233
|
+
|
|
234
|
+
### 8. Audit font size values
|
|
235
|
+
|
|
236
|
+
- \`fontSize={17}\` is a raw numeric platform value and keeps platform-default line-height behavior.
|
|
237
|
+
- \`fontSize="17px"\` is an exact pixel value.
|
|
238
|
+
- Configured font \`size\` and \`lineHeight\` tokens should use px strings when exact web pixels are intended.
|
|
239
|
+
- Convert custom config font tokens to px strings if exact pixels were intended.
|
|
240
|
+
|
|
241
|
+
### 9. Update FocusScope
|
|
242
|
+
|
|
243
|
+
- Function-as-children is removed. Pass JSX children directly.
|
|
244
|
+
- FocusScope renders a \`display: contents\` wrapper.
|
|
245
|
+
- Use \`noFocus\` for zero-focus mode when focus should be rejected entirely.
|
|
246
|
+
|
|
247
|
+
Before:
|
|
248
|
+
|
|
249
|
+
\`\`\`tsx
|
|
250
|
+
<FocusScope loop>
|
|
251
|
+
{({ ref, onKeyDown, tabIndex }) => (
|
|
252
|
+
<View ref={ref} onKeyDown={onKeyDown} tabIndex={tabIndex} />
|
|
253
|
+
)}
|
|
254
|
+
</FocusScope>
|
|
255
|
+
\`\`\`
|
|
256
|
+
|
|
257
|
+
After:
|
|
258
|
+
|
|
259
|
+
\`\`\`tsx
|
|
260
|
+
<FocusScope loop>
|
|
261
|
+
<View />
|
|
262
|
+
</FocusScope>
|
|
263
|
+
\`\`\`
|
|
264
|
+
|
|
265
|
+
### 10. Update Dialog, Popover, Select, and Adapt flows
|
|
266
|
+
|
|
267
|
+
- Dialog, Popover, and Select use one Adapt handoff model.
|
|
268
|
+
- Adapted Sheet content stays mounted through the sheet slide-out.
|
|
269
|
+
- Parts own their presence animation lifecycles.
|
|
270
|
+
- The \`onDidAnimate\` prop is replaced by the typed \`onTransition\` lifecycle: \`onTransition={(e) => e.phase === 'end' && e.cause === 'enter' && done()}\`.
|
|
271
|
+
- \`Popover.Content forceMount\` now matches Dialog semantics.
|
|
272
|
+
- \`Dialog.Content\` no longer accepts the old no-op \`size\` variant.
|
|
273
|
+
- Non-modal Dialog content no longer enables RemoveScroll while open.
|
|
274
|
+
- Remove internal imports such as \`useShowPopoverSheet\`, \`PopoverAdaptHiddenContext\`, or \`useSelectBreakpointActive\` if the app used them.
|
|
275
|
+
|
|
276
|
+
### 11. Update Select
|
|
277
|
+
|
|
278
|
+
- Keep \`name\` when Select participates in a form. Remove the unsupported \`autoComplete\` prop.
|
|
279
|
+
- Use \`Select.Separator\` for visual grouping.
|
|
280
|
+
- \`Select.Content\` accepts \`onEscapeKeyDown\` and \`onInteractOutside\`.
|
|
281
|
+
- \`Select.Trigger\` and web \`Select.Viewport\` expose \`data-state="open" | "closed"\`.
|
|
282
|
+
|
|
283
|
+
### 12. Update themed icons
|
|
284
|
+
|
|
285
|
+
- \`<Icon size="4" />\` now resolves through the current font's \`font.size['4']\` scale.
|
|
286
|
+
- Raw numeric icon sizes are unchanged.
|
|
287
|
+
- Themed icons no longer accept Tamagui media or pseudo props directly.
|
|
288
|
+
- Wrap icons in a styled \`View\` for media and state clauses.
|
|
289
|
+
|
|
290
|
+
### 13. Check ScrollView web usage
|
|
291
|
+
|
|
292
|
+
\`@tamagui/scroll-view\` now has its own web implementation. It supports \`scrollTo\`, \`scrollToEnd\`, \`getScrollableNode\`, RN-shaped \`onScroll\`, \`contentContainerStyle\`, \`horizontal\`, and indicator props.
|
|
293
|
+
|
|
294
|
+
Replace unsupported old web/lite usage such as momentum events, \`snapTo*\`, and \`keyboardDismissMode\`.
|
|
295
|
+
|
|
296
|
+
### 14. Optional Tailwind frontend
|
|
297
|
+
|
|
298
|
+
Skip this in the intermediate V3 API checkpoint unless Tailwind adoption was
|
|
299
|
+
separately requested. It does not require changing the whole app to Config v6.
|
|
300
|
+
|
|
301
|
+
Tailwind authoring is selected by the component package, with no global config:
|
|
302
|
+
|
|
303
|
+
\`\`\`tsx
|
|
304
|
+
import { View, Text, styled } from '@tamagui/tailwind'
|
|
305
|
+
\`\`\`
|
|
306
|
+
|
|
307
|
+
Keep importing regular Tamagui components from \`tamagui\` or
|
|
308
|
+
\`@tamagui/core\`. Do not mix utility classes and Tamagui style props on the
|
|
309
|
+
same component; choose the import whose styling language that component uses.
|
|
310
|
+
|
|
311
|
+
### Required API follow-ups
|
|
312
|
+
|
|
313
|
+
- Transition values: replace arrays with \`{ preset: 'quick', opacity: 'lazy' }\`, rename the transition object's \`default\` to \`preset\`, and place physics under \`spring\`. Move \`animateOnly\` into \`transition.properties\`. Read the upgrade guide's transition section before converting driver-specific options.
|
|
314
|
+
- Groups and containers: \`group="card"\` enables \`group-hover/card:\` and other group states. Size queries require \`container="card"\` and use \`@sm/card:\`; a group alone no longer enables container measurement.
|
|
315
|
+
- Control sizes: Config v6 uses \`xs | sm | md | lg | xl\` (default \`md\`). Keep numeric token keys while retaining Config v5, then map control sizes when separately adopting v6. Shape and icon geometry still uses size tokens or numbers.
|
|
316
|
+
- Remove top-level \`createTamagui({ defaultProps })\`. Put default styles in \`styled()\` definitions and inherited non-style defaults in \`Component.Props\`.
|
|
317
|
+
- Toast: replace \`useToastController().show(title, { message })\` with \`toast(title, { description: message })\`. Import \`Toast\` and \`toast\` from \`tamagui/toast\`; mount \`Toast.Root\` and \`Toast.List\` with the desired parts once in the app. The old provider/controller API is removed.
|
|
318
|
+
- Replace \`ThemeableStack\` and \`SizableStack\` with \`YStack\` or \`XStack\` plus explicit styles; use \`elevation\` for elevation and border width/color for borders.
|
|
319
|
+
- Checked/selected states: Checkbox, Switch, Tabs and ToggleGroup read \`background-press\`; customize \`activeStyle\` to override it per instance. Audit the resulting active background against the previous app and customize its theme or skin where needed.
|
|
320
|
+
|
|
321
|
+
### 15. Verification
|
|
322
|
+
|
|
323
|
+
- Run \`npx tamagui check --strict\`.
|
|
324
|
+
- Run typecheck and build.
|
|
325
|
+
- Start the app and manually test screens using Sheet, Dialog, Popover, Select, FocusScope, icons, and ScrollView.
|
|
326
|
+
- Test Adapt breakpoints where popovers/selects/dialogs become sheets.
|
|
327
|
+
- Verify keyboard focus, Escape, outside click, scroll locking, and close animations.
|
|
328
|
+
- Inspect icon alignment next to text at each app size token.
|
|
329
|
+
- If the Tailwind frontend is used, compare web and native output for the classes used.
|
|
330
|
+
- Compare the same screens and resolved control dimensions with the baseline. Keeping Config v5 preserves the scales, but does not prove that changed component APIs preserve every layout.
|
|
331
|
+
- Report the final package version, retained config, manual fixes, runtime evidence, and deferred optional work. A validated V3 app on Config v5 is a completed migration.
|
|
332
|
+
|
|
333
|
+
### Optional follow-up: Config v6, only when separately requested
|
|
334
|
+
|
|
335
|
+
This appendix is not part of the intermediate V3 API checkpoint. Start a new
|
|
336
|
+
reviewable change after that checkpoint is validated. Record new visual
|
|
337
|
+
acceptance criteria before changing design values.
|
|
338
|
+
|
|
339
|
+
- New apps can start with \`defaultConfig\` from \`@tamagui/config/v6\`.
|
|
340
|
+
- For an existing app, inventory and compare resolved spacing, size, radius, font, icon, and media values. Map by resolved value when preserving appearance; the same token name can mean a different number in v6.
|
|
341
|
+
- Preserve breakpoint meaning: changing a max-width key to a min-width key can invert responsive behavior.
|
|
342
|
+
|
|
343
|
+
- Use \`createThemes\`, \`levels\`, scales, and the other recipe helpers from \`@tamagui/themes/builder\`.
|
|
344
|
+
- Remove \`componentThemes\`, \`templates\`, \`masks\`, \`childrenThemes\`, and \`grandChildrenThemes\`. Express hierarchy in the recipe tree, semantic values in scales, and exact one-theme overrides in \`values\`.
|
|
345
|
+
|
|
346
|
+
Rename the adaptive 12-step ramp approximately:
|
|
347
|
+
|
|
348
|
+
- \`color1\` -> \`color1\`
|
|
349
|
+
- \`color2\` -> \`color2\`
|
|
350
|
+
- \`color3\` -> \`color3\`
|
|
351
|
+
- \`color4\` -> \`color4\`
|
|
352
|
+
- \`color5\` -> \`color5\`
|
|
353
|
+
- \`color6\` and \`color7\` -> \`color6\`
|
|
354
|
+
- \`color8\` -> \`color7\`
|
|
355
|
+
- \`color9\` -> \`color8\`
|
|
356
|
+
- \`color10\` -> \`color9\`
|
|
357
|
+
- \`color11\` -> \`color10\`
|
|
358
|
+
- \`color12\` -> \`color11\`
|
|
359
|
+
|
|
360
|
+
The endpoints are exact; inspect contrast in the compressed middle. Replace
|
|
361
|
+
\`surface1\` with \`level2\`, \`surface2\` with \`level3\`, and \`surface3\`
|
|
362
|
+
or \`surface4\` with \`level4\`. Levels are relative and preserve a surrounding
|
|
363
|
+
color theme when nested.
|
|
364
|
+
|
|
365
|
+
Search the config and application together:
|
|
366
|
+
|
|
367
|
+
\`\`\`bash
|
|
368
|
+
rg "@tamagui/theme-builder|v5-builder|createV5Theme|componentThemes|grandChildrenThemes|surface[1-4]|color12"
|
|
369
|
+
\`\`\`
|
|
370
|
+
|
|
371
|
+
Validate the config change separately with light/dark screenshots, responsive
|
|
372
|
+
layouts, text and icon alignment, and every platform the app ships. Do not
|
|
373
|
+
accept visual drift merely because the codemod and typecheck are green.`
|
|
374
|
+
|
|
375
|
+
const v1ToV2Prompt = `## v1 -> v2 migration pass
|
|
376
|
+
|
|
377
|
+
Bring the app to the v2 baseline before applying v3 changes.
|
|
378
|
+
|
|
379
|
+
### Requirements
|
|
380
|
+
|
|
381
|
+
- React 19+
|
|
382
|
+
- React Native 0.81+ with New Architecture support
|
|
383
|
+
- TypeScript 5+
|
|
384
|
+
|
|
385
|
+
### Config
|
|
386
|
+
|
|
387
|
+
- Preserve the app's existing token, theme, font, and breakpoint values while reaching the v2 API baseline. Keep supported Config v5 imports or serialize the old generated config into app-owned values when an entry is no longer exported. Config v6 is a separate optional migration after the v3 checkpoint below.
|
|
388
|
+
- Import animations separately from \`@tamagui/config/animations-css\`, \`animations-rn\`, \`animations-reanimated\`, or \`animations-motion\`.
|
|
389
|
+
- Move root \`createTamagui\` settings into \`settings\`.
|
|
390
|
+
- Account for the defaults \`flexBasis: 0\` and \`position: static\`. Use \`styleCompat: 'legacy'\` or explicit props if needed.
|
|
391
|
+
- Rename media queries: \`$2xl\` -> \`$xxl\`, \`$2xs\` -> \`$xxs\`, and max queries to kebab-case such as \`$max-md\`.
|
|
392
|
+
- Preserve resolved colors and themes; defer v6 recipe conversion to the optional follow-up below.
|
|
393
|
+
|
|
394
|
+
### v1 prop and API changes
|
|
395
|
+
|
|
396
|
+
- \`animation\` -> \`transition\`.
|
|
397
|
+
- \`AnimationProp\` -> \`TransitionProp\`.
|
|
398
|
+
- \`tag\` -> \`render\`.
|
|
399
|
+
- \`Stack\` -> \`View\`.
|
|
400
|
+
- \`StackProps\` -> \`ViewProps\`.
|
|
401
|
+
- \`space\` and \`spaceDirection\` -> \`gap\`.
|
|
402
|
+
- \`themeInverse\` and \`<Theme inverse>\` -> \`theme="inverse"\` and \`<Theme name="inverse">\`.
|
|
403
|
+
- \`onHoverIn\` / \`onHoverOut\` -> \`onPointerEnter\` / \`onPointerLeave\` or mouse events.
|
|
404
|
+
- \`ellipse\` -> \`numberOfLines={1}\`.
|
|
405
|
+
- React Native accessibility props -> ARIA/web equivalents where applicable.
|
|
406
|
+
- React Native shadow props -> \`boxShadow\`.
|
|
407
|
+
|
|
408
|
+
### v1 component changes
|
|
409
|
+
|
|
410
|
+
- Input and Image prefer web-standard props such as \`type\`, \`inputMode\`, \`src\`, \`alt\`, and \`objectFit\`.
|
|
411
|
+
- Button and ListItem no longer take direct text style props. Style text through child components.
|
|
412
|
+
- Tabs uses \`Tabs.Tab\` instead of \`Tabs.Trigger\`; \`activationMode\` defaults to \`manual\`.
|
|
413
|
+
- Group requires \`Group.Item\`; remove old separator/space/scrollable auto-cloning props.
|
|
414
|
+
- Replace old \`Popover.Sheet\` subcomponents with standalone \`Sheet\` inside \`Adapt\`.
|
|
415
|
+
- Add native setup imports where needed: \`@tamagui/native/setup-teleport\`, \`setup-gesture-handler\`, \`setup-expo-ui-menu\` or \`setup-zeego\`, \`setup-burnt\`, and linear-gradient setup.
|
|
416
|
+
|
|
417
|
+
### v1 -> v2 verification
|
|
418
|
+
|
|
419
|
+
- Run the app before starting v3 changes.
|
|
420
|
+
- Verify layout affected by flex/position defaults.
|
|
421
|
+
- Verify forms, tabs, groups, portals, native sheets, and Input/Image behavior.
|
|
422
|
+
- Commit the v1 -> v2 migration separately if possible.`
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// the agent brief for setting tamagui up in a project that has never had it.
|
|
2
|
+
// `tamagui migrate --from v2` is the sibling for projects that already run v2.
|
|
3
|
+
//
|
|
4
|
+
// both are printed by the cli rather than kept only in docs so that whatever
|
|
5
|
+
// version a user installs describes itself, instead of an agent reading a docs
|
|
6
|
+
// page written against a different release.
|
|
7
|
+
|
|
8
|
+
import prompts from 'prompts'
|
|
9
|
+
|
|
10
|
+
export async function resolveStyleValueSyntax(
|
|
11
|
+
setting?: 'string' | 'object' | 'both'
|
|
12
|
+
): Promise<'string' | 'object' | 'both'> {
|
|
13
|
+
if (setting === 'string' || setting === 'object' || setting === 'both') {
|
|
14
|
+
return setting
|
|
15
|
+
}
|
|
16
|
+
if (!process.stdin.isTTY) {
|
|
17
|
+
return 'both'
|
|
18
|
+
}
|
|
19
|
+
const response = await prompts({
|
|
20
|
+
type: 'select',
|
|
21
|
+
name: 'syntax',
|
|
22
|
+
message: 'Which style value syntax would you like to document?',
|
|
23
|
+
choices: [
|
|
24
|
+
{ title: 'both - document both string and object syntax', value: 'both' },
|
|
25
|
+
{ title: 'string - e.g. bg="red hover:blue"', value: 'string' },
|
|
26
|
+
{ title: 'object - e.g. bg={{ default: "red", hover: "blue" }}', value: 'object' },
|
|
27
|
+
],
|
|
28
|
+
initial: 0,
|
|
29
|
+
})
|
|
30
|
+
return response.syntax || 'both'
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function setupPrompt(options?: any) {
|
|
34
|
+
const { generatePrompt } = require('./generate-prompt')
|
|
35
|
+
return await generatePrompt(options)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function printSetupPrompt(syntax?: 'string' | 'object' | 'both') {
|
|
39
|
+
if (syntax) {
|
|
40
|
+
process.stdout.write(getSetupPrompt(syntax))
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
if (!process.stdin.isTTY) {
|
|
44
|
+
process.stdout.write(getSetupPrompt('both'))
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
resolveStyleValueSyntax().then((chosen) => {
|
|
48
|
+
process.stdout.write(getSetupPrompt(chosen))
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function getSetupPrompt(syntax: 'string' | 'object' | 'both' = 'both') {
|
|
53
|
+
const styleExample =
|
|
54
|
+
syntax === 'string'
|
|
55
|
+
? '```tsx\n<View bg="background hover:background-hover" p="4 sm:6" />\n```'
|
|
56
|
+
: syntax === 'object'
|
|
57
|
+
? "```tsx\n<View bg={{ default: 'background', hover: 'background-hover' }} p={{ default: '4', sm: '6' }} />\n```"
|
|
58
|
+
: `\`\`\`tsx
|
|
59
|
+
// string form
|
|
60
|
+
<View bg="background hover:background-hover" p="4 sm:6" />
|
|
61
|
+
|
|
62
|
+
// object form
|
|
63
|
+
<View bg={{ default: 'background', hover: 'background-hover' }} p={{ default: '4', sm: '6' }} />
|
|
64
|
+
\`\`\``
|
|
65
|
+
|
|
66
|
+
return `You are adding Tamagui v3 to a project that does not use it yet.
|
|
67
|
+
|
|
68
|
+
Work like a careful coding agent:
|
|
69
|
+
|
|
70
|
+
- Read the project first: package manager, bundler, framework, TypeScript config,
|
|
71
|
+
and whether it targets web, native, or both. Every choice below depends on it.
|
|
72
|
+
- Make the smallest install that actually runs, then verify it before adding more.
|
|
73
|
+
- Do not restyle existing components as part of setup.
|
|
74
|
+
- Do not publish packages, rotate secrets, or change production infrastructure.
|
|
75
|
+
- Stop and report if a step cannot be completed rather than guessing around it.
|
|
76
|
+
|
|
77
|
+
## 1. Check the baseline
|
|
78
|
+
|
|
79
|
+
Tamagui v3 requires React 19+, TypeScript 5+, and, for native apps, React Native
|
|
80
|
+
0.81+ with the New Architecture enabled. Web-only apps have no React Native
|
|
81
|
+
version requirement. If the project is below any of these, say so and stop.
|
|
82
|
+
|
|
83
|
+
## 2. Install
|
|
84
|
+
|
|
85
|
+
Tamagui v3 is currently a beta on the \`beta\` dist-tag. Resolve it once and pin
|
|
86
|
+
every package to the same version, because a mixed install silently produces two
|
|
87
|
+
copies of the runtime and styles that do nothing.
|
|
88
|
+
|
|
89
|
+
\`\`\`bash
|
|
90
|
+
V=$(npm view tamagui@beta version)
|
|
91
|
+
npm i tamagui@$V @tamagui/config@$V
|
|
92
|
+
\`\`\`
|
|
93
|
+
|
|
94
|
+
\`tamagui\` is a superset of \`@tamagui/core\`. Install \`@tamagui/core\` alone
|
|
95
|
+
only for a styling-only install with no UI kit.
|
|
96
|
+
|
|
97
|
+
## 3. Create the config
|
|
98
|
+
|
|
99
|
+
\`\`\`tsx
|
|
100
|
+
// tamagui.config.ts
|
|
101
|
+
import { defaultConfig } from '@tamagui/config/v6'
|
|
102
|
+
import { createTamagui } from 'tamagui'
|
|
103
|
+
|
|
104
|
+
export const config = createTamagui(defaultConfig)
|
|
105
|
+
|
|
106
|
+
type AppConfig = typeof config
|
|
107
|
+
|
|
108
|
+
declare module 'tamagui' {
|
|
109
|
+
interface TamaguiCustomConfig extends AppConfig {}
|
|
110
|
+
}
|
|
111
|
+
\`\`\`
|
|
112
|
+
|
|
113
|
+
Pick an animation driver explicitly and import it from \`@tamagui/config\`:
|
|
114
|
+
\`animations-css\` (web), \`animations-rn\`, \`animations-reanimated\`, or
|
|
115
|
+
\`animations-motion\`. Do not install \`@tamagui/theme-builder\` or any v5 builder
|
|
116
|
+
package; they are not part of v3.
|
|
117
|
+
|
|
118
|
+
## 4. Wrap the app
|
|
119
|
+
|
|
120
|
+
\`\`\`tsx
|
|
121
|
+
import { TamaguiProvider, View } from 'tamagui'
|
|
122
|
+
import { config } from './tamagui.config'
|
|
123
|
+
|
|
124
|
+
export default function App() {
|
|
125
|
+
return (
|
|
126
|
+
<TamaguiProvider config={config} defaultTheme="light">
|
|
127
|
+
<View w={200} h={200} bg="background" />
|
|
128
|
+
</TamaguiProvider>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
\`\`\`
|
|
132
|
+
|
|
133
|
+
## 5. Wire the bundler
|
|
134
|
+
|
|
135
|
+
Add the adapter for the bundler this project actually uses, and no others:
|
|
136
|
+
|
|
137
|
+
- Vite: \`@tamagui/vite-plugin\`, or \`@tamagui/cli/vite\`
|
|
138
|
+
- Metro: \`@tamagui/metro-plugin\`, or \`@tamagui/cli/metro\`
|
|
139
|
+
- Next.js: \`@tamagui/next-plugin\`
|
|
140
|
+
- Turbopack: the \`tamagui build\` precompile step
|
|
141
|
+
|
|
142
|
+
There is no Webpack plugin in v3.
|
|
143
|
+
|
|
144
|
+
The compiler is an optimization, not a requirement. If wiring it is not
|
|
145
|
+
straightforward, skip it, note that you skipped it, and confirm the app runs
|
|
146
|
+
first.
|
|
147
|
+
|
|
148
|
+
## 6. Write styles the v3 way
|
|
149
|
+
|
|
150
|
+
This is the part most likely to be written as if it were v2. In v3, token and
|
|
151
|
+
theme names are bare, and conditions are flat clauses inside the value:
|
|
152
|
+
|
|
153
|
+
${styleExample}
|
|
154
|
+
|
|
155
|
+
- No \`$\` sigils: \`bg="background"\`, not \`bg="$background"\`.
|
|
156
|
+
- No condition objects: there is no \`hoverStyle={{ ... }}\` and no \`$sm={{ ... }}\`.
|
|
157
|
+
- Modifiers chain left to right and read as prefixes: \`hover:sm:small\`.
|
|
158
|
+
- Clauses work on variant props too, not just style props, so
|
|
159
|
+
\`size="lg sm:sm"\` selects a different variant value per condition.
|
|
160
|
+
- When two clauses both apply, the winner is decided by specificity, not by
|
|
161
|
+
source order: first by platform (\`ios:\` beats \`native:\` beats unprefixed),
|
|
162
|
+
then by how many conditions the clause carries, then by category
|
|
163
|
+
(media < container < theme < group < state). Writing a clause later in the
|
|
164
|
+
string does not make it win.
|
|
165
|
+
- A chain is capped at five distinct non-platform conditions.
|
|
166
|
+
|
|
167
|
+
## 7. Verify before reporting success
|
|
168
|
+
|
|
169
|
+
\`\`\`bash
|
|
170
|
+
npx tamagui check --strict
|
|
171
|
+
\`\`\`
|
|
172
|
+
|
|
173
|
+
\`tamagui check --strict\` reports version mismatches, duplicate installs, lockfile
|
|
174
|
+
problems, a missing config, and any v2 style syntax left in source. Then run the
|
|
175
|
+
project's own typecheck and build, and start the app and confirm a Tamagui
|
|
176
|
+
component renders with its styles applied. A passing typecheck is not sufficient:
|
|
177
|
+
single-token values are checked when \`settings.allowedStyleValues\` is enabled,
|
|
178
|
+
but conditional payloads also need the strict checker.
|
|
179
|
+
|
|
180
|
+
## 8. Give the agent the project's own vocabulary
|
|
181
|
+
|
|
182
|
+
Once the app runs, generate a description of this project's actual tokens,
|
|
183
|
+
themes, and components so later prompts do not guess at them:
|
|
184
|
+
|
|
185
|
+
\`\`\`bash
|
|
186
|
+
npx tamagui generate-prompt
|
|
187
|
+
\`\`\`
|
|
188
|
+
|
|
189
|
+
That writes \`tamagui-prompt.md\`. Keep it in the repo and regenerate it when the
|
|
190
|
+
config changes.
|
|
191
|
+
`
|
|
192
|
+
}
|