@ledgerhq/lumen-ui-rnative 0.1.37 → 0.1.38

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 (129) hide show
  1. package/dist/module/lib/Components/AmountInput/AmountInput.js +109 -72
  2. package/dist/module/lib/Components/AmountInput/AmountInput.js.map +1 -1
  3. package/dist/module/lib/Components/AmountInput/AmountInput.mdx +12 -0
  4. package/dist/module/lib/Components/AmountInput/AmountInput.stories.js +53 -0
  5. package/dist/module/lib/Components/AmountInput/AmountInput.stories.js.map +1 -1
  6. package/dist/module/lib/Components/Avatar/Avatar.js +6 -5
  7. package/dist/module/lib/Components/Avatar/Avatar.js.map +1 -1
  8. package/dist/module/lib/Components/Avatar/Avatar.mdx +2 -0
  9. package/dist/module/lib/Components/Avatar/Avatar.test.js +10 -13
  10. package/dist/module/lib/Components/Avatar/Avatar.test.js.map +1 -1
  11. package/dist/module/lib/Components/DotIcon/DotIcon.js +7 -4
  12. package/dist/module/lib/Components/DotIcon/DotIcon.js.map +1 -1
  13. package/dist/module/lib/Components/DotIcon/DotIcon.stories.js +10 -0
  14. package/dist/module/lib/Components/DotIcon/DotIcon.stories.js.map +1 -1
  15. package/dist/module/lib/Components/DotIndicator/DotIndicator.js +5 -5
  16. package/dist/module/lib/Components/DotIndicator/DotIndicator.js.map +1 -1
  17. package/dist/module/lib/Components/DotIndicator/DotIndicator.mdx +4 -4
  18. package/dist/module/lib/Components/DotIndicator/DotIndicator.stories.js +3 -3
  19. package/dist/module/lib/Components/DotIndicator/DotIndicator.test.js +12 -2
  20. package/dist/module/lib/Components/DotIndicator/DotIndicator.test.js.map +1 -1
  21. package/dist/module/lib/Components/DotSymbol/DotSymbol.js +7 -4
  22. package/dist/module/lib/Components/DotSymbol/DotSymbol.js.map +1 -1
  23. package/dist/module/lib/Components/DotSymbol/DotSymbol.stories.js +19 -0
  24. package/dist/module/lib/Components/DotSymbol/DotSymbol.stories.js.map +1 -1
  25. package/dist/module/lib/Components/Label/Label.js +1 -1
  26. package/dist/module/lib/Components/MediaButton/MediaButton.js +2 -2
  27. package/dist/module/lib/Components/MediaButton/MediaButton.mdx +2 -2
  28. package/dist/module/lib/Components/MediaImage/MediaImage.js +4 -2
  29. package/dist/module/lib/Components/MediaImage/MediaImage.js.map +1 -1
  30. package/dist/module/lib/Components/MediaImage/MediaImage.mdx +1 -1
  31. package/dist/module/lib/Components/MediaImage/MediaImage.stories.js +12 -0
  32. package/dist/module/lib/Components/MediaImage/MediaImage.stories.js.map +1 -1
  33. package/dist/module/lib/Components/OptionList/OptionList.mdx +1 -1
  34. package/dist/module/lib/Components/ThemeProvider/ThemeProvider.js +2 -5
  35. package/dist/module/lib/Components/ThemeProvider/ThemeProvider.js.map +1 -1
  36. package/dist/module/lib/Components/index.js +0 -1
  37. package/dist/module/lib/Components/index.js.map +1 -1
  38. package/dist/module/lib/Symbols/Icons/Lightbulb.js +3 -3
  39. package/dist/module/lib/Symbols/Icons/Lightbulb.js.map +1 -1
  40. package/dist/typescript/src/lib/Components/AmountInput/AmountInput.d.ts +1 -1
  41. package/dist/typescript/src/lib/Components/AmountInput/AmountInput.d.ts.map +1 -1
  42. package/dist/typescript/src/lib/Components/AmountInput/types.d.ts +12 -0
  43. package/dist/typescript/src/lib/Components/AmountInput/types.d.ts.map +1 -1
  44. package/dist/typescript/src/lib/Components/Avatar/Avatar.d.ts +1 -1
  45. package/dist/typescript/src/lib/Components/Avatar/Avatar.d.ts.map +1 -1
  46. package/dist/typescript/src/lib/Components/DotIcon/DotIcon.d.ts +2 -1
  47. package/dist/typescript/src/lib/Components/DotIcon/DotIcon.d.ts.map +1 -1
  48. package/dist/typescript/src/lib/Components/DotIcon/types.d.ts +1 -1
  49. package/dist/typescript/src/lib/Components/DotIcon/types.d.ts.map +1 -1
  50. package/dist/typescript/src/lib/Components/DotIndicator/types.d.ts +2 -2
  51. package/dist/typescript/src/lib/Components/DotSymbol/DotSymbol.d.ts.map +1 -1
  52. package/dist/typescript/src/lib/Components/DotSymbol/types.d.ts +1 -1
  53. package/dist/typescript/src/lib/Components/DotSymbol/types.d.ts.map +1 -1
  54. package/dist/typescript/src/lib/Components/Label/Label.d.ts +1 -1
  55. package/dist/typescript/src/lib/Components/MediaButton/MediaButton.d.ts +2 -2
  56. package/dist/typescript/src/lib/Components/MediaImage/MediaImage.d.ts.map +1 -1
  57. package/dist/typescript/src/lib/Components/MediaImage/types.d.ts +1 -1
  58. package/dist/typescript/src/lib/Components/MediaImage/types.d.ts.map +1 -1
  59. package/dist/typescript/src/lib/Components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
  60. package/dist/typescript/src/lib/Components/index.d.ts +0 -1
  61. package/dist/typescript/src/lib/Components/index.d.ts.map +1 -1
  62. package/package.json +3 -3
  63. package/src/lib/Components/AmountInput/AmountInput.mdx +12 -0
  64. package/src/lib/Components/AmountInput/AmountInput.stories.tsx +68 -1
  65. package/src/lib/Components/AmountInput/AmountInput.tsx +118 -75
  66. package/src/lib/Components/AmountInput/types.ts +14 -0
  67. package/src/lib/Components/Avatar/Avatar.mdx +2 -0
  68. package/src/lib/Components/Avatar/Avatar.test.tsx +16 -18
  69. package/src/lib/Components/Avatar/Avatar.tsx +9 -8
  70. package/src/lib/Components/DotIcon/DotIcon.stories.tsx +8 -0
  71. package/src/lib/Components/DotIcon/DotIcon.tsx +4 -1
  72. package/src/lib/Components/DotIcon/types.ts +1 -1
  73. package/src/lib/Components/DotIndicator/DotIndicator.mdx +4 -4
  74. package/src/lib/Components/DotIndicator/DotIndicator.stories.tsx +2 -2
  75. package/src/lib/Components/DotIndicator/DotIndicator.test.tsx +12 -2
  76. package/src/lib/Components/DotIndicator/DotIndicator.tsx +5 -5
  77. package/src/lib/Components/DotIndicator/types.ts +2 -2
  78. package/src/lib/Components/DotSymbol/DotSymbol.stories.tsx +15 -0
  79. package/src/lib/Components/DotSymbol/DotSymbol.tsx +4 -1
  80. package/src/lib/Components/DotSymbol/types.ts +1 -1
  81. package/src/lib/Components/Label/Label.tsx +1 -1
  82. package/src/lib/Components/MediaButton/MediaButton.mdx +2 -2
  83. package/src/lib/Components/MediaButton/MediaButton.tsx +2 -2
  84. package/src/lib/Components/MediaImage/MediaImage.mdx +1 -1
  85. package/src/lib/Components/MediaImage/MediaImage.stories.tsx +3 -0
  86. package/src/lib/Components/MediaImage/MediaImage.tsx +2 -0
  87. package/src/lib/Components/MediaImage/types.ts +1 -1
  88. package/src/lib/Components/OptionList/OptionList.mdx +1 -1
  89. package/src/lib/Components/ThemeProvider/ThemeProvider.tsx +1 -4
  90. package/src/lib/Components/index.ts +0 -1
  91. package/src/lib/Symbols/Icons/Lightbulb.tsx +3 -3
  92. package/dist/module/lib/Components/Select/GlobalSelectBottomSheet.js +0 -155
  93. package/dist/module/lib/Components/Select/GlobalSelectBottomSheet.js.map +0 -1
  94. package/dist/module/lib/Components/Select/GlobalSelectContext.js +0 -78
  95. package/dist/module/lib/Components/Select/GlobalSelectContext.js.map +0 -1
  96. package/dist/module/lib/Components/Select/Select.js +0 -366
  97. package/dist/module/lib/Components/Select/Select.js.map +0 -1
  98. package/dist/module/lib/Components/Select/Select.mdx +0 -596
  99. package/dist/module/lib/Components/Select/Select.stories.js +0 -304
  100. package/dist/module/lib/Components/Select/Select.stories.js.map +0 -1
  101. package/dist/module/lib/Components/Select/Select.test.js +0 -123
  102. package/dist/module/lib/Components/Select/Select.test.js.map +0 -1
  103. package/dist/module/lib/Components/Select/SelectContext.js +0 -38
  104. package/dist/module/lib/Components/Select/SelectContext.js.map +0 -1
  105. package/dist/module/lib/Components/Select/index.js +0 -6
  106. package/dist/module/lib/Components/Select/index.js.map +0 -1
  107. package/dist/module/lib/Components/Select/types.js +0 -4
  108. package/dist/module/lib/Components/Select/types.js.map +0 -1
  109. package/dist/typescript/src/lib/Components/Select/GlobalSelectBottomSheet.d.ts +0 -20
  110. package/dist/typescript/src/lib/Components/Select/GlobalSelectBottomSheet.d.ts.map +0 -1
  111. package/dist/typescript/src/lib/Components/Select/GlobalSelectContext.d.ts +0 -44
  112. package/dist/typescript/src/lib/Components/Select/GlobalSelectContext.d.ts.map +0 -1
  113. package/dist/typescript/src/lib/Components/Select/Select.d.ts +0 -52
  114. package/dist/typescript/src/lib/Components/Select/Select.d.ts.map +0 -1
  115. package/dist/typescript/src/lib/Components/Select/SelectContext.d.ts +0 -36
  116. package/dist/typescript/src/lib/Components/Select/SelectContext.d.ts.map +0 -1
  117. package/dist/typescript/src/lib/Components/Select/index.d.ts +0 -4
  118. package/dist/typescript/src/lib/Components/Select/index.d.ts.map +0 -1
  119. package/dist/typescript/src/lib/Components/Select/types.d.ts +0 -130
  120. package/dist/typescript/src/lib/Components/Select/types.d.ts.map +0 -1
  121. package/src/lib/Components/Select/GlobalSelectBottomSheet.tsx +0 -180
  122. package/src/lib/Components/Select/GlobalSelectContext.tsx +0 -103
  123. package/src/lib/Components/Select/Select.mdx +0 -596
  124. package/src/lib/Components/Select/Select.stories.tsx +0 -266
  125. package/src/lib/Components/Select/Select.test.tsx +0 -117
  126. package/src/lib/Components/Select/Select.tsx +0 -469
  127. package/src/lib/Components/Select/SelectContext.tsx +0 -68
  128. package/src/lib/Components/Select/index.ts +0 -3
  129. package/src/lib/Components/Select/types.ts +0 -149
