react-native-terra-ui 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/lib/module/components/chip/Chip.js +97 -41
  3. package/lib/module/components/chip/Chip.js.map +1 -1
  4. package/lib/module/components/chip/utils.js +3 -1
  5. package/lib/module/components/chip/utils.js.map +1 -1
  6. package/lib/module/components/header/variants/LargeTitleHeader/index.js +50 -16
  7. package/lib/module/components/header/variants/LargeTitleHeader/index.js.map +1 -1
  8. package/lib/module/components/screen/ScreenFlashList.js +32 -26
  9. package/lib/module/components/screen/ScreenFlashList.js.map +1 -1
  10. package/lib/module/components/screen/ScreenFlatList.js +37 -31
  11. package/lib/module/components/screen/ScreenFlatList.js.map +1 -1
  12. package/lib/module/components/screen/ScreenScrollView.js +24 -18
  13. package/lib/module/components/screen/ScreenScrollView.js.map +1 -1
  14. package/lib/module/components/text/Text.js +2 -0
  15. package/lib/module/components/text/Text.js.map +1 -1
  16. package/lib/module/context/ThemeProvider.js +15 -0
  17. package/lib/module/context/ThemeProvider.js.map +1 -1
  18. package/lib/module/context/index.js +1 -1
  19. package/lib/module/context/index.js.map +1 -1
  20. package/lib/module/theme/breakpoints.js +29 -0
  21. package/lib/module/theme/breakpoints.js.map +1 -0
  22. package/lib/module/theme/index.js +4 -0
  23. package/lib/module/theme/index.js.map +1 -1
  24. package/lib/module/theme/registry.js +3 -1
  25. package/lib/module/theme/registry.js.map +1 -1
  26. package/lib/module/theme/screen-margin.js +17 -0
  27. package/lib/module/theme/screen-margin.js.map +1 -0
  28. package/lib/module/theme/tokens/dark.js +3 -3
  29. package/lib/module/theme/tokens/dark.js.map +1 -1
  30. package/lib/module/theme/tokens/primitives.js +12 -2
  31. package/lib/module/theme/tokens/primitives.js.map +1 -1
  32. package/lib/typescript/src/components/chip/Chip.d.ts.map +1 -1
  33. package/lib/typescript/src/components/chip/utils.d.ts.map +1 -1
  34. package/lib/typescript/src/components/header/variants/LargeTitleHeader/index.d.ts +9 -3
  35. package/lib/typescript/src/components/header/variants/LargeTitleHeader/index.d.ts.map +1 -1
  36. package/lib/typescript/src/components/screen/ScreenFlashList.d.ts.map +1 -1
  37. package/lib/typescript/src/components/screen/ScreenFlatList.d.ts.map +1 -1
  38. package/lib/typescript/src/components/screen/ScreenScrollView.d.ts.map +1 -1
  39. package/lib/typescript/src/components/text/Text.d.ts +1 -0
  40. package/lib/typescript/src/components/text/Text.d.ts.map +1 -1
  41. package/lib/typescript/src/context/ThemeProvider.d.ts +8 -0
  42. package/lib/typescript/src/context/ThemeProvider.d.ts.map +1 -1
  43. package/lib/typescript/src/context/index.d.ts +1 -1
  44. package/lib/typescript/src/context/index.d.ts.map +1 -1
  45. package/lib/typescript/src/theme/breakpoints.d.ts +32 -0
  46. package/lib/typescript/src/theme/breakpoints.d.ts.map +1 -0
  47. package/lib/typescript/src/theme/index.d.ts +4 -0
  48. package/lib/typescript/src/theme/index.d.ts.map +1 -1
  49. package/lib/typescript/src/theme/registry.d.ts.map +1 -1
  50. package/lib/typescript/src/theme/screen-margin.d.ts +15 -0
  51. package/lib/typescript/src/theme/screen-margin.d.ts.map +1 -0
  52. package/lib/typescript/src/theme/tokens/primitives.d.ts +10 -2
  53. package/lib/typescript/src/theme/tokens/primitives.d.ts.map +1 -1
  54. package/lib/typescript/src/theme/types.d.ts +9 -3
  55. package/lib/typescript/src/theme/types.d.ts.map +1 -1
  56. package/package.json +1 -2
  57. package/src/components/chip/Chip.tsx +94 -48
  58. package/src/components/chip/utils.ts +8 -1
  59. package/src/components/header/variants/LargeTitleHeader/index.tsx +56 -15
  60. package/src/components/screen/ScreenFlashList.tsx +37 -30
  61. package/src/components/screen/ScreenFlatList.tsx +41 -34
  62. package/src/components/screen/ScreenScrollView.tsx +24 -18
  63. package/src/components/text/Text.tsx +3 -0
  64. package/src/context/ThemeProvider.tsx +15 -0
  65. package/src/context/index.ts +1 -1
  66. package/src/theme/breakpoints.ts +41 -0
  67. package/src/theme/index.ts +5 -0
  68. package/src/theme/registry.ts +2 -1
  69. package/src/theme/screen-margin.ts +26 -0
  70. package/src/theme/tokens/dark.ts +3 -3
  71. package/src/theme/tokens/primitives.ts +12 -2
  72. package/src/theme/types.ts +12 -2
  73. package/skills/terra-ui/SKILL.md +0 -193
  74. package/skills/terra-ui/references/recipes.md +0 -198
  75. package/skills/terra-ui/references/troubleshooting.md +0 -112
@@ -1,198 +0,0 @@
1
- # Recipes
2
-
3
- Read the component's types before adapting these — the props are on disk under
4
- `node_modules/react-native-terra-ui/lib/typescript/src/components/`.
5
-
6
- ## App Root
7
-
8
- ```tsx
9
- // index.js
10
- import './terra-ui'; // configureTerraUI, FIRST
11
- import 'expo-router/entry';
12
- ```
13
-
14
- ```tsx
15
- // app/_layout.tsx
16
- import { TerraUIProvider, ToastProvider } from 'react-native-terra-ui';
17
-
18
- export default function RootLayout() {
19
- return (
20
- <TerraUIProvider>
21
- <ToastProvider>
22
- <Stack screenOptions={{ headerShown: false }} />
23
- </ToastProvider>
24
- </TerraUIProvider>
25
- );
26
- }
27
- ```
28
-
29
- `TerraUIProvider` already renders `SafeAreaProvider`. Add your own only if something above
30
- it needs insets. `ToastProvider` is separate and only needed if you use toasts.
31
-
32
- ## A Screen With A Collapsing Header
33
-
34
- The large title collapses as the scroll container moves, so the two must be paired.
35
-
36
- ```tsx
37
- import { Header, Screen, Text } from 'react-native-terra-ui';
38
-
39
- export function LibraryScreen() {
40
- return (
41
- <Screen>
42
- <Screen.Header as={Header.LargeTitle} title="Library" caption="24 items" />
43
-
44
- <Screen.ScrollView>
45
- <Text variant="body-md">Content starts below the bar automatically.</Text>
46
- </Screen.ScrollView>
47
- </Screen>
48
- );
49
- }
50
- ```
51
-
52
- `Screen.Header` is polymorphic: pass the header through `as` and its props flow straight
53
- on. Older code nests the header as a child instead
54
- (`<Screen.Header><Header.LargeTitle …/></Screen.Header>`); that still renders, but `as` is
55
- the current form — prefer it.
56
-
57
- The scroll containers reserve the header height plus the top safe-area inset as content
58
- padding — do not add your own top padding for the header.
59
-
60
- `margins` controls the screen's horizontal/vertical content margins
61
- (`'all' | 'x' | 'y' | 'none'`, default `'all'`); set it on `Screen` or override per
62
- container. For a full-bleed carousel use `margins="none"`.
63
-
64
- ## A Compact Header With Actions
65
-
66
- ```tsx
67
- import { Header, Screen, Toolbar } from 'react-native-terra-ui';
68
-
69
- <Screen.Header
70
- as={Header.Title}
71
- title="Album"
72
- dismissAction="back"
73
- onDismiss={() => router.back()}
74
- RightToolbar={
75
- <>
76
- <Toolbar.Group>
77
- <Toolbar.Button icon="add" accessibilityLabel="Add" onPress={add} />
78
- <Toolbar.Button icon="download" accessibilityLabel="Save" onPress={save} />
79
- </Toolbar.Group>
80
- <Toolbar.Button icon="share" accessibilityLabel="Share" onPress={share} />
81
- </>
82
- }
83
- />
84
- ```
85
-
86
- The header wraps the slot in a `Toolbar` row for you — pass `Toolbar.Group` /
87
- `Toolbar.Button` children directly, not your own `Toolbar`.
88
-
89
- `dismissAction` is `'back' | 'close' | 'none'`. Pass `navigation` (or `onDismiss`) so it
90
- knows how to leave.
91
-
92
- ## A Toolbar Outside A Header
93
-
94
- Anywhere else, supply the row yourself:
95
-
96
- ```tsx
97
- <Toolbar style={{ position: 'absolute', right: 16, bottom: 24 }}>
98
- <Toolbar.Group background="surface.raised">
99
- <Toolbar.Button icon="add" accessibilityLabel="Add" onPress={add} />
100
- </Toolbar.Group>
101
- <Toolbar.Button icon="share" accessibilityLabel="Share" onPress={share} background="surface.raised" />
102
- </Toolbar>
103
- ```
104
-
105
- One `Toolbar.Group` is one capsule. Items inside share it; a `Toolbar.Button` that is a
106
- direct child of the row keeps its own circle. Text labels work too —
107
- `<Toolbar.Button onPress={save}>Save</Toolbar.Button>` — and the cell grows to fit.
108
-
109
- ## A List
110
-
111
- ```tsx
112
- <Screen>
113
- <Screen.Header as={Header.LargeTitle} title="Inbox" />
114
-
115
- <Screen.FlatList
116
- data={items}
117
- keyExtractor={(item) => item.id}
118
- renderItem={({ item }) => <Row item={item} />}
119
- loading={isLoading}
120
- EmptyComponent={<EmptyState title="Nothing here yet" />}
121
- />
122
- </Screen>
123
- ```
124
-
125
- All three scroll containers share `loading`, `LoadingComponent`, `EmptyComponent`, and
126
- `margins`. `loading` wins over `EmptyComponent` while data is in flight, so a first load
127
- shows a spinner rather than an empty state. Use `Screen.FlashList` for long lists.
128
-
129
- ## Toasts
130
-
131
- ```tsx
132
- import { Toast } from 'react-native-terra-ui';
133
-
134
- Toast.show({ label: 'Saved', variant: 'success' });
135
- ```
136
-
137
- Imperative statics — no hook needed at the call site, but `ToastProvider` must be mounted.
138
- `useToast()` is there if you need the queue. The headline field is `label`, not `title`;
139
- `ToastShowConfig` also takes `description`, `icon`, `actionLabel`, `onActionPress`,
140
- `duration` (a number or `'persistent'`), `placement`, and `showCloseButton`.
141
-
142
- ## Themed Styles
143
-
144
- ```tsx
145
- import { StyleSheet } from 'react-native-unistyles';
146
-
147
- const styles = StyleSheet.create((theme, rt) => ({
148
- card: {
149
- backgroundColor: theme.color['surface.raised'],
150
- borderRadius: theme.radius.lg,
151
- padding: theme.spacing['4'],
152
- gap: theme.spacing['2'],
153
- marginBottom: rt.insets.bottom,
154
- variants: {
155
- emphasis: {
156
- default: {},
157
- strong: { borderWidth: 1, borderColor: theme.color['border.strong'] },
158
- },
159
- },
160
- },
161
- }));
162
-
163
- // in the component
164
- styles.useVariants({ emphasis });
165
- <View style={styles.card} />
166
- ```
167
-
168
- ## Token Props Without A Stylesheet
169
-
170
- For simple layout, `Box` avoids a stylesheet entirely:
171
-
172
- ```tsx
173
- <Box row align="center" justify="between" gap="3" p="4" bg="surface.default" radius="lg">
174
- <Text variant="label-md">Total</Text>
175
- <Text variant="title-sm">$42</Text>
176
- </Box>
177
- ```
178
-
179
- `asChild` merges Box's props onto a single child instead of rendering a `View` — useful for
180
- router links:
181
-
182
- ```tsx
183
- <Link href="/settings" asChild>
184
- <Button variant="outline">Settings</Button>
185
- </Link>
186
- ```
187
-
188
- ## Theme Toggle
189
-
190
- ```tsx
191
- const { scheme, setScheme, accent, setAccent } = useTheme();
192
-
193
- <Button onPress={() => setScheme(scheme === 'dark' ? 'light' : 'dark')}>
194
- {scheme === 'dark' ? 'Light' : 'Dark'}
195
- </Button>
196
- ```
197
-
198
- `setAccent('brand')` needs `brand` registered in `configureTerraUI({ accents })`.
@@ -1,112 +0,0 @@
1
- # Troubleshooting
2
-
3
- Symptom → cause. Most Terra UI problems are setup problems, and most of them fail
4
- **silently** rather than throwing.
5
-
6
- ## Components render unstyled, or the app crashes on launch
7
-
8
- Expo Go. Unistyles v3 requires native modules, so Expo Go cannot run it. Build a
9
- development client:
10
-
11
- ```sh
12
- npx expo run:ios # or run:android
13
- ```
14
-
15
- ## Styles do not change when the theme changes
16
-
17
- The Unistyles Babel plugin is not processing the library. Add it to `autoProcessImports`,
18
- and keep the worklets plugin last:
19
-
20
- ```js
21
- plugins: [
22
- ['react-native-unistyles/plugin', {
23
- root: path.resolve(__dirname, 'src'),
24
- autoProcessImports: ['react-native-terra-ui'],
25
- }],
26
- 'react-native-worklets/plugin', // MUST be last
27
- ]
28
- ```
29
-
30
- Clear the cache after changing Babel config — `npx expo start --clear`.
31
-
32
- The same symptom appears in **your own** components if you built the style object in the
33
- component body from `useUnistyles()`. Move it into `StyleSheet.create`.
34
-
35
- ## My theme config is ignored
36
-
37
- Import order. Something imported `react-native-terra-ui` (the root entry) before your
38
- `configureTerraUI()` call ran, so the auto-default won and later calls are no-ops.
39
-
40
- - The bootstrap file must import from `react-native-terra-ui/theme` only.
41
- - It must be the **first** import in your app entry, before `expo-router/entry` or your
42
- `AppRegistry` registration.
43
-
44
- There is no warning for this. Verify with `getIsConfigured()` from
45
- `react-native-terra-ui/theme` before your call.
46
-
47
- ## An icon renders nothing
48
-
49
- The name is not registered. Only eight semantic names ship with the library
50
- (`navigation.back/forward/close`, `status.info/success/warning/danger`, `person`); every
51
- other name must be in **both** the `TerraUI.IconRegistry` declaration and the `icons` map
52
- passed to `configureTerraUI`. A missing name logs a dev warning and renders `null` — the
53
- layout still reserves space, so it looks like a blank gap.
54
-
55
- ## Content sits under the header, or too far below it
56
-
57
- Use a `Screen` scroll container (`Screen.ScrollView` / `.FlatList` / `.FlashList`) rather
58
- than a plain `ScrollView`. They reserve the header height plus the top inset as content
59
- padding. Do not add your own top padding on top of that.
60
-
61
- If content lands too *low* on first paint in a native tab screen, `react-native-screens`
62
- is also applying UIKit's automatic content inset. Opt out at the navigator — on an
63
- expo-router native tab that is `disableAutomaticContentInsets` on the trigger.
64
-
65
- ## `Header.LargeTitle` does not collapse
66
-
67
- It reads scroll position from the `Screen` context, so it needs both halves:
68
-
69
- - rendered through `Screen.Header` — `<Screen.Header as={Header.LargeTitle} title="…" />`
70
- (or nested inside it, the older form), as a direct child of `Screen`, and
71
- - paired with `Screen.ScrollView` / `.FlatList` / `.FlashList` in the same `Screen`.
72
-
73
- A plain `ScrollView` sibling will not drive it.
74
-
75
- ## `useScreen()` / toast hooks throw
76
-
77
- They require their provider. `useScreen()` must be under a `Screen`; `useToast()` and
78
- `Toast.show()` need `ToastProvider` mounted (it is **not** included in `TerraUIProvider`).
79
-
80
- ## A token prop does not work
81
-
82
- Token style props (`p`, `gap`, `bg`, `radius`, `row`, …) exist on `Box` and `Surface`
83
- only. Every other component takes explicit props — read its types.
84
-
85
- ## A color token has no effect
86
-
87
- Colors are flat dotted keys, not nested objects:
88
-
89
- ```ts
90
- theme.color['surface.default'] // ✅
91
- theme.color.surface.default // ✗ undefined
92
- theme.color.background // ✅ the one single-segment token
93
- ```
94
-
95
- An unknown key yields `undefined`, which React Native ignores silently.
96
-
97
- ## My `Surface` has a radius or shadow I did not ask for
98
-
99
- `Surface` reads `radius` and `elevation` from `configureTerraUI({ components: { surface } })`.
100
- That is the point of it — but if you want a neutral container, use `Box`.
101
-
102
- ## Types are missing or stale after upgrading
103
-
104
- The package ships declarations at `lib/typescript`. Reinstall, and restart the TS server in
105
- your editor. If you use the `"source"` export condition (monorepo/Metro), you are compiling
106
- the library's TypeScript directly, so its own type errors surface in your build.
107
-
108
- ## Something looks wrong and none of the above applies
109
-
110
- Read the component's source — it ships in the package under
111
- `node_modules/react-native-terra-ui/src/components/<name>/`. The JSDoc on each prop states
112
- its default, and it is the version you actually have installed.