@ranimontagna/agent-toolkit 0.1.5 → 0.1.6
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 +42 -8
- package/package.json +1 -1
- package/skills/frontend/react/react-patterns/LICENSE +21 -0
- package/skills/frontend/react/react-patterns/NOTICE.md +11 -0
- package/skills/frontend/react/react-patterns/SKILL.md +341 -0
- package/skills/frontend/react/react-performance/LICENSE +21 -0
- package/skills/frontend/react/react-performance/NOTICE.md +11 -0
- package/skills/frontend/react/react-performance/SKILL.md +574 -0
- package/skills/frontend/react/react-testing/LICENSE +21 -0
- package/skills/frontend/react/react-testing/NOTICE.md +11 -0
- package/skills/frontend/react/react-testing/SKILL.md +423 -0
- package/skills/frontend/react-native/react-native-expert/LICENSE +21 -0
- package/skills/frontend/react-native/react-native-expert/NOTICE.md +11 -0
- package/skills/frontend/react-native/react-native-expert/SKILL.md +187 -0
- package/skills/frontend/react-native/react-native-expert/references/expo-router.md +187 -0
- package/skills/frontend/react-native/react-native-expert/references/list-optimization.md +204 -0
- package/skills/frontend/react-native/react-native-expert/references/platform-handling.md +188 -0
- package/skills/frontend/react-native/react-native-expert/references/project-structure.md +171 -0
- package/skills/frontend/react-native/react-native-expert/references/storage-hooks.md +173 -0
- package/skills/frontend/react-native/react-native-unistyles-v3/LICENSE +21 -0
- package/skills/frontend/react-native/react-native-unistyles-v3/NOTICE.md +11 -0
- package/skills/frontend/react-native/react-native-unistyles-v3/SKILL.md +159 -0
- package/skills/frontend/react-native/react-native-unistyles-v3/references/api-reference.md +495 -0
- package/skills/frontend/react-native/react-native-unistyles-v3/references/common-issues.md +389 -0
- package/skills/frontend/react-native/react-native-unistyles-v3/references/setup-guide.md +217 -0
- package/skills/frontend/react-native/react-native-unistyles-v3/references/styling-patterns.md +705 -0
- package/skills/frontend/react-native/react-native-unistyles-v3/references/third-party-integration.md +318 -0
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
# Common Issues
|
|
2
|
+
|
|
3
|
+
Curated from 150+ GitHub issues. Organized by category with symptoms, causes, and solutions.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Setup & Initialization
|
|
8
|
+
|
|
9
|
+
### "Unistyles was loaded but not configured" after hot reload
|
|
10
|
+
|
|
11
|
+
**Symptoms:** Error appears after fast refresh / hot reload, not on cold start.
|
|
12
|
+
**Cause:** `StyleSheet.configure()` runs in a module scope that doesn't re-execute on HMR.
|
|
13
|
+
**Solution:** Ensure `StyleSheet.configure()` is imported in your entry point file. For Expo Router, follow the [Expo Router integration steps](setup-guide.md#expo-router-integration).
|
|
14
|
+
**Ref:** [#1098](https://github.com/jpudysz/react-native-unistyles/issues/1098)
|
|
15
|
+
|
|
16
|
+
### "Unistyles not initialized correctly"
|
|
17
|
+
|
|
18
|
+
**Symptoms:** Crash on app start.
|
|
19
|
+
**Cause:** `StyleSheet.create()` is called before `StyleSheet.configure()`.
|
|
20
|
+
**Solution:** Move `StyleSheet.configure()` to your app's entry point, before any component imports that use `StyleSheet.create`.
|
|
21
|
+
**Ref:** [#1010](https://github.com/jpudysz/react-native-unistyles/issues/1010)
|
|
22
|
+
|
|
23
|
+
### StyleSheet.configure timing with Expo Router
|
|
24
|
+
|
|
25
|
+
**Symptoms:** Styles don't work or "not configured" error with Expo Router.
|
|
26
|
+
**Cause:** Expo Router resolves routes before your config runs.
|
|
27
|
+
**Solution:**
|
|
28
|
+
1. Set `"main": "index.ts"` in package.json
|
|
29
|
+
2. Create `index.ts` with:
|
|
30
|
+
```ts
|
|
31
|
+
import './unistyles' // configure first
|
|
32
|
+
import 'expo-router/entry'
|
|
33
|
+
```
|
|
34
|
+
3. For static rendering, also import config in `app/+html.tsx`
|
|
35
|
+
|
|
36
|
+
### "Property value expected type of number but got null" for hasAdaptiveThemes
|
|
37
|
+
|
|
38
|
+
**Symptoms:** Runtime error mentioning `hasAdaptiveThemes` property.
|
|
39
|
+
**Cause:** `adaptiveThemes` set to `true` without both `light` and `dark` themes registered.
|
|
40
|
+
**Solution:** Ensure themes object has keys named exactly `light` and `dark`:
|
|
41
|
+
```tsx
|
|
42
|
+
StyleSheet.configure({
|
|
43
|
+
themes: { light: lightTheme, dark: darkTheme },
|
|
44
|
+
settings: { adaptiveThemes: true }
|
|
45
|
+
})
|
|
46
|
+
```
|
|
47
|
+
**Ref:** [#1040](https://github.com/jpudysz/react-native-unistyles/issues/1040)
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 2. Style Spreading (Most Common Issue)
|
|
52
|
+
|
|
53
|
+
### "Style is not bound!" error
|
|
54
|
+
|
|
55
|
+
**Symptoms:** Runtime error "Style is not bound!" or styles not applying.
|
|
56
|
+
**Cause:** Spreading Unistyles styles with `{...styles.x}`. v3 styles are C++ proxy objects — spreading breaks the native binding.
|
|
57
|
+
**Solution:** ALWAYS use array syntax:
|
|
58
|
+
```tsx
|
|
59
|
+
// WRONG
|
|
60
|
+
<View style={{ ...styles.container, ...styles.extra }} />
|
|
61
|
+
<View style={{ ...styles.container, marginTop: 10 }} />
|
|
62
|
+
|
|
63
|
+
// CORRECT
|
|
64
|
+
<View style={[styles.container, styles.extra]} />
|
|
65
|
+
<View style={[styles.container, { marginTop: 10 }]} />
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Spreading in useAnimatedStyle callbacks
|
|
69
|
+
|
|
70
|
+
**Symptoms:** Animated styles don't update or crash.
|
|
71
|
+
**Cause:** Spreading Unistyles styles inside `useAnimatedStyle`.
|
|
72
|
+
**Solution:** Use array syntax when combining:
|
|
73
|
+
```tsx
|
|
74
|
+
// WRONG
|
|
75
|
+
const animStyle = useAnimatedStyle(() => ({ ...styles.box }))
|
|
76
|
+
|
|
77
|
+
// CORRECT
|
|
78
|
+
<Animated.View style={[styles.box, animStyle]} />
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 3. Babel Plugin Issues
|
|
84
|
+
|
|
85
|
+
### Re-exporting StyleSheet from barrel files
|
|
86
|
+
|
|
87
|
+
**Symptoms:** Styles not reactive; theme changes have no effect.
|
|
88
|
+
**Cause:** The Babel plugin detects `StyleSheet.create` by checking the import source is `react-native-unistyles`. Re-exporting through a barrel file (e.g., `export { StyleSheet } from 'react-native-unistyles'` in `utils/index.ts`) breaks detection.
|
|
89
|
+
**Solution:** Always import directly:
|
|
90
|
+
```tsx
|
|
91
|
+
// WRONG
|
|
92
|
+
import { StyleSheet } from '@/utils' // barrel re-export
|
|
93
|
+
|
|
94
|
+
// CORRECT
|
|
95
|
+
import { StyleSheet } from 'react-native-unistyles'
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Plugin interferes with other .create() calls
|
|
99
|
+
|
|
100
|
+
**Symptoms:** Other libraries' `.create()` calls break (e.g., Zustand, custom factories).
|
|
101
|
+
**Cause:** The Babel plugin processes any `StyleSheet.create()` it finds.
|
|
102
|
+
**Solution:** The plugin only processes `StyleSheet.create()` when `StyleSheet` is imported from `react-native-unistyles`. If you have a different `StyleSheet` variable, rename it to avoid collision.
|
|
103
|
+
**Ref:** [#993](https://github.com/jpudysz/react-native-unistyles/issues/993)
|
|
104
|
+
|
|
105
|
+
### Wrong root directory
|
|
106
|
+
|
|
107
|
+
**Symptoms:** Styles not reactive; Babel plugin appears to do nothing.
|
|
108
|
+
**Cause:** The `root` option in Babel config resolves to the project root or an incorrect directory.
|
|
109
|
+
**Solution:** `root` must point to your **source code directory**, not the project root:
|
|
110
|
+
```js
|
|
111
|
+
// WRONG — root resolves to project root
|
|
112
|
+
['react-native-unistyles/plugin', { root: '.' }]
|
|
113
|
+
['react-native-unistyles/plugin', { root: '' }]
|
|
114
|
+
|
|
115
|
+
// CORRECT
|
|
116
|
+
['react-native-unistyles/plugin', { root: 'src' }]
|
|
117
|
+
['react-native-unistyles/plugin', { root: 'app' }] // for Expo Router
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Files outside root not processed
|
|
121
|
+
|
|
122
|
+
**Symptoms:** Shared package styles not reactive.
|
|
123
|
+
**Cause:** Only files inside `root` are processed by default.
|
|
124
|
+
**Solution:** Add `autoProcessPaths` for additional directories:
|
|
125
|
+
```js
|
|
126
|
+
['react-native-unistyles/plugin', {
|
|
127
|
+
root: 'src',
|
|
128
|
+
autoProcessPaths: ['../packages/shared/src']
|
|
129
|
+
}]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 4. Theme Updates Not Propagating
|
|
135
|
+
|
|
136
|
+
### Nested Text components + Reanimated conflict
|
|
137
|
+
|
|
138
|
+
**Symptoms:** Nested `<Text>` components don't update color when theme changes while using Reanimated.
|
|
139
|
+
**Cause:** Reanimated's animated components can interfere with Unistyles' ShadowTree updates on nested text.
|
|
140
|
+
**Solution:** Ensure nested Text components have explicit style bindings. If using Reanimated, avoid wrapping Text in Animated containers for theme-dependent colors.
|
|
141
|
+
**Ref:** [#1045](https://github.com/jpudysz/react-native-unistyles/issues/1045)
|
|
142
|
+
|
|
143
|
+
### ScopedTheme not applied to dynamic children
|
|
144
|
+
|
|
145
|
+
**Symptoms:** Items rendered inside `<ScopedTheme>` after mount don't pick up the scoped theme.
|
|
146
|
+
**Cause:** ScopedTheme applies at mount time. Dynamically added children (e.g., FlatList items) may not inherit.
|
|
147
|
+
**Status:** WONTFIX — by design.
|
|
148
|
+
**Workaround:** Wrap each dynamically rendered item in its own `<ScopedTheme>`:
|
|
149
|
+
```tsx
|
|
150
|
+
<ScopedTheme name="dark">
|
|
151
|
+
{items.map(item => (
|
|
152
|
+
<ScopedTheme key={item.id} name="dark">
|
|
153
|
+
<ItemCard item={item} />
|
|
154
|
+
</ScopedTheme>
|
|
155
|
+
))}
|
|
156
|
+
</ScopedTheme>
|
|
157
|
+
```
|
|
158
|
+
**Ref:** [#955](https://github.com/jpudysz/react-native-unistyles/issues/955)
|
|
159
|
+
|
|
160
|
+
### Reanimated CSS transitions stale colors
|
|
161
|
+
|
|
162
|
+
**Symptoms:** After theme switch, CSS transition colors show the old theme's value.
|
|
163
|
+
**Cause:** Reanimated CSS transitions cache the initial color value.
|
|
164
|
+
**Solution:** Use `key={rt.themeName}` to force re-mount on theme change:
|
|
165
|
+
```tsx
|
|
166
|
+
const { rt } = useUnistyles()
|
|
167
|
+
<Animated.View key={rt.themeName} style={styles.card} />
|
|
168
|
+
```
|
|
169
|
+
**Ref:** [#1007](https://github.com/jpudysz/react-native-unistyles/issues/1007)
|
|
170
|
+
|
|
171
|
+
### withUnistyles not always updating
|
|
172
|
+
|
|
173
|
+
**Symptoms:** Wrapped component doesn't re-render when theme changes.
|
|
174
|
+
**Cause:** The wrapped component may have internal memoization preventing updates.
|
|
175
|
+
**Solution:** Pass `key` prop tied to theme:
|
|
176
|
+
```tsx
|
|
177
|
+
const UniButton = withUnistyles(Button, (theme) => ({
|
|
178
|
+
color: theme.colors.primary,
|
|
179
|
+
key: theme.colors.primary, // force update
|
|
180
|
+
}))
|
|
181
|
+
```
|
|
182
|
+
**Ref:** [#980](https://github.com/jpudysz/react-native-unistyles/issues/980)
|
|
183
|
+
|
|
184
|
+
### Theme reverts after app background on Android
|
|
185
|
+
|
|
186
|
+
**Symptoms:** Theme resets to initial theme when app returns from background.
|
|
187
|
+
**Cause:** Android activity recreation can re-trigger initialization.
|
|
188
|
+
**Solution:** Use `adaptiveThemes: true` if following OS theme, or persist theme choice and use `initialTheme: () => getStoredTheme()`.
|
|
189
|
+
**Ref:** [#963](https://github.com/jpudysz/react-native-unistyles/issues/963)
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 5. Android-Specific
|
|
194
|
+
|
|
195
|
+
### FlatList crash on orientation change
|
|
196
|
+
|
|
197
|
+
**Symptoms:** App crashes when rotating device while FlatList is visible.
|
|
198
|
+
**Cause:** React Native core FlatList issue, not Unistyles-specific.
|
|
199
|
+
**Solution:** Use FlashList or Legend List instead of FlatList.
|
|
200
|
+
**Ref:** [#803](https://github.com/jpudysz/react-native-unistyles/issues/803)
|
|
201
|
+
|
|
202
|
+
### Keyboard inset lag with react-native-keyboard-controller
|
|
203
|
+
|
|
204
|
+
**Symptoms:** `rt.insets.ime` lags behind actual keyboard position.
|
|
205
|
+
**Cause:** Conflict between Unistyles' IME tracking and react-native-keyboard-controller.
|
|
206
|
+
**Solution:** Use only one keyboard tracking solution. Prefer `rt.insets.ime` and remove `react-native-keyboard-controller`, or vice versa.
|
|
207
|
+
**Ref:** [#1065](https://github.com/jpudysz/react-native-unistyles/issues/1065)
|
|
208
|
+
|
|
209
|
+
### CMake build failures
|
|
210
|
+
|
|
211
|
+
**Symptoms:** Build fails with CMake errors on Android.
|
|
212
|
+
**Cause:** Various CMake configuration issues, often related to NDK version or build tools.
|
|
213
|
+
**Solution:** Ensure you're using a compatible NDK version. Clean build:
|
|
214
|
+
```bash
|
|
215
|
+
cd android && ./gradlew clean && cd ..
|
|
216
|
+
npx react-native run-android
|
|
217
|
+
```
|
|
218
|
+
**Ref:** [#1058](https://github.com/jpudysz/react-native-unistyles/issues/1058), [#889](https://github.com/jpudysz/react-native-unistyles/issues/889), [#1013](https://github.com/jpudysz/react-native-unistyles/issues/1013)
|
|
219
|
+
|
|
220
|
+
### Screen orientation not updating runtime values
|
|
221
|
+
|
|
222
|
+
**Symptoms:** `rt.screen.width` / `rt.screen.height` don't update on rotation.
|
|
223
|
+
**Cause:** Missing orientation listener setup or Android activity configuration.
|
|
224
|
+
**Solution:** Ensure your AndroidManifest.xml allows orientation changes:
|
|
225
|
+
```xml
|
|
226
|
+
<activity android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode" />
|
|
227
|
+
```
|
|
228
|
+
**Ref:** [#1033](https://github.com/jpudysz/react-native-unistyles/issues/1033)
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## 6. Web-Specific
|
|
233
|
+
|
|
234
|
+
### SSR hydration mismatches
|
|
235
|
+
|
|
236
|
+
**Symptoms:** React hydration warnings on page load with SSR.
|
|
237
|
+
**Cause:** Server-rendered styles don't match client-side computed styles.
|
|
238
|
+
**Solution:** Use the SSR utilities:
|
|
239
|
+
```tsx
|
|
240
|
+
// Server: inject styles
|
|
241
|
+
const styles = useServerUnistyles() // or getServerUnistyles()
|
|
242
|
+
|
|
243
|
+
// Client: hydrate
|
|
244
|
+
hydrateServerUnistyles()
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Safari 16.3 and below not supported
|
|
248
|
+
|
|
249
|
+
**Symptoms:** Styles broken or app crashes on older Safari.
|
|
250
|
+
**Cause:** Unistyles v3 web implementation uses features not available in Safari < 16.4.
|
|
251
|
+
**Solution:** Require Safari 16.4+ or provide a fallback.
|
|
252
|
+
**Ref:** [#1073](https://github.com/jpudysz/react-native-unistyles/issues/1073)
|
|
253
|
+
|
|
254
|
+
### Styles not working on Reanimated Animated.View on web
|
|
255
|
+
|
|
256
|
+
**Symptoms:** Animated.View doesn't receive Unistyles styles on web platform.
|
|
257
|
+
**Cause:** Reanimated's web implementation may not forward the style processing correctly.
|
|
258
|
+
**Solution:** Use `getWebProps` or apply styles differently on web.
|
|
259
|
+
**Ref:** [#1014](https://github.com/jpudysz/react-native-unistyles/issues/1014)
|
|
260
|
+
|
|
261
|
+
### Gap polyfill incorrect margins on SmartTV
|
|
262
|
+
|
|
263
|
+
**Symptoms:** `gap` property produces wrong spacing on SmartTV web browsers.
|
|
264
|
+
**Cause:** Polyfill for `gap` uses margins which behave differently on some TV browsers.
|
|
265
|
+
**Solution:** Use explicit margin/padding instead of `gap` for TV targets.
|
|
266
|
+
**Ref:** [#1091](https://github.com/jpudysz/react-native-unistyles/issues/1091)
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## 7. TypeScript Issues
|
|
271
|
+
|
|
272
|
+
### boxShadow array in variants incorrect return type
|
|
273
|
+
|
|
274
|
+
**Symptoms:** TypeScript error when using `boxShadow` array inside variant styles.
|
|
275
|
+
**Cause:** Type inference doesn't correctly handle arrays inside variant branches.
|
|
276
|
+
**Workaround:** Cast with `as any` or extract the shadow to a const:
|
|
277
|
+
```tsx
|
|
278
|
+
const shadow = [{ offsetX: 0, offsetY: 2, blurRadius: 4, color: 'rgba(0,0,0,0.1)' }]
|
|
279
|
+
|
|
280
|
+
variants: {
|
|
281
|
+
elevated: {
|
|
282
|
+
true: { boxShadow: shadow as any },
|
|
283
|
+
},
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
**Ref:** [#1047](https://github.com/jpudysz/react-native-unistyles/issues/1047)
|
|
287
|
+
|
|
288
|
+
### withUnistyles inference failures
|
|
289
|
+
|
|
290
|
+
**Symptoms:** TypeScript can't infer prop types when using `withUnistyles`.
|
|
291
|
+
**Cause:** Complex generic inference in the HOC type.
|
|
292
|
+
**Workaround:** Explicitly type the component:
|
|
293
|
+
```tsx
|
|
294
|
+
const UniButton = withUnistyles<typeof Button, { color: string }>(
|
|
295
|
+
Button,
|
|
296
|
+
(theme) => ({ color: theme.colors.primary })
|
|
297
|
+
)
|
|
298
|
+
```
|
|
299
|
+
**Ref:** [#1008](https://github.com/jpudysz/react-native-unistyles/issues/1008)
|
|
300
|
+
|
|
301
|
+
### Variant categories with different shapes
|
|
302
|
+
|
|
303
|
+
**Symptoms:** TypeScript errors when variant categories have different style properties.
|
|
304
|
+
**Cause:** TypeScript tries to unify all variant branch types.
|
|
305
|
+
**Workaround:** Ensure all branches in a variant category have compatible types, or use type assertions.
|
|
306
|
+
**Ref:** [#1052](https://github.com/jpudysz/react-native-unistyles/issues/1052)
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## 8. React Compiler
|
|
311
|
+
|
|
312
|
+
### useVariants breaks with panicThreshold: 'all_errors'
|
|
313
|
+
|
|
314
|
+
**Symptoms:** Build error or runtime crash when using `styles.useVariants()` with React Compiler `panicThreshold: 'all_errors'`.
|
|
315
|
+
**Cause:** React Compiler can't analyze the `useVariants` call pattern.
|
|
316
|
+
**Status:** Known issue, planned fix in v4.
|
|
317
|
+
**Workaround:** Use `panicThreshold: 'none'` (default) or `'critical_errors'`.
|
|
318
|
+
**Ref:** [#1002](https://github.com/jpudysz/react-native-unistyles/issues/1002)
|
|
319
|
+
|
|
320
|
+
### Plugin ordering
|
|
321
|
+
|
|
322
|
+
**Symptoms:** Styles not reactive, build errors.
|
|
323
|
+
**Cause:** React Compiler runs before Unistyles plugin.
|
|
324
|
+
**Solution:** Unistyles plugin MUST come BEFORE React Compiler in babel.config.js:
|
|
325
|
+
```js
|
|
326
|
+
plugins: [
|
|
327
|
+
['react-native-unistyles/plugin', { root: 'src' }], // FIRST
|
|
328
|
+
'babel-plugin-react-compiler', // SECOND
|
|
329
|
+
]
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## 9. Performance
|
|
335
|
+
|
|
336
|
+
### useUnistyles causes re-renders
|
|
337
|
+
|
|
338
|
+
**Symptoms:** Excessive re-renders, especially on theme/orientation changes.
|
|
339
|
+
**Cause:** `useUnistyles()` subscribes to theme and runtime changes, triggering re-renders.
|
|
340
|
+
**Solution:** Prefer `StyleSheet.create(theme => ...)` which uses zero-re-render C++ updates. Reserve `useUnistyles()` for cases where you need theme/runtime in JS logic.
|
|
341
|
+
|
|
342
|
+
### Variant memory in long lists
|
|
343
|
+
|
|
344
|
+
**Symptoms:** High memory usage or slow performance when using variants in long list items.
|
|
345
|
+
**Cause:** Each list item with `useVariants()` maintains its own variant state.
|
|
346
|
+
**Solution:** Use dynamic functions instead of variants for list items:
|
|
347
|
+
```tsx
|
|
348
|
+
// Instead of variants:
|
|
349
|
+
const styles = StyleSheet.create(theme => ({
|
|
350
|
+
item: (isActive: boolean) => ({
|
|
351
|
+
backgroundColor: isActive ? theme.colors.active : theme.colors.surface,
|
|
352
|
+
}),
|
|
353
|
+
}))
|
|
354
|
+
|
|
355
|
+
// Usage in list item:
|
|
356
|
+
<View style={styles.item(isActive)} />
|
|
357
|
+
```
|
|
358
|
+
**Ref:** [#1034](https://github.com/jpudysz/react-native-unistyles/issues/1034)
|
|
359
|
+
|
|
360
|
+
### Tab navigation slow theme change
|
|
361
|
+
|
|
362
|
+
**Symptoms:** Theme change takes noticeable time with many tab screens.
|
|
363
|
+
**Cause:** Many mounted stylesheets updating simultaneously.
|
|
364
|
+
**Solution:** Use `adaptiveThemes` for smooth OS-level transitions, or batch theme updates.
|
|
365
|
+
**Ref:** [#1107](https://github.com/jpudysz/react-native-unistyles/issues/1107)
|
|
366
|
+
|
|
367
|
+
---
|
|
368
|
+
|
|
369
|
+
## 10. Third-Party Library Conflicts
|
|
370
|
+
|
|
371
|
+
### Pressable from react-native-gesture-handler stale theme
|
|
372
|
+
|
|
373
|
+
**Symptoms:** `Pressable` from `react-native-gesture-handler` doesn't update on theme change.
|
|
374
|
+
**Cause:** RNGH's Pressable doesn't go through the standard React Native style processing that Unistyles hooks into.
|
|
375
|
+
**Solution:** Use React Native's built-in `Pressable` or wrap RNGH's Pressable with `withUnistyles`:
|
|
376
|
+
```tsx
|
|
377
|
+
import { Pressable as GHPressable } from 'react-native-gesture-handler'
|
|
378
|
+
import { withUnistyles } from 'react-native-unistyles'
|
|
379
|
+
|
|
380
|
+
const Pressable = withUnistyles(GHPressable)
|
|
381
|
+
```
|
|
382
|
+
**Ref:** [#1109](https://github.com/jpudysz/react-native-unistyles/issues/1109)
|
|
383
|
+
|
|
384
|
+
### withUnistyles wraps elements on RN Web breaking SVG composition
|
|
385
|
+
|
|
386
|
+
**Symptoms:** SVG elements break when parent is wrapped with `withUnistyles` on web.
|
|
387
|
+
**Cause:** `withUnistyles` wraps the component in an additional View on web, breaking SVG's direct parent-child relationship.
|
|
388
|
+
**Solution:** Use `useUnistyles()` hook instead for SVG containers, or apply styles directly.
|
|
389
|
+
**Ref:** [#1087](https://github.com/jpudysz/react-native-unistyles/issues/1087)
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Setup Guide
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install react-native-unistyles react-native-nitro-modules
|
|
7
|
+
# or
|
|
8
|
+
yarn add react-native-unistyles react-native-nitro-modules
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Then rebuild your native project:
|
|
12
|
+
```bash
|
|
13
|
+
npx pod-install # iOS
|
|
14
|
+
npx react-native run-android # Android
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Babel Plugin Configuration
|
|
18
|
+
|
|
19
|
+
The Babel plugin is **mandatory**. It transforms `StyleSheet.create` calls at build time to enable zero-re-render reactivity.
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
// babel.config.js
|
|
23
|
+
module.exports = {
|
|
24
|
+
presets: ['module:@react-native/babel-preset'],
|
|
25
|
+
plugins: [
|
|
26
|
+
['react-native-unistyles/plugin', {
|
|
27
|
+
root: 'src' // REQUIRED: directory containing your app source code
|
|
28
|
+
}]
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Plugin options
|
|
34
|
+
|
|
35
|
+
| Option | Type | Description |
|
|
36
|
+
|--------|------|-------------|
|
|
37
|
+
| `root` | `string` | **Required.** Path to your source code root (relative to project root). Only files in this directory are processed. Must NOT resolve to the project root itself. |
|
|
38
|
+
| `autoProcessPaths` | `string[]` | Additional directories outside `root` to process (e.g., shared packages in a monorepo). |
|
|
39
|
+
| `autoProcessImports` | `string[]` | Additional package names whose imports trigger processing (e.g., `['@myorg/ui']`). |
|
|
40
|
+
| `autoRemapImports` | `Record<string, Record<string, string>>` | Map exotic component imports to Unistyles component factories. |
|
|
41
|
+
| `debug` | `boolean` | Enable debug logging to see which files are processed. Default: `false`. |
|
|
42
|
+
|
|
43
|
+
### Example: Monorepo with shared packages
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
// babel.config.js
|
|
47
|
+
module.exports = {
|
|
48
|
+
plugins: [
|
|
49
|
+
['react-native-unistyles/plugin', {
|
|
50
|
+
root: 'src',
|
|
51
|
+
autoProcessPaths: ['../shared-ui/src'],
|
|
52
|
+
autoProcessImports: ['@myorg/shared-ui']
|
|
53
|
+
}]
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### React Compiler ordering
|
|
59
|
+
|
|
60
|
+
If using React Compiler, the Unistyles plugin **MUST come BEFORE** React Compiler:
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
// babel.config.js
|
|
64
|
+
module.exports = {
|
|
65
|
+
plugins: [
|
|
66
|
+
['react-native-unistyles/plugin', { root: 'src' }], // FIRST
|
|
67
|
+
'babel-plugin-react-compiler', // SECOND
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## StyleSheet.configure
|
|
73
|
+
|
|
74
|
+
Call **once** before any component renders. Typically in your app entry point file.
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
import { StyleSheet } from 'react-native-unistyles'
|
|
78
|
+
import { lightTheme, darkTheme } from './themes'
|
|
79
|
+
import { breakpoints } from './breakpoints'
|
|
80
|
+
|
|
81
|
+
StyleSheet.configure({
|
|
82
|
+
themes: {
|
|
83
|
+
light: lightTheme,
|
|
84
|
+
dark: darkTheme,
|
|
85
|
+
},
|
|
86
|
+
breakpoints: {
|
|
87
|
+
xs: 0, // first breakpoint MUST start at 0
|
|
88
|
+
sm: 576,
|
|
89
|
+
md: 768,
|
|
90
|
+
lg: 992,
|
|
91
|
+
xl: 1200,
|
|
92
|
+
},
|
|
93
|
+
settings: {
|
|
94
|
+
initialTheme: 'light',
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Settings options
|
|
100
|
+
|
|
101
|
+
| Setting | Type | Description |
|
|
102
|
+
|---------|------|-------------|
|
|
103
|
+
| `initialTheme` | `string \| () => string` | Theme to use on app start. Can be a function for lazy evaluation (e.g., reading from storage). Mutually exclusive with `adaptiveThemes`. |
|
|
104
|
+
| `adaptiveThemes` | `boolean` | Auto-switch between `light` and `dark` themes based on OS color scheme. Requires themes named exactly `light` and `dark`. Mutually exclusive with `initialTheme`. |
|
|
105
|
+
| `CSSVars` | `boolean` | Use CSS custom properties for theme values on web. Enables instant theme switching without style recalculation. Default: `false`. |
|
|
106
|
+
| `nativeBreakpointsMode` | `'pixels' \| 'points'` | Whether breakpoint values are in physical pixels or logical points. Default: device-dependent. |
|
|
107
|
+
|
|
108
|
+
### Minimal configuration (no themes, no breakpoints)
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
StyleSheet.configure({})
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Even without themes/breakpoints, `StyleSheet.configure()` must be called to initialize the C++ runtime.
|
|
115
|
+
|
|
116
|
+
## TypeScript Declarations
|
|
117
|
+
|
|
118
|
+
Augment the Unistyles module to get type-safe themes and breakpoints:
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
// unistyles.ts (or wherever you call StyleSheet.configure)
|
|
122
|
+
import { StyleSheet } from 'react-native-unistyles'
|
|
123
|
+
import { lightTheme } from './themes'
|
|
124
|
+
import { breakpoints } from './breakpoints'
|
|
125
|
+
|
|
126
|
+
type AppThemes = {
|
|
127
|
+
light: typeof lightTheme
|
|
128
|
+
dark: typeof lightTheme // same shape as light
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
type AppBreakpoints = typeof breakpoints
|
|
132
|
+
|
|
133
|
+
declare module 'react-native-unistyles' {
|
|
134
|
+
export interface UnistylesThemes extends AppThemes {}
|
|
135
|
+
export interface UnistylesBreakpoints extends AppBreakpoints {}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
StyleSheet.configure({
|
|
139
|
+
themes: { light: lightTheme, dark: darkTheme },
|
|
140
|
+
breakpoints,
|
|
141
|
+
})
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
This enables:
|
|
145
|
+
- Auto-completion for `theme.colors.*`, `theme.spacing.*`, etc.
|
|
146
|
+
- Type-safe breakpoint names in styles and `mq`
|
|
147
|
+
- Type-safe theme names in `UnistylesRuntime.setTheme()`
|
|
148
|
+
|
|
149
|
+
## Expo Router Integration
|
|
150
|
+
|
|
151
|
+
Expo Router resolves routes before Unistyles can initialize. Extra steps are needed:
|
|
152
|
+
|
|
153
|
+
### 1. Change the main entry point
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
// package.json
|
|
157
|
+
{ "main": "index.ts" }
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### 2. Create index.ts
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
// index.ts — import config BEFORE the router
|
|
164
|
+
import './unistyles' // your StyleSheet.configure() file
|
|
165
|
+
import 'expo-router/entry'
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 3. For static rendering (Expo SDK 52+)
|
|
169
|
+
|
|
170
|
+
Import your Unistyles config in `app/+html.tsx`:
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
// app/+html.tsx
|
|
174
|
+
import '../unistyles' // ensures Unistyles initializes for each static page
|
|
175
|
+
|
|
176
|
+
import { ScrollViewStyleReset } from 'expo-router/html'
|
|
177
|
+
import { type PropsWithChildren } from 'react'
|
|
178
|
+
|
|
179
|
+
export default function Root({ children }: PropsWithChildren) {
|
|
180
|
+
return (
|
|
181
|
+
<html lang="en">
|
|
182
|
+
<head>
|
|
183
|
+
<meta charSet="utf-8" />
|
|
184
|
+
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
|
185
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
|
186
|
+
<ScrollViewStyleReset />
|
|
187
|
+
</head>
|
|
188
|
+
<body>{children}</body>
|
|
189
|
+
</html>
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Testing / Mocks Setup
|
|
195
|
+
|
|
196
|
+
The Babel plugin auto-disables in test environments (`NODE_ENV=test`). Import the mocks file in your Jest setup:
|
|
197
|
+
|
|
198
|
+
```js
|
|
199
|
+
// jest.setup.js
|
|
200
|
+
require('react-native-unistyles/mocks')
|
|
201
|
+
require('./unistyles') // your StyleSheet.configure() call — provides theme data to mocks
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
```js
|
|
205
|
+
// jest.config.js
|
|
206
|
+
module.exports = {
|
|
207
|
+
setupFiles: ['./jest.setup.js'],
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The mock provides:
|
|
212
|
+
- `StyleSheet.create` that resolves theme functions using the first registered theme
|
|
213
|
+
- `StyleSheet.configure` that stores themes/breakpoints
|
|
214
|
+
- `useUnistyles()` returning `{ theme, rt }` with mock runtime values
|
|
215
|
+
- `withUnistyles` that applies mapper function
|
|
216
|
+
- `mq`, `Display`, `Hide`, `ScopedTheme` as no-ops
|
|
217
|
+
- `useAnimatedTheme` and `useAnimatedVariantColor` mocks (from `react-native-unistyles/reanimated`)
|