@@ -1,596 +0,0 @@
1
- import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';
2
- import * as SelectStories from './Select.stories.tsx';
3
- import { Select } from './Select';
4
- import { CustomTabs, Tab } from '../../../../.storybook/components';
5
-
6
- <Meta title='Selection/Select' of={SelectStories} />
7
-
8
- # Select
9
-
10
- <CustomTabs>
11
- <Tab label="Overview">
12
-
13
- ## Introduction
14
-
15
- The Select component provides a dropdown interface for choosing from a list of options using a native bottom sheet. Built specifically for React Native, it offers excellent accessibility, touch-friendly interactions, and a modern floating label design that matches our BaseInput component.
16
-
17
- > View in [Figma](https://www.figma.com/design/JxaLVMTWirCpU0rsbZ30k7/2.-Components-Library?node-id=6397-463&m=dev).
18
-
19
- > ⚠️ **Note on Web Preview:** The Storybook preview below may display visual inconsistencies as certain React Native APIs (such as Reanimated animations) cannot be fully translated to web environments. While the component's functionality should accurately represent the native implementation, it may not render as intended. For the complete native experience, please refer to the component on an actual iOS or Android device.
20
-
21
- <Canvas of={SelectStories.Base} />
22
- <Controls of={SelectStories.Base} />
23
-
24
- ## Anatomy
25
-
26
- > **Layout:** The Select component takes the full width of its container by default. You can control the width directly using `lx` prop or by wrapping in a container.
27
-
28
- The Select component consists of several sub-components:
29
-
30
- - **Select**: The root component that manages the select's state
31
- - **SelectTrigger**: The clickable element that opens the bottom sheet with floating label support
32
- - **SelectValue**: Displays the currently selected value
33
- - **SelectContent**: Container for select items (not rendered directly, used for structure)
34
- - **SelectItem**: Individual selectable options
35
- - **SelectItemText**: The text content of an item
36
- - **SelectGroup**: Optional grouping of related items
37
- - **SelectLabel**: Labels for groups
38
- - **SelectSeparator**: Visual dividers between groups or items
39
-
40
- ### Bottom Sheet Architecture
41
-
42
- Unlike web implementations, the React Native Select uses a bottom sheet for displaying options. This provides a native mobile experience with smooth animations and proper handling of keyboard and screen size.
43
-
44
- The bottom sheet requires `ThemeProvider` and `BottomSheetModalProvider` at your app's root level. See the [Implementation tab](#implementation) for setup.
45
-
46
- ### Floating Label
47
-
48
- The label text automatically floats above the input when a value is selected, providing a clean and modern interface that saves vertical space.
49
-
50
- ### Disabled State
51
-
52
- The select can be disabled to prevent user interaction, with visual feedback indicating the disabled state.
53
-
54
- ## Properties
55
-
56
- ### Grouped Options
57
-
58
- Organize options with groups, labels, and separators:
59
-
60
- <Canvas of={SelectStories.WithGroups} />
61
-
62
- ### Disabled Items
63
-
64
- Individual items can be disabled while keeping the select interactive:
65
-
66
- <Canvas of={SelectStories.WithDisabledItems} />
67
-
68
- ### Disabled Select
69
-
70
- The entire select can be disabled:
71
-
72
- <Canvas of={SelectStories.DisabledSelect} />
73
-
74
- ### With Callbacks
75
-
76
- Listen to value changes and open/close events:
77
-
78
- <Canvas of={SelectStories.WithChangeCallback} />
79
-
80
- ## Controlled vs Uncontrolled
81
-
82
- The Select component supports both controlled and uncontrolled usage.
83
-
84
- ### Uncontrolled (with defaultValue)
85
-
86
- Use `defaultValue` when you don't need to track the select's value in state. The component manages its own internal state.
87
-
88
- ### Controlled (with value and onValueChange)
89
-
90
- Use `value` and `onValueChange` when you want full control of the select's state from your component logic.
91
-
92
- ## Accessibility
93
-
94
- The Select component follows accessibility best practices:
95
-
96
- - Supports screen reader navigation
97
- - Labels are properly associated with selects
98
- - Touch target sizes meet minimum requirements (48px height)
99
- - Proper focus management with bottom sheet
100
- - Check icon indicates selected state
101
- - Disabled items are properly announced
102
-
103
- ## Best Practices
104
-
105
- **Labels**: Always provide clear, descriptive labels
106
-
107
- **Grouping**: Use groups and separators for long lists with related items
108
-
109
- **Default Values**: Consider providing sensible defaults when appropriate
110
-
111
- **Disabled State**: Use `disabled` on both the Select and individual items when needed
112
-
113
- **Value Management**: Always provide both `value` and `onValueChange` for controlled usage
114
-
115
- </Tab>
116
- <Tab label="Implementation">
117
-
118
- ## Setup
119
-
120
- Install and set up the library with our [Setup Guide →](?path=/docs/getting-started-setup--docs).
121
-
122
- ### Provider Setup
123
-
124
- Select uses a bottom sheet that requires specific providers. `BottomSheetModalProvider` must be **inside** `GestureHandlerRootView`:
125
-
126
- ```tsx
127
- import { ThemeProvider, BottomSheetModalProvider, GlobalSelectBottomSheet } from '@ledgerhq/lumen-ui-rnative';
128
- import { GestureHandlerRootView } from 'react-native-gesture-handler';
129
-
130
- function App() {
131
- return (
132
- <ThemeProvider themes={yourThemes} colorScheme="light">
133
- <GestureHandlerRootView style={{ flex: 1 }}>
134
- <BottomSheetModalProvider>
135
- <YourAppContent />
136
- <GlobalSelectBottomSheet />
137
- </BottomSheetModalProvider>
138
- </GestureHandlerRootView>
139
- </ThemeProvider>
140
- );
141
- }
142
- ```
143
-
144
- ### Basic Usage
145
-
146
- ```tsx
147
- import {
148
- Select,
149
- SelectTrigger,
150
- SelectValue,
151
- SelectContent,
152
- SelectItem,
153
- SelectItemText,
154
- } from '@ledgerhq/lumen-ui-rnative';
155
- import { useState } from 'react';
156
-
157
- function MyComponent() {
158
- const [value, setValue] = useState('');
159
-
160
- return (
161
- <Select value={value} onValueChange={setValue}>
162
- <SelectTrigger label='Choose an option'>
163
- <SelectValue />
164
- </SelectTrigger>
165
- <SelectContent>
166
- <SelectItem value='option1'>
167
- <SelectItemText>Option 1</SelectItemText>
168
- </SelectItem>
169
- <SelectItem value='option2'>
170
- <SelectItemText>Option 2</SelectItemText>
171
- </SelectItem>
172
- <SelectItem value='option3'>
173
- <SelectItemText>Option 3</SelectItemText>
174
- </SelectItem>
175
- </SelectContent>
176
- </Select>
177
- );
178
- }
179
- ```
180
-
181
- > **Note:** `SelectValue` must be explicitly included in `SelectTrigger` to display the selected value.
182
-
183
- ### With Groups and Separators
184
-
185
- Organize related options using groups with labels and separators:
186
-
187
- ```tsx
188
- import {
189
- Select,
190
- SelectTrigger,
191
- SelectValue,
192
- SelectContent,
193
- SelectGroup,
194
- SelectLabel,
195
- SelectItem,
196
- SelectItemText,
197
- SelectSeparator,
198
- } from '@ledgerhq/lumen-ui-rnative';
199
- import { useState } from 'react';
200
-
201
- function MyComponent() {
202
- const [value, setValue] = useState('');
203
-
204
- return (
205
- <Select value={value} onValueChange={setValue}>
206
- <SelectTrigger label='Category'>
207
- <SelectValue />
208
- </SelectTrigger>
209
- <SelectContent>
210
- <SelectGroup>
211
- <SelectLabel>Fruits</SelectLabel>
212
- <SelectItem value='apple'>
213
- <SelectItemText>Apple</SelectItemText>
214
- </SelectItem>
215
- <SelectItem value='banana'>
216
- <SelectItemText>Banana</SelectItemText>
217
- </SelectItem>
218
- </SelectGroup>
219
- <SelectSeparator />
220
- <SelectGroup>
221
- <SelectLabel>Vegetables</SelectLabel>
222
- <SelectItem value='carrot'>
223
- <SelectItemText>Carrot</SelectItemText>
224
- </SelectItem>
225
- <SelectItem value='broccoli'>
226
- <SelectItemText>Broccoli</SelectItemText>
227
- </SelectItem>
228
- </SelectGroup>
229
- </SelectContent>
230
- </Select>
231
- );
232
- }
233
- ```
234
-
235
- ### With Default Value
236
-
237
- Provide an initial value using the `defaultValue` prop for uncontrolled usage:
238
-
239
- ```tsx
240
- <Select defaultValue='option1' onValueChange={(value) => console.log(value)}>
241
- <SelectTrigger label='Choose an option'>
242
- <SelectValue />
243
- </SelectTrigger>
244
- <SelectContent>
245
- <SelectItem value='option1'>
246
- <SelectItemText>Option 1</SelectItemText>
247
- </SelectItem>
248
- <SelectItem value='option2'>
249
- <SelectItemText>Option 2</SelectItemText>
250
- </SelectItem>
251
- </SelectContent>
252
- </Select>
253
- ```
254
-
255
- ### Disabled State
256
-
257
- Use the `disabled` prop to prevent user interaction:
258
-
259
- ```tsx
260
- // Disable entire select
261
- <Select value={value} onValueChange={setValue} disabled>
262
- <SelectTrigger label='Choose an option'>
263
- <SelectValue />
264
- </SelectTrigger>
265
- <SelectContent>
266
- <SelectItem value='option1'>
267
- <SelectItemText>Option 1</SelectItemText>
268
- </SelectItem>
269
- </SelectContent>
270
- </Select>
271
-
272
- // Disable individual items
273
- <SelectContent>
274
- <SelectItem value='option1'>
275
- <SelectItemText>Option 1</SelectItemText>
276
- </SelectItem>
277
- <SelectItem value='option2' disabled>
278
- <SelectItemText>Option 2 (Disabled)</SelectItemText>
279
- </SelectItem>
280
- </SelectContent>
281
- ```
282
-
283
- ### With Custom Styling
284
-
285
- While the component comes with predefined styles, you can extend them using the `lx` prop:
286
-
287
- ```tsx
288
- import { Box } from '@ledgerhq/lumen-ui-rnative';
289
-
290
- <Box lx={{ maxWidth: 's320' }}>
291
- <Select value={value} onValueChange={setValue}>
292
- <SelectTrigger label='Choose an option'>
293
- <SelectValue />
294
- </SelectTrigger>
295
- <SelectContent>
296
- <SelectItem value='option1'>
297
- <SelectItemText>Option 1</SelectItemText>
298
- </SelectItem>
299
- </SelectContent>
300
- </Select>
301
- </Box>
302
- ```
303
-
304
- ## Do's and Don'ts
305
-
306
- The following guidelines ensure consistent usage of the Select component and maintain design system principles.
307
-
308
- ### Component Structure
309
-
310
- ✅ **Do**
311
-
312
- ```tsx
313
- // Always use the complete component structure
314
- <Select value={value} onValueChange={setValue}>
315
- <SelectTrigger label='Choose option'>
316
- <SelectValue />
317
- </SelectTrigger>
318
- <SelectContent>
319
- <SelectItem value='option1'>
320
- <SelectItemText>Option 1</SelectItemText>
321
- </SelectItem>
322
- </SelectContent>
323
- </Select>
324
-
325
- // Use groups and labels for organized lists
326
- <Select value={value} onValueChange={setValue}>
327
- <SelectTrigger label='Category'>
328
- <SelectValue />
329
- </SelectTrigger>
330
- <SelectContent>
331
- <SelectGroup>
332
- <SelectLabel>Group Title</SelectLabel>
333
- <SelectItem value='item1'>
334
- <SelectItemText>Item 1</SelectItemText>
335
- </SelectItem>
336
- </SelectGroup>
337
- </SelectContent>
338
- </Select>
339
-
340
- // Always wrap SelectItemText in SelectItem
341
- <SelectItem value='option1'>
342
- <SelectItemText>Option 1</SelectItemText>
343
- </SelectItem>
344
- ```
345
-
346
- ❌ **Don't**
347
-
348
- ```tsx
349
- // Don't omit SelectValue from SelectTrigger
350
- <SelectTrigger label='Choose option' />
351
-
352
- // Don't use raw text in SelectItem without SelectItemText
353
- <SelectItem value='option1'>Option 1</SelectItem>
354
-
355
- // Don't skip required components
356
- <Select value={value}>
357
- <SelectTrigger label='Choose option' />
358
- </Select>
359
- ```
360
-
361
- ### Value Management
362
-
363
- ✅ **Do**
364
-
365
- ```tsx
366
- // Use controlled pattern with both value and onValueChange
367
- const [value, setValue] = useState('');
368
- <Select value={value} onValueChange={setValue}>
369
- <SelectTrigger label='Option'>
370
- <SelectValue />
371
- </SelectTrigger>
372
- <SelectContent>
373
- <SelectItem value='option1'>
374
- <SelectItemText>Option 1</SelectItemText>
375
- </SelectItem>
376
- </SelectContent>
377
- </Select>
378
-
379
- // Or use uncontrolled pattern with defaultValue
380
- <Select defaultValue='option1' onValueChange={(value) => console.log(value)}>
381
- <SelectTrigger label='Option'>
382
- <SelectValue />
383
- </SelectTrigger>
384
- <SelectContent>
385
- <SelectItem value='option1'>
386
- <SelectItemText>Option 1</SelectItemText>
387
- </SelectItem>
388
- </SelectContent>
389
- </Select>
390
- ```
391
-
392
- ❌ **Don't**
393
-
394
- ```tsx
395
- // Don't mix controlled and uncontrolled patterns
396
- <Select value={value} defaultValue='option1' onValueChange={setValue}>
397
- <SelectTrigger label='Option'>
398
- <SelectValue />
399
- </SelectTrigger>
400
- <SelectContent>
401
- <SelectItem value='option1'>
402
- <SelectItemText>Option 1</SelectItemText>
403
- </SelectItem>
404
- </SelectContent>
405
- </Select>
406
-
407
- // Don't forget onValueChange in controlled mode
408
- <Select value={value}>
409
- <SelectTrigger label='Option'>
410
- <SelectValue />
411
- </SelectTrigger>
412
- <SelectContent>
413
- <SelectItem value='option1'>
414
- <SelectItemText>Option 1</SelectItemText>
415
- </SelectItem>
416
- </SelectContent>
417
- </Select>
418
- ```
419
-
420
- ### Layout and Styling
421
-
422
- The Select component takes the **full width** of its parent container by default. You can control the width using `lx` prop or wrapper containers:
423
-
424
- ✅ **Do**
425
-
426
- ```tsx
427
- // Preferred: Direct width control with lx
428
- <Select value={value} onValueChange={setValue}>
429
- <SelectTrigger label='Option' lx={{ maxWidth: 's320' }}>
430
- <SelectValue />
431
- </SelectTrigger>
432
- <SelectContent>
433
- <SelectItem value='option1'>
434
- <SelectItemText>Option 1</SelectItemText>
435
- </SelectItem>
436
- </SelectContent>
437
- </Select>
438
-
439
- // Use lx for margins and positioning
440
- <Select value={value} onValueChange={setValue}>
441
- <SelectTrigger label='Option' lx={{ marginTop: 's16', marginHorizontal: 'auto' }}>
442
- <SelectValue />
443
- </SelectTrigger>
444
- <SelectContent>
445
- <SelectItem value='option1'>
446
- <SelectItemText>Option 1</SelectItemText>
447
- </SelectItem>
448
- </SelectContent>
449
- </Select>
450
-
451
- // Alternative: Container wrapper
452
- <Box lx={{ maxWidth: 's320' }}>
453
- <Select value={value} onValueChange={setValue}>
454
- <SelectTrigger label='Option'>
455
- <SelectValue />
456
- </SelectTrigger>
457
- <SelectContent>
458
- <SelectItem value='option1'>
459
- <SelectItemText>Option 1</SelectItemText>
460
- </SelectItem>
461
- </SelectContent>
462
- </Select>
463
- </Box>
464
- ```
465
-
466
- ❌ **Don't**
467
-
468
- ```tsx
469
- // Don't use style prop for token-based values (use lx instead)
470
- <SelectTrigger label='Option' style={{ maxWidth: 320 }}>
471
- <SelectValue />
472
- </SelectTrigger>
473
- ```
474
-
475
- ### Accessibility and Labels
476
-
477
- ✅ **Do**
478
-
479
- ```tsx
480
- // Always provide labels
481
- <Select value={value} onValueChange={setValue}>
482
- <SelectTrigger label='Choose category'>
483
- <SelectValue />
484
- </SelectTrigger>
485
- <SelectContent>
486
- <SelectItem value='option1'>
487
- <SelectItemText>Option 1</SelectItemText>
488
- </SelectItem>
489
- </SelectContent>
490
- </Select>
491
-
492
- // Labels automatically float when a value is selected
493
- <Select value={value} onValueChange={setValue}>
494
- <SelectTrigger label='Important'>
495
- <SelectValue />
496
- </SelectTrigger>
497
- <SelectContent>
498
- <SelectItem value='option1'>
499
- <SelectItemText>Option 1</SelectItemText>
500
- </SelectItem>
501
- </SelectContent>
502
- </Select>
503
- ```
504
-
505
- ❌ **Don't**
506
-
507
- ```tsx
508
- // Don't omit labels
509
- <Select value={value} onValueChange={setValue}>
510
- <SelectTrigger>
511
- <SelectValue />
512
- </SelectTrigger>
513
- <SelectContent>
514
- <SelectItem value='option1'>
515
- <SelectItemText>Option 1</SelectItemText>
516
- </SelectItem>
517
- </SelectContent>
518
- </Select>
519
-
520
- // Don't use style prop to modify core appearance
521
- <SelectTrigger label='Option' style={{ backgroundColor: 'red' }}>
522
- <SelectValue />
523
- </SelectTrigger>
524
- ```
525
-
526
- ### Performance Considerations
527
-
528
- ✅ **Do**
529
-
530
- ```tsx
531
- // Use stable callbacks with useCallback
532
- const handleValueChange = useCallback((newValue: string) => {
533
- setValue(newValue);
534
- }, []);
535
-
536
- <Select value={value} onValueChange={handleValueChange}>
537
- <SelectTrigger label='Option'>
538
- <SelectValue />
539
- </SelectTrigger>
540
- <SelectContent>
541
- <SelectItem value='option1'>
542
- <SelectItemText>Option 1</SelectItemText>
543
- </SelectItem>
544
- </SelectContent>
545
- </Select>;
546
- ```
547
-
548
- ❌ **Don't**
549
-
550
- ```tsx
551
- // Don't create new functions in render for frequently re-rendered components
552
- <FlatList
553
- data={items}
554
- renderItem={({ item }) => (
555
- <Select
556
- value={item.value}
557
- onValueChange={(value) => handleChange(item.id, value)}
558
- >
559
- <SelectTrigger label='Option'>
560
- <SelectValue />
561
- </SelectTrigger>
562
- <SelectContent>
563
- <SelectItem value='option1'>
564
- <SelectItemText>Option 1</SelectItemText>
565
- </SelectItem>
566
- </SelectContent>
567
- </Select>
568
- )}
569
- />
570
- ```
571
-
572
- ## Platform Considerations
573
-
574
- ### iOS Specific
575
-
576
- - Bottom sheet automatically adapts to iOS design guidelines
577
- - Respects iOS safe area insets
578
- - Supports iOS accessibility settings like Dynamic Type
579
- - Native-feeling bottom sheet animations
580
-
581
- ### Android Specific
582
-
583
- - Supports Android back button to close bottom sheet
584
- - Handles Android system gestures appropriately
585
- - Respects Android accessibility services
586
- - Material Design-inspired animations
587
-
588
- ### Cross-Platform
589
-
590
- - Consistent visual appearance across platforms
591
- - Platform-appropriate touch feedback
592
- - Unified API regardless of platform
593
- - Animated floating labels work seamlessly on both platforms
594
-
595
- </Tab>
596
- </CustomTabs>