@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.
- package/dist/module/lib/Components/AmountInput/AmountInput.js +109 -72
- package/dist/module/lib/Components/AmountInput/AmountInput.js.map +1 -1
- package/dist/module/lib/Components/AmountInput/AmountInput.mdx +12 -0
- package/dist/module/lib/Components/AmountInput/AmountInput.stories.js +53 -0
- package/dist/module/lib/Components/AmountInput/AmountInput.stories.js.map +1 -1
- package/dist/module/lib/Components/Avatar/Avatar.js +6 -5
- package/dist/module/lib/Components/Avatar/Avatar.js.map +1 -1
- package/dist/module/lib/Components/Avatar/Avatar.mdx +2 -0
- package/dist/module/lib/Components/Avatar/Avatar.test.js +10 -13
- package/dist/module/lib/Components/Avatar/Avatar.test.js.map +1 -1
- package/dist/module/lib/Components/DotIcon/DotIcon.js +7 -4
- package/dist/module/lib/Components/DotIcon/DotIcon.js.map +1 -1
- package/dist/module/lib/Components/DotIcon/DotIcon.stories.js +10 -0
- package/dist/module/lib/Components/DotIcon/DotIcon.stories.js.map +1 -1
- package/dist/module/lib/Components/DotIndicator/DotIndicator.js +5 -5
- package/dist/module/lib/Components/DotIndicator/DotIndicator.js.map +1 -1
- package/dist/module/lib/Components/DotIndicator/DotIndicator.mdx +4 -4
- package/dist/module/lib/Components/DotIndicator/DotIndicator.stories.js +3 -3
- package/dist/module/lib/Components/DotIndicator/DotIndicator.test.js +12 -2
- package/dist/module/lib/Components/DotIndicator/DotIndicator.test.js.map +1 -1
- package/dist/module/lib/Components/DotSymbol/DotSymbol.js +7 -4
- package/dist/module/lib/Components/DotSymbol/DotSymbol.js.map +1 -1
- package/dist/module/lib/Components/DotSymbol/DotSymbol.stories.js +19 -0
- package/dist/module/lib/Components/DotSymbol/DotSymbol.stories.js.map +1 -1
- package/dist/module/lib/Components/Label/Label.js +1 -1
- package/dist/module/lib/Components/MediaButton/MediaButton.js +2 -2
- package/dist/module/lib/Components/MediaButton/MediaButton.mdx +2 -2
- package/dist/module/lib/Components/MediaImage/MediaImage.js +4 -2
- package/dist/module/lib/Components/MediaImage/MediaImage.js.map +1 -1
- package/dist/module/lib/Components/MediaImage/MediaImage.mdx +1 -1
- package/dist/module/lib/Components/MediaImage/MediaImage.stories.js +12 -0
- package/dist/module/lib/Components/MediaImage/MediaImage.stories.js.map +1 -1
- package/dist/module/lib/Components/OptionList/OptionList.mdx +1 -1
- package/dist/module/lib/Components/ThemeProvider/ThemeProvider.js +2 -5
- package/dist/module/lib/Components/ThemeProvider/ThemeProvider.js.map +1 -1
- package/dist/module/lib/Components/index.js +0 -1
- package/dist/module/lib/Components/index.js.map +1 -1
- package/dist/module/lib/Symbols/Icons/Lightbulb.js +3 -3
- package/dist/module/lib/Symbols/Icons/Lightbulb.js.map +1 -1
- package/dist/typescript/src/lib/Components/AmountInput/AmountInput.d.ts +1 -1
- package/dist/typescript/src/lib/Components/AmountInput/AmountInput.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/AmountInput/types.d.ts +12 -0
- package/dist/typescript/src/lib/Components/AmountInput/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Avatar/Avatar.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Avatar/Avatar.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/DotIcon/DotIcon.d.ts +2 -1
- package/dist/typescript/src/lib/Components/DotIcon/DotIcon.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/DotIcon/types.d.ts +1 -1
- package/dist/typescript/src/lib/Components/DotIcon/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/DotIndicator/types.d.ts +2 -2
- package/dist/typescript/src/lib/Components/DotSymbol/DotSymbol.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/DotSymbol/types.d.ts +1 -1
- package/dist/typescript/src/lib/Components/DotSymbol/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Label/Label.d.ts +1 -1
- package/dist/typescript/src/lib/Components/MediaButton/MediaButton.d.ts +2 -2
- package/dist/typescript/src/lib/Components/MediaImage/MediaImage.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/MediaImage/types.d.ts +1 -1
- package/dist/typescript/src/lib/Components/MediaImage/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/ThemeProvider/ThemeProvider.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/index.d.ts +0 -1
- package/dist/typescript/src/lib/Components/index.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/lib/Components/AmountInput/AmountInput.mdx +12 -0
- package/src/lib/Components/AmountInput/AmountInput.stories.tsx +68 -1
- package/src/lib/Components/AmountInput/AmountInput.tsx +118 -75
- package/src/lib/Components/AmountInput/types.ts +14 -0
- package/src/lib/Components/Avatar/Avatar.mdx +2 -0
- package/src/lib/Components/Avatar/Avatar.test.tsx +16 -18
- package/src/lib/Components/Avatar/Avatar.tsx +9 -8
- package/src/lib/Components/DotIcon/DotIcon.stories.tsx +8 -0
- package/src/lib/Components/DotIcon/DotIcon.tsx +4 -1
- package/src/lib/Components/DotIcon/types.ts +1 -1
- package/src/lib/Components/DotIndicator/DotIndicator.mdx +4 -4
- package/src/lib/Components/DotIndicator/DotIndicator.stories.tsx +2 -2
- package/src/lib/Components/DotIndicator/DotIndicator.test.tsx +12 -2
- package/src/lib/Components/DotIndicator/DotIndicator.tsx +5 -5
- package/src/lib/Components/DotIndicator/types.ts +2 -2
- package/src/lib/Components/DotSymbol/DotSymbol.stories.tsx +15 -0
- package/src/lib/Components/DotSymbol/DotSymbol.tsx +4 -1
- package/src/lib/Components/DotSymbol/types.ts +1 -1
- package/src/lib/Components/Label/Label.tsx +1 -1
- package/src/lib/Components/MediaButton/MediaButton.mdx +2 -2
- package/src/lib/Components/MediaButton/MediaButton.tsx +2 -2
- package/src/lib/Components/MediaImage/MediaImage.mdx +1 -1
- package/src/lib/Components/MediaImage/MediaImage.stories.tsx +3 -0
- package/src/lib/Components/MediaImage/MediaImage.tsx +2 -0
- package/src/lib/Components/MediaImage/types.ts +1 -1
- package/src/lib/Components/OptionList/OptionList.mdx +1 -1
- package/src/lib/Components/ThemeProvider/ThemeProvider.tsx +1 -4
- package/src/lib/Components/index.ts +0 -1
- package/src/lib/Symbols/Icons/Lightbulb.tsx +3 -3
- package/dist/module/lib/Components/Select/GlobalSelectBottomSheet.js +0 -155
- package/dist/module/lib/Components/Select/GlobalSelectBottomSheet.js.map +0 -1
- package/dist/module/lib/Components/Select/GlobalSelectContext.js +0 -78
- package/dist/module/lib/Components/Select/GlobalSelectContext.js.map +0 -1
- package/dist/module/lib/Components/Select/Select.js +0 -366
- package/dist/module/lib/Components/Select/Select.js.map +0 -1
- package/dist/module/lib/Components/Select/Select.mdx +0 -596
- package/dist/module/lib/Components/Select/Select.stories.js +0 -304
- package/dist/module/lib/Components/Select/Select.stories.js.map +0 -1
- package/dist/module/lib/Components/Select/Select.test.js +0 -123
- package/dist/module/lib/Components/Select/Select.test.js.map +0 -1
- package/dist/module/lib/Components/Select/SelectContext.js +0 -38
- package/dist/module/lib/Components/Select/SelectContext.js.map +0 -1
- package/dist/module/lib/Components/Select/index.js +0 -6
- package/dist/module/lib/Components/Select/index.js.map +0 -1
- package/dist/module/lib/Components/Select/types.js +0 -4
- package/dist/module/lib/Components/Select/types.js.map +0 -1
- package/dist/typescript/src/lib/Components/Select/GlobalSelectBottomSheet.d.ts +0 -20
- package/dist/typescript/src/lib/Components/Select/GlobalSelectBottomSheet.d.ts.map +0 -1
- package/dist/typescript/src/lib/Components/Select/GlobalSelectContext.d.ts +0 -44
- package/dist/typescript/src/lib/Components/Select/GlobalSelectContext.d.ts.map +0 -1
- package/dist/typescript/src/lib/Components/Select/Select.d.ts +0 -52
- package/dist/typescript/src/lib/Components/Select/Select.d.ts.map +0 -1
- package/dist/typescript/src/lib/Components/Select/SelectContext.d.ts +0 -36
- package/dist/typescript/src/lib/Components/Select/SelectContext.d.ts.map +0 -1
- package/dist/typescript/src/lib/Components/Select/index.d.ts +0 -4
- package/dist/typescript/src/lib/Components/Select/index.d.ts.map +0 -1
- package/dist/typescript/src/lib/Components/Select/types.d.ts +0 -130
- package/dist/typescript/src/lib/Components/Select/types.d.ts.map +0 -1
- package/src/lib/Components/Select/GlobalSelectBottomSheet.tsx +0 -180
- package/src/lib/Components/Select/GlobalSelectContext.tsx +0 -103
- package/src/lib/Components/Select/Select.mdx +0 -596
- package/src/lib/Components/Select/Select.stories.tsx +0 -266
- package/src/lib/Components/Select/Select.test.tsx +0 -117
- package/src/lib/Components/Select/Select.tsx +0 -469
- package/src/lib/Components/Select/SelectContext.tsx +0 -68
- package/src/lib/Components/Select/index.ts +0 -3
- 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>
|