react-native-platform-components 0.9.0 → 1.1.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.
- package/README.md +73 -1011
- package/android/src/main/java/com/platformcomponents/PCDatePickerView.kt +17 -3
- package/android/src/main/java/com/platformcomponents/PCSegmentedControlView.kt +5 -3
- package/android/src/main/java/com/platformcomponents/PCSelectionMenuView.kt +2 -1
- package/android/src/main/java/com/platformcomponents/PCThemeSupport.kt +94 -0
- package/android/src/main/res/values/styles.xml +40 -0
- package/lib/typescript/commonjs/docs/docusaurus.config.d.ts +4 -0
- package/lib/typescript/commonjs/docs/docusaurus.config.d.ts.map +1 -0
- package/lib/typescript/commonjs/docs/sidebars.d.ts +4 -0
- package/lib/typescript/commonjs/docs/sidebars.d.ts.map +1 -0
- package/lib/typescript/module/docs/docusaurus.config.d.ts +4 -0
- package/lib/typescript/module/docs/docusaurus.config.d.ts.map +1 -0
- package/lib/typescript/module/docs/sidebars.d.ts +4 -0
- package/lib/typescript/module/docs/sidebars.d.ts.map +1 -0
- package/package.json +34 -13
- package/plugin/build/index.cjs +58 -17
- package/plugin/build/index.d.ts +32 -15
- package/plugin/build/index.d.ts.map +1 -1
- package/plugin/tsconfig.json +7 -2
package/README.md
CHANGED
|
@@ -2,973 +2,94 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/react-native-platform-components)
|
|
4
4
|
[](https://www.npmjs.com/package/react-native-platform-components)
|
|
5
|
+
[](https://github.com/JarX-Concepts/react-native-platform-components/actions/workflows/ci.yml)
|
|
6
|
+
[](./LICENSE)
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
This library focuses on **true native behavior**, not JavaScript re-implementations.
|
|
9
|
-
|
|
10
|
-
**Have a component request?** If there's a native UI component you'd like to see added, [open an issue](https://github.com/JarX-Concepts/react-native-platform-components/issues/new) describing the component and its native APIs on iOS and Android.
|
|
8
|
+
Native **DatePicker**, **ContextMenu**, **SelectionMenu**, **SegmentedControl** and **LiquidGlass** for React Native. Every component is the real platform widget on both iOS and Android (UIKit and SwiftUI on iOS, Material 3 on Android), behind one typed, declarative API. No JavaScript re-implementations.
|
|
11
9
|
|
|
12
10
|
<table>
|
|
13
11
|
<tr>
|
|
14
|
-
<td align="center"><
|
|
15
|
-
<td align="center"><
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<td><
|
|
19
|
-
<td><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/android-datepicker.gif" height="550" /></td>
|
|
20
|
-
</tr>
|
|
21
|
-
<tr>
|
|
22
|
-
<td align="center"><strong>iOS ContextMenu</strong></td>
|
|
23
|
-
<td align="center"><strong>Android ContextMenu</strong></td>
|
|
24
|
-
</tr>
|
|
25
|
-
<tr>
|
|
26
|
-
<td><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/ios-contextmenu.gif" height="550" /></td>
|
|
27
|
-
<td><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/android-contextmenu.gif" height="550" /></td>
|
|
28
|
-
</tr>
|
|
29
|
-
<tr>
|
|
30
|
-
<td align="center"><strong>iOS SelectionMenu</strong></td>
|
|
31
|
-
<td align="center"><strong>Android SelectionMenu</strong></td>
|
|
32
|
-
</tr>
|
|
33
|
-
<tr>
|
|
34
|
-
<td><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/ios-selectionmenu.gif" height="550" /></td>
|
|
35
|
-
<td><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/android-selectionmenu.gif" height="550" /></td>
|
|
36
|
-
</tr>
|
|
37
|
-
<tr>
|
|
38
|
-
<td align="center"><strong>iOS SegmentedControl</strong></td>
|
|
39
|
-
<td align="center"><strong>Android SegmentedControl</strong></td>
|
|
12
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/datepicker">DatePicker</a></td>
|
|
13
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/contextmenu">ContextMenu</a></td>
|
|
14
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/selectionmenu">SelectionMenu</a></td>
|
|
15
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/segmentedcontrol">SegmentedControl</a></td>
|
|
16
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/liquidglass">LiquidGlass</a></td>
|
|
40
17
|
</tr>
|
|
41
18
|
<tr>
|
|
42
|
-
<td><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/ios-
|
|
43
|
-
<td><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/
|
|
19
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/datepicker"><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/ios-datepicker.gif" width="120" alt="DatePicker on iOS" /></a></td>
|
|
20
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/contextmenu"><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/ios-contextmenu.gif" width="120" alt="ContextMenu on iOS" /></a></td>
|
|
21
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/selectionmenu"><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/ios-selectionmenu.gif" width="120" alt="SelectionMenu on iOS" /></a></td>
|
|
22
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/segmentedcontrol"><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/ios-segmentedcontrol.gif" width="120" alt="SegmentedControl on iOS" /></a></td>
|
|
23
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/liquidglass"><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/ios-liquidglass.gif" width="120" alt="LiquidGlass on iOS" /></a></td>
|
|
44
24
|
</tr>
|
|
45
25
|
<tr>
|
|
46
|
-
<td align="center"><
|
|
47
|
-
<td align="center"><
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<td
|
|
51
|
-
<td align="center"><em>iOS 26+ only</em><br/><br/>On Android, renders as a<br/>regular View with optional<br/>fallback background color.</td>
|
|
26
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/datepicker"><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/android-datepicker.gif" width="120" alt="DatePicker on Android" /></a></td>
|
|
27
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/contextmenu"><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/android-contextmenu.gif" width="120" alt="ContextMenu on Android" /></a></td>
|
|
28
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/selectionmenu"><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/android-selectionmenu.gif" width="120" alt="SelectionMenu on Android" /></a></td>
|
|
29
|
+
<td align="center"><a href="https://jarx-concepts.github.io/react-native-platform-components/components/segmentedcontrol"><img src="https://raw.githubusercontent.com/JarX-Concepts/react-native-platform-components/main/assets/android-segmentedcontrol.gif" width="120" alt="SegmentedControl on Android" /></a></td>
|
|
30
|
+
<td align="center" valign="middle"><sub>iOS 26+ only.<br/>Plain View on Android.</sub></td>
|
|
52
31
|
</tr>
|
|
53
32
|
</table>
|
|
54
33
|
|
|
55
|
-
### Components
|
|
56
|
-
|
|
57
|
-
- **DatePicker** – native date & time pickers with modal and embedded presentations
|
|
58
|
-
- **ContextMenu** – native context menus with long-press activation (UIContextMenuInteraction on iOS, PopupMenu on Android)
|
|
59
|
-
- **SelectionMenu** – native selection menus (Material on Android, system menus on iOS)
|
|
60
|
-
- **SegmentedControl** – native segmented controls (UISegmentedControl on iOS, MaterialButtonToggleGroup on Android)
|
|
61
|
-
- **LiquidGlass** – iOS 26+ glass morphism effects (UIGlassEffect on iOS, fallback View on Android)
|
|
62
|
-
|
|
63
|
-
### Goals
|
|
64
|
-
|
|
65
|
-
- Feel **100% native** on each platform
|
|
66
|
-
- Support modern platform design systems (Material 3 on Android, system pickers on iOS)
|
|
67
|
-
- Offer **headless** and **inline** modes for maximum layout control
|
|
68
|
-
- Integrate cleanly with **React Native Codegen / Fabric**
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
## Installation
|
|
73
|
-
|
|
74
34
|
```sh
|
|
75
35
|
npm install react-native-platform-components
|
|
76
|
-
# or
|
|
77
|
-
yarn add react-native-platform-components
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### iOS
|
|
81
|
-
|
|
82
|
-
```sh
|
|
83
|
-
cd ios
|
|
84
|
-
pod install
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
- Minimum iOS version: **iOS 13+**
|
|
88
|
-
- Uses `UIDatePicker`, SwiftUI Menu, and `UIContextMenuInteraction`
|
|
89
|
-
|
|
90
|
-
### Android
|
|
91
|
-
|
|
92
|
-
- Uses native Android Views with Material Design (including `PopupMenu` for context menus)
|
|
93
|
-
- Supports **Material 3** styling
|
|
94
|
-
- **⚠️ Your app may crash if theme is not configured** — See [Android Theme Configuration](#android-theme-configuration) below
|
|
95
|
-
|
|
96
|
-
### Expo (Managed Workflow)
|
|
97
|
-
|
|
98
|
-
> **Note:** This library is **not supported in Expo Go**. It requires native code and must be used with [Expo Dev Client](https://docs.expo.dev/develop/development-builds/introduction/) or EAS Build.
|
|
99
|
-
|
|
100
|
-
```sh
|
|
101
|
-
npx expo install react-native-platform-components
|
|
102
|
-
npx expo prebuild
|
|
103
|
-
npx expo run:ios
|
|
104
|
-
# or
|
|
105
|
-
npx expo run:android
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
The library includes an Expo config plugin that handles all native configuration automatically. No manual native setup is required.
|
|
109
|
-
|
|
110
|
-
**EAS Build:**
|
|
111
|
-
|
|
112
|
-
```sh
|
|
113
|
-
eas build --platform ios
|
|
114
|
-
eas build --platform android
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
**Config Plugin:**
|
|
118
|
-
|
|
119
|
-
Add to your `app.json`:
|
|
120
|
-
|
|
121
|
-
```json
|
|
122
|
-
{
|
|
123
|
-
"expo": {
|
|
124
|
-
"plugins": [["react-native-platform-components/app.plugin", {}]]
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
For a complete working example, see the [`example-expo/`](./example-expo) directory.
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
## React Native New Architecture
|
|
134
|
-
|
|
135
|
-
This library is built for the **React Native New Architecture** (Fabric + TurboModules).
|
|
136
|
-
|
|
137
|
-
| Feature | Status |
|
|
138
|
-
| --------------------- | ---------------------------------- |
|
|
139
|
-
| Fabric (New Renderer) | Supported |
|
|
140
|
-
| Codegen | Used for type-safe native bindings |
|
|
141
|
-
| TurboModules | N/A (view components only) |
|
|
142
|
-
| Old Architecture | Not supported |
|
|
143
|
-
|
|
144
|
-
**Tested with:**
|
|
145
|
-
|
|
146
|
-
- React Native 0.81+ (bare and Expo)
|
|
147
|
-
- Expo SDK 54+
|
|
148
|
-
|
|
149
|
-
**Requirements:**
|
|
150
|
-
|
|
151
|
-
- New Architecture must be enabled in your app
|
|
152
|
-
- For bare React Native: set `newArchEnabled=true` in `gradle.properties` (Android) and use the `RCT_NEW_ARCH_ENABLED` flag (iOS)
|
|
153
|
-
- For Expo: set `"newArchEnabled": true` in `app.json`
|
|
154
|
-
|
|
155
|
-
---
|
|
156
|
-
|
|
157
|
-
## Quick Start
|
|
158
|
-
|
|
159
|
-
### DatePicker (Modal)
|
|
160
|
-
|
|
161
|
-
```tsx
|
|
162
|
-
import { DatePicker } from 'react-native-platform-components';
|
|
163
|
-
|
|
164
|
-
export function Example() {
|
|
165
|
-
const [date, setDate] = React.useState<Date | null>(null);
|
|
166
|
-
const [visible, setVisible] = React.useState(false);
|
|
167
|
-
|
|
168
|
-
return (
|
|
169
|
-
<>
|
|
170
|
-
<Button title="Pick date" onPress={() => setVisible(true)} />
|
|
171
|
-
|
|
172
|
-
<DatePicker
|
|
173
|
-
date={date}
|
|
174
|
-
visible={visible}
|
|
175
|
-
presentation="modal"
|
|
176
|
-
mode="date"
|
|
177
|
-
onConfirm={(d, confirmed) => {
|
|
178
|
-
setDate(d);
|
|
179
|
-
if (confirmed) setVisible(false);
|
|
180
|
-
}}
|
|
181
|
-
onClosed={() => setVisible(false)}
|
|
182
|
-
ios={{ preferredStyle: 'inline' }}
|
|
183
|
-
android={{ material: 'system' }}
|
|
184
|
-
/>
|
|
185
|
-
</>
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### DatePicker (Embedded)
|
|
191
|
-
|
|
192
|
-
```tsx
|
|
193
|
-
import { DatePicker } from 'react-native-platform-components';
|
|
194
|
-
|
|
195
|
-
export function Example() {
|
|
196
|
-
const [date, setDate] = React.useState<Date | null>(new Date());
|
|
197
|
-
|
|
198
|
-
return (
|
|
199
|
-
<DatePicker
|
|
200
|
-
date={date}
|
|
201
|
-
presentation="embedded"
|
|
202
|
-
mode="date"
|
|
203
|
-
onConfirm={(d, confirmed) => setDate(d)}
|
|
204
|
-
ios={{ preferredStyle: 'inline' }}
|
|
205
|
-
android={{ material: 'system' }}
|
|
206
|
-
/>
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
---
|
|
212
|
-
|
|
213
|
-
### ContextMenu (Gesture Mode)
|
|
214
|
-
|
|
215
|
-
```tsx
|
|
216
|
-
import { ContextMenu } from 'react-native-platform-components';
|
|
217
|
-
import { Platform, View, Text } from 'react-native';
|
|
218
|
-
|
|
219
|
-
export function Example() {
|
|
220
|
-
const [lastAction, setLastAction] = React.useState<string | null>(null);
|
|
221
|
-
|
|
222
|
-
return (
|
|
223
|
-
<ContextMenu
|
|
224
|
-
title="Options"
|
|
225
|
-
actions={[
|
|
226
|
-
{
|
|
227
|
-
id: 'copy',
|
|
228
|
-
title: 'Copy',
|
|
229
|
-
image: Platform.OS === 'ios' ? 'doc.on.doc' : 'content_copy',
|
|
230
|
-
},
|
|
231
|
-
{
|
|
232
|
-
id: 'share',
|
|
233
|
-
title: 'Share',
|
|
234
|
-
image: Platform.OS === 'ios' ? 'square.and.arrow.up' : 'share',
|
|
235
|
-
},
|
|
236
|
-
{
|
|
237
|
-
id: 'delete',
|
|
238
|
-
title: 'Delete',
|
|
239
|
-
image: Platform.OS === 'ios' ? 'trash' : 'delete',
|
|
240
|
-
attributes: { destructive: true },
|
|
241
|
-
},
|
|
242
|
-
]}
|
|
243
|
-
onPressAction={(id, title) => setLastAction(title)}
|
|
244
|
-
>
|
|
245
|
-
<View
|
|
246
|
-
style={{ padding: 20, backgroundColor: '#E8F4FD', borderRadius: 8 }}
|
|
247
|
-
>
|
|
248
|
-
<Text>Long-press me</Text>
|
|
249
|
-
</View>
|
|
250
|
-
</ContextMenu>
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### ContextMenu (Modal Mode)
|
|
256
|
-
|
|
257
|
-
```tsx
|
|
258
|
-
import { ContextMenu } from 'react-native-platform-components';
|
|
259
|
-
import { View, Text } from 'react-native';
|
|
260
|
-
|
|
261
|
-
export function Example() {
|
|
262
|
-
return (
|
|
263
|
-
<ContextMenu
|
|
264
|
-
title="Actions"
|
|
265
|
-
actions={[
|
|
266
|
-
{ id: 'edit', title: 'Edit' },
|
|
267
|
-
{ id: 'duplicate', title: 'Duplicate' },
|
|
268
|
-
{ id: 'delete', title: 'Delete', attributes: { destructive: true } },
|
|
269
|
-
]}
|
|
270
|
-
trigger="tap" // or "longPress" (default)
|
|
271
|
-
onPressAction={(id) => console.log('Selected:', id)}
|
|
272
|
-
>
|
|
273
|
-
<View style={{ padding: 16, backgroundColor: '#eee' }}>
|
|
274
|
-
<Text>Tap or long-press me</Text>
|
|
275
|
-
</View>
|
|
276
|
-
</ContextMenu>
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
36
|
```
|
|
280
37
|
|
|
281
|
-
---
|
|
282
|
-
|
|
283
|
-
### SelectionMenu (Headless)
|
|
284
|
-
|
|
285
|
-
```tsx
|
|
286
|
-
import { SelectionMenu } from 'react-native-platform-components';
|
|
287
|
-
|
|
288
|
-
const options = [
|
|
289
|
-
{ label: 'Apple', data: 'apple' },
|
|
290
|
-
{ label: 'Banana', data: 'banana' },
|
|
291
|
-
{ label: 'Orange', data: 'orange' },
|
|
292
|
-
];
|
|
293
|
-
|
|
294
|
-
export function Example() {
|
|
295
|
-
const [visible, setVisible] = React.useState(false);
|
|
296
|
-
const [value, setValue] = React.useState<string | null>(null);
|
|
297
|
-
|
|
298
|
-
return (
|
|
299
|
-
<>
|
|
300
|
-
<Button title="Open menu" onPress={() => setVisible(true)} />
|
|
301
|
-
|
|
302
|
-
<SelectionMenu
|
|
303
|
-
options={options}
|
|
304
|
-
selected={value}
|
|
305
|
-
visible={visible}
|
|
306
|
-
onSelect={(data) => {
|
|
307
|
-
setValue(data);
|
|
308
|
-
setVisible(false);
|
|
309
|
-
}}
|
|
310
|
-
onRequestClose={() => setVisible(false)}
|
|
311
|
-
/>
|
|
312
|
-
</>
|
|
313
|
-
);
|
|
314
|
-
}
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
### SelectionMenu (Inline)
|
|
318
|
-
|
|
319
|
-
```tsx
|
|
320
|
-
import { SelectionMenu } from 'react-native-platform-components';
|
|
321
|
-
|
|
322
|
-
const options = [
|
|
323
|
-
{ label: 'Apple', data: 'apple' },
|
|
324
|
-
{ label: 'Banana', data: 'banana' },
|
|
325
|
-
{ label: 'Orange', data: 'orange' },
|
|
326
|
-
];
|
|
327
|
-
|
|
328
|
-
export function Example() {
|
|
329
|
-
const [value, setValue] = React.useState<string | null>(null);
|
|
330
|
-
|
|
331
|
-
return (
|
|
332
|
-
<SelectionMenu
|
|
333
|
-
options={options}
|
|
334
|
-
selected={value}
|
|
335
|
-
presentation="embedded"
|
|
336
|
-
placeholder="Select fruit"
|
|
337
|
-
onSelect={(data) => setValue(data)}
|
|
338
|
-
android={{ material: 'm3' }}
|
|
339
|
-
/>
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
---
|
|
345
|
-
|
|
346
|
-
### SegmentedControl
|
|
347
|
-
|
|
348
|
-
```tsx
|
|
349
|
-
import { SegmentedControl } from 'react-native-platform-components';
|
|
350
|
-
|
|
351
|
-
const segments = [
|
|
352
|
-
{ label: 'Day', value: 'day' },
|
|
353
|
-
{ label: 'Week', value: 'week' },
|
|
354
|
-
{ label: 'Month', value: 'month' },
|
|
355
|
-
];
|
|
356
|
-
|
|
357
|
-
export function Example() {
|
|
358
|
-
const [selected, setSelected] = React.useState('day');
|
|
359
|
-
|
|
360
|
-
return (
|
|
361
|
-
<SegmentedControl
|
|
362
|
-
segments={segments}
|
|
363
|
-
selectedValue={selected}
|
|
364
|
-
onSelect={(value) => setSelected(value)}
|
|
365
|
-
/>
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
### SegmentedControl (With Icons)
|
|
371
|
-
|
|
372
38
|
```tsx
|
|
373
39
|
import { SegmentedControl } from 'react-native-platform-components';
|
|
374
40
|
|
|
375
|
-
const segments = [
|
|
376
|
-
{
|
|
377
|
-
label: 'List',
|
|
378
|
-
value: 'list',
|
|
379
|
-
// Native symbol on each platform, no Platform.OS branching
|
|
380
|
-
icon: {
|
|
381
|
-
ios: { type: 'sfSymbol', name: 'list.bullet' },
|
|
382
|
-
android: { type: 'drawable', name: 'list_bullet' },
|
|
383
|
-
},
|
|
384
|
-
},
|
|
385
|
-
{
|
|
386
|
-
label: 'Alerts',
|
|
387
|
-
value: 'alerts',
|
|
388
|
-
// One image asset shared by both platforms, tinted like a template
|
|
389
|
-
icon: { type: 'image', source: require('./bell.png') },
|
|
390
|
-
},
|
|
391
|
-
];
|
|
392
|
-
|
|
393
|
-
export function Example() {
|
|
394
|
-
const [selected, setSelected] = React.useState('list');
|
|
395
|
-
|
|
396
|
-
return (
|
|
397
|
-
<SegmentedControl
|
|
398
|
-
segments={segments}
|
|
399
|
-
selectedValue={selected}
|
|
400
|
-
onSelect={(value) => setSelected(value)}
|
|
401
|
-
// 'auto' | 'labeled' | 'unlabeled'
|
|
402
|
-
labelVisibility="auto"
|
|
403
|
-
ios={{ apportionsSegmentWidthsByContent: true }}
|
|
404
|
-
/>
|
|
405
|
-
);
|
|
406
|
-
}
|
|
407
|
-
```
|
|
408
|
-
|
|
409
|
-
---
|
|
410
|
-
|
|
411
|
-
### LiquidGlass
|
|
412
|
-
|
|
413
|
-
```tsx
|
|
414
|
-
import {
|
|
415
|
-
LiquidGlass,
|
|
416
|
-
isLiquidGlassSupported,
|
|
417
|
-
} from 'react-native-platform-components';
|
|
418
|
-
import { View, Text, Image } from 'react-native';
|
|
419
|
-
|
|
420
|
-
export function Example() {
|
|
421
|
-
return (
|
|
422
|
-
<View style={{ flex: 1 }}>
|
|
423
|
-
{/* Background content */}
|
|
424
|
-
<Image
|
|
425
|
-
source={{ uri: 'https://example.com/photo.jpg' }}
|
|
426
|
-
style={{ flex: 1 }}
|
|
427
|
-
/>
|
|
428
|
-
|
|
429
|
-
{/* Glass effect overlay */}
|
|
430
|
-
<LiquidGlass
|
|
431
|
-
style={{
|
|
432
|
-
position: 'absolute',
|
|
433
|
-
top: 50,
|
|
434
|
-
left: 20,
|
|
435
|
-
right: 20,
|
|
436
|
-
padding: 20,
|
|
437
|
-
}}
|
|
438
|
-
cornerRadius={20}
|
|
439
|
-
ios={{
|
|
440
|
-
effect: 'regular',
|
|
441
|
-
interactive: true,
|
|
442
|
-
colorScheme: 'system',
|
|
443
|
-
}}
|
|
444
|
-
android={{
|
|
445
|
-
fallbackBackgroundColor: '#FFFFFF80',
|
|
446
|
-
}}
|
|
447
|
-
>
|
|
448
|
-
<Text style={{ fontSize: 18, fontWeight: '600' }}>
|
|
449
|
-
{isLiquidGlassSupported ? 'Glass Effect!' : 'Fallback View'}
|
|
450
|
-
</Text>
|
|
451
|
-
</LiquidGlass>
|
|
452
|
-
</View>
|
|
453
|
-
);
|
|
454
|
-
}
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
---
|
|
458
|
-
|
|
459
|
-
## Components
|
|
460
|
-
|
|
461
|
-
## DatePicker
|
|
462
|
-
|
|
463
|
-
Native date & time picker using **platform system pickers**.
|
|
464
|
-
|
|
465
|
-
### Props
|
|
466
|
-
|
|
467
|
-
| Prop | Type | Description |
|
|
468
|
-
| -------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
469
|
-
| `date` | `Date \| null` | Controlled date value |
|
|
470
|
-
| `minDate` | `Date \| null` | Minimum selectable date |
|
|
471
|
-
| `maxDate` | `Date \| null` | Maximum selectable date |
|
|
472
|
-
| `locale` | `string` | Locale identifier (e.g., `'en-US'`) |
|
|
473
|
-
| `timeZoneName` | `string` | Time zone identifier |
|
|
474
|
-
| `mode` | `'date' \| 'time' \| 'dateAndTime' \| 'countDownTimer'` | Picker mode |
|
|
475
|
-
| `presentation` | `'modal' \| 'embedded'` | Presentation style |
|
|
476
|
-
| `visible` | `boolean` | Controls modal visibility (modal mode only) |
|
|
477
|
-
| `onConfirm` | `(date: Date, confirmed: boolean) => void` | Called on date change; `confirmed` is `true` for deliberate selections (see below) |
|
|
478
|
-
| `onClosed` | `() => void` | Called when modal is dismissed |
|
|
479
|
-
|
|
480
|
-
### iOS Props (`ios`)
|
|
481
|
-
|
|
482
|
-
| Prop | Type | Description |
|
|
483
|
-
| -------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------ |
|
|
484
|
-
| `preferredStyle` | `'automatic' \| 'compact' \| 'inline' \| 'wheels'` | iOS date picker style |
|
|
485
|
-
| `countDownDurationSeconds` | `number` | Duration for countdown timer mode |
|
|
486
|
-
| `minuteInterval` | `number` | Minute interval (1-30) |
|
|
487
|
-
| `roundsToMinuteInterval` | `'inherit' \| 'round' \| 'noRound'` | Rounding behavior |
|
|
488
|
-
| `showConfirmToolbar` | `boolean` | Modal only. Show Cancel/Done toolbar below the picker. Defaults to `true`. See below. |
|
|
489
|
-
|
|
490
|
-
### Android Props (`android`)
|
|
491
|
-
|
|
492
|
-
| Prop | Type | Description |
|
|
493
|
-
| --------------------- | ------------------ | ---------------------------------------------------------------------- |
|
|
494
|
-
| `firstDayOfWeek` | `number` | First day of week (1-7, Sunday=1) |
|
|
495
|
-
| `material` | `'system' \| 'm3'` | Material Design style (modal only; embedded always uses system picker) |
|
|
496
|
-
| `dialogTitle` | `string` | Custom dialog title |
|
|
497
|
-
| `positiveButtonTitle` | `string` | Custom confirm button text |
|
|
498
|
-
| `negativeButtonTitle` | `string` | Custom cancel button text |
|
|
499
|
-
|
|
500
|
-
### The `confirmed` Flag
|
|
501
|
-
|
|
502
|
-
`onConfirm` fires on every date/time change, but the second argument (`confirmed`) lets you distinguish between browsing and deliberate selections:
|
|
503
|
-
|
|
504
|
-
| Platform / Mode | Every change | Deliberate selection |
|
|
505
|
-
| -------------------- | ----------------------------------------- | ------------------------------------- |
|
|
506
|
-
| **iOS modal** | `confirmed: false` (user still adjusting) | `confirmed: true` (tapping **Done**) |
|
|
507
|
-
| **iOS embedded** | `confirmed: true` | — |
|
|
508
|
-
| **Android modal** | — | `confirmed: true` (pressing OK) |
|
|
509
|
-
| **Android embedded** | `confirmed: true` | — |
|
|
510
|
-
|
|
511
|
-
On iOS in modal presentation, the picker is shown in a popover with a Cancel/Done toolbar below it. Tapping **Done** emits `confirmed: true`; tapping **Cancel** or outside the popover calls `onClosed`. Set `ios.showConfirmToolbar: false` to hide the toolbar — in that mode `confirmed: true` never fires, and your app is expected to drive dismissal by flipping `visible` off (reading the current date from the stream of `confirmed: false` events). This only makes UX sense paired with `ios.preferredStyle: 'inline'`.
|
|
512
|
-
|
|
513
|
-
A common pattern is to close the modal only on a confirmed selection:
|
|
514
|
-
|
|
515
|
-
```tsx
|
|
516
|
-
<DatePicker
|
|
517
|
-
date={date}
|
|
518
|
-
visible={visible}
|
|
519
|
-
presentation="modal"
|
|
520
|
-
mode="time"
|
|
521
|
-
onConfirm={(d, confirmed) => {
|
|
522
|
-
setDate(d);
|
|
523
|
-
if (confirmed) setVisible(false);
|
|
524
|
-
}}
|
|
525
|
-
onClosed={() => setVisible(false)}
|
|
526
|
-
/>
|
|
527
|
-
```
|
|
528
|
-
|
|
529
|
-
---
|
|
530
|
-
|
|
531
|
-
## ContextMenu
|
|
532
|
-
|
|
533
|
-
Native context menu that wraps content and responds to **long-press** or **tap** gestures.
|
|
534
|
-
|
|
535
|
-
### Props
|
|
536
|
-
|
|
537
|
-
| Prop | Type | Description |
|
|
538
|
-
| --------------- | --------------------------------- | ------------------------------------------- |
|
|
539
|
-
| `title` | `string` | Menu title (shown as header on iOS) |
|
|
540
|
-
| `actions` | `ContextMenuAction[]` | Array of menu actions |
|
|
541
|
-
| `disabled` | `boolean` | Disables the menu |
|
|
542
|
-
| `trigger` | `'longPress' \| 'tap'` | How the menu opens (default: `'longPress'`) |
|
|
543
|
-
| `onPressAction` | `(actionId, actionTitle) => void` | Called when user selects an action |
|
|
544
|
-
| `onMenuOpen` | `() => void` | Called when menu opens |
|
|
545
|
-
| `onMenuClose` | `() => void` | Called when menu closes |
|
|
546
|
-
| `children` | `ReactNode` | Content to wrap (required) |
|
|
547
|
-
|
|
548
|
-
### ContextMenuAction
|
|
549
|
-
|
|
550
|
-
| Property | Type | Description |
|
|
551
|
-
| ------------ | -------------------------------------- | ------------------------------------------------- |
|
|
552
|
-
| `id` | `string` | Unique identifier returned in callbacks |
|
|
553
|
-
| `title` | `string` | Display text |
|
|
554
|
-
| `subtitle` | `string` | Secondary text (iOS only) |
|
|
555
|
-
| `image` | `string` | Icon name (SF Symbol on iOS, drawable on Android) |
|
|
556
|
-
| `imageColor` | `string` | Tint color for the icon (hex string) |
|
|
557
|
-
| `attributes` | `{ destructive?, disabled?, hidden? }` | Action attributes |
|
|
558
|
-
| `state` | `'off' \| 'on' \| 'mixed'` | Checkmark state |
|
|
559
|
-
| `subactions` | `ContextMenuAction[]` | Nested actions for submenu |
|
|
560
|
-
|
|
561
|
-
### iOS Props (`ios`)
|
|
562
|
-
|
|
563
|
-
| Prop | Type | Description |
|
|
564
|
-
| --------------- | --------- | --------------------------------- |
|
|
565
|
-
| `enablePreview` | `boolean` | Enable preview when long-pressing |
|
|
566
|
-
|
|
567
|
-
### Android Props (`android`)
|
|
568
|
-
|
|
569
|
-
| Prop | Type | Description |
|
|
570
|
-
| ---------------- | ------------------- | ---------------------------------------------- |
|
|
571
|
-
| `anchorPosition` | `'left' \| 'right'` | Anchor position for the popup menu |
|
|
572
|
-
| `visible` | `boolean` | Programmatic visibility control (Android only) |
|
|
573
|
-
|
|
574
|
-
### Trigger Modes
|
|
575
|
-
|
|
576
|
-
- **Long-Press** (default): Long-press on wrapped content triggers the menu.
|
|
577
|
-
- **Tap** (`trigger="tap"`): Single tap on wrapped content triggers the menu.
|
|
578
|
-
- **Programmatic** (Android only): Use `android.visible` to control menu visibility programmatically. iOS does not support programmatic menu opening due to platform limitations.
|
|
579
|
-
|
|
580
|
-
### Icon Support
|
|
581
|
-
|
|
582
|
-
- **iOS**: Use SF Symbol names (e.g., `'trash'`, `'square.and.arrow.up'`, `'doc.on.doc'`)
|
|
583
|
-
- **Android**: Use drawable resource names or Material icon names
|
|
584
|
-
|
|
585
|
-
---
|
|
586
|
-
|
|
587
|
-
## SelectionMenu
|
|
588
|
-
|
|
589
|
-
Native selection menu with **modal** and **embedded** modes.
|
|
590
|
-
|
|
591
|
-
### Props
|
|
592
|
-
|
|
593
|
-
| Prop | Type | Description |
|
|
594
|
-
| ------------------ | ----------------------------------- | ----------------------------------------------- |
|
|
595
|
-
| `options` | `{ label: string; data: string }[]` | Array of options to display |
|
|
596
|
-
| `selected` | `string \| null` | Currently selected option's `data` value |
|
|
597
|
-
| `disabled` | `boolean` | Disables the menu |
|
|
598
|
-
| `placeholder` | `string` | Placeholder text when no selection |
|
|
599
|
-
| `presentation` | `'modal' \| 'embedded'` | Presentation mode (default: `'modal'`) |
|
|
600
|
-
| `visible` | `boolean` | Controls modal mode menu visibility |
|
|
601
|
-
| `onSelect` | `(data, label, index) => void` | Called when user selects an option |
|
|
602
|
-
| `onRequestClose` | `() => void` | Called when menu is dismissed without selection |
|
|
603
|
-
| `android.material` | `'system' \| 'm3'` | Material Design style preference |
|
|
604
|
-
|
|
605
|
-
### Modes
|
|
606
|
-
|
|
607
|
-
- **Modal mode** (default): Menu visibility controlled by `visible` prop. Use for custom trigger UI.
|
|
608
|
-
- **Embedded mode** (`presentation="embedded"`): Native picker UI rendered inline. Menu managed internally.
|
|
609
|
-
|
|
610
|
-
> **Note:** On iOS, modal mode uses a custom popover to enable programmatic presentation. For the full native menu experience (system animations, scroll physics), use embedded mode. This is an intentional trade-off: modal gives you control over the trigger UI, embedded gives you the complete system menu behavior.
|
|
611
|
-
|
|
612
|
-
---
|
|
613
|
-
|
|
614
|
-
## SegmentedControl
|
|
615
|
-
|
|
616
|
-
Native segmented control using **UISegmentedControl** on iOS and **MaterialButtonToggleGroup** on Android.
|
|
617
|
-
|
|
618
|
-
### Props
|
|
619
|
-
|
|
620
|
-
| Prop | Type | Description |
|
|
621
|
-
| ----------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
622
|
-
| `segments` | `SegmentedControlSegment[]` | Array of segments to display |
|
|
623
|
-
| `selectedValue` | `string \| null` | Currently selected segment's `value` |
|
|
624
|
-
| `disabled` | `boolean` | Disables the entire control |
|
|
625
|
-
| `labelVisibility` | `'auto' \| 'labeled' \| 'unlabeled'` | How labels and icons combine. See [Label visibility](#label-visibility). Default: `'auto'` |
|
|
626
|
-
| `selectedSegmentColor` | `ColorValue` | Background of the selected segment |
|
|
627
|
-
| `activeTintColor` | `ColorValue` | Text and icon color of the selected segment |
|
|
628
|
-
| `inactiveTintColor` | `ColorValue` | Text and icon color of unselected segments |
|
|
629
|
-
| `labelStyle` | `{ fontFamily?, fontSize?, fontWeight?, fontStyle? }` | Font for segment labels. See [Styling](#styling) |
|
|
630
|
-
| `badgeStyle` | `{ backgroundColor?, color? }` | Colors for segment badges. See [Badges](#badges) |
|
|
631
|
-
| `onSelect` | `(value: string, index: number) => void` | Called when user selects a segment |
|
|
632
|
-
| `onDeselect` | `() => void` | Called when the user clears the selection by tapping the selected segment. Android only; requires `android.selectionRequired: false` |
|
|
633
|
-
|
|
634
|
-
### SegmentedControlSegment
|
|
635
|
-
|
|
636
|
-
| Property | Type | Description |
|
|
637
|
-
| -------------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
638
|
-
| `label` | `string` | Display text for the segment |
|
|
639
|
-
| `value` | `string` | Unique value returned in callbacks |
|
|
640
|
-
| `disabled` | `boolean` | Disables this specific segment |
|
|
641
|
-
| `icon` | `SegmentedControlIcon` | Optional icon. See [Icon Support](#icon-support-1) |
|
|
642
|
-
| `badge` | `string \| number` | Badge at the segment's top-right corner, e.g. an unread count. See [Badges](#badges) |
|
|
643
|
-
| `accessibilityLabel` | `string` | Screen-reader label. Defaults to `label`. On iOS it applies to icon segments; text segments announce their title |
|
|
644
|
-
|
|
645
|
-
### iOS Props (`ios`)
|
|
646
|
-
|
|
647
|
-
| Prop | Type | Description |
|
|
648
|
-
| ---------------------------------- | --------- | --------------------------------------------------------------------------- |
|
|
649
|
-
| `momentary` | `boolean` | If true, segments don't show selected state |
|
|
650
|
-
| `apportionsSegmentWidthsByContent` | `boolean` | If true, segment widths are proportional to content |
|
|
651
|
-
| `selectedSegmentTintColor` | `string` | **Deprecated.** Use `selectedSegmentColor`, which works on both platforms. |
|
|
652
|
-
|
|
653
|
-
### Android Props (`android`)
|
|
654
|
-
|
|
655
|
-
| Prop | Type | Description |
|
|
656
|
-
| ------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
657
|
-
| `selectionRequired` | `boolean` | If true (default), one segment must always be selected. Set to `false` to let a tap on the selected segment clear it and fire `onDeselect`. |
|
|
658
|
-
| `rippleColor` | `ColorValue` | Ripple shown while pressing a segment |
|
|
659
|
-
| `strokeColor` | `ColorValue` | Outline color of the segments |
|
|
660
|
-
|
|
661
|
-
### Icon Support
|
|
662
|
-
|
|
663
|
-
`icon` accepts a single source, or an `{ ios, android }` pair so you never branch on `Platform.OS`:
|
|
664
|
-
|
|
665
|
-
| Shape | iOS | Android |
|
|
666
|
-
| ------------------------------------------- | ----------------------------------- | --------------------------------------------- |
|
|
667
|
-
| `'name'` (string) | SF Symbol name | Drawable resource name |
|
|
668
|
-
| `{ type: 'sfSymbol', name }` | SF Symbol | Ignored (segment shows its label) |
|
|
669
|
-
| `{ type: 'drawable', name }` | Ignored (segment shows its label) | Drawable from `res/drawable` |
|
|
670
|
-
| `{ type: 'image', source, tinted? }` | Image asset or `{ uri }` | Image asset or `{ uri }` |
|
|
671
|
-
| `{ ios: <source>, android: <source> }` | Uses `ios` | Uses `android` |
|
|
672
|
-
|
|
673
|
-
```tsx
|
|
674
|
-
// A bundled asset works everywhere and is tinted like a template.
|
|
675
|
-
icon: { type: 'image', source: require('./icons/bell.png') }
|
|
676
|
-
|
|
677
|
-
// Keep the original colors of a full-color image.
|
|
678
|
-
icon: { type: 'image', source: require('./icons/logo.png'), tinted: false }
|
|
679
|
-
|
|
680
|
-
// Remote images load asynchronously; pass `scale` for @2x/@3x artwork.
|
|
681
|
-
icon: { type: 'image', source: { uri: 'https://example.com/icon@2x.png', scale: 2 } }
|
|
682
|
-
```
|
|
683
|
-
|
|
684
|
-
Image icons render at their point size, so ship `@2x` / `@3x` variants sized around 18–22 points. Local assets load synchronously in release builds; in development they stream from Metro and the segment shows its label until the image arrives.
|
|
685
|
-
|
|
686
|
-
### Label visibility
|
|
687
|
-
|
|
688
|
-
`UISegmentedControl` shows either a title or an image per segment, while Material buttons can show both. `labelVisibility` makes the outcome predictable:
|
|
689
|
-
|
|
690
|
-
| Value | iOS | Android |
|
|
691
|
-
| --------------------- | ------------------------------------------ | -------------------------- |
|
|
692
|
-
| `'auto'` (default) | Icon when the segment has one, else label | Icon and label |
|
|
693
|
-
| `'labeled'` | Label only (icon is not shown) | Icon and label |
|
|
694
|
-
| `'unlabeled'` | Icon when the segment has one, else label | Icon only, else label |
|
|
695
|
-
|
|
696
|
-
Screen readers announce the label (or `accessibilityLabel`) in every mode on both platforms.
|
|
697
|
-
|
|
698
|
-
### Styling
|
|
699
|
-
|
|
700
|
-
Colors take any React Native `ColorValue` (hex, `rgba()`, named colors, `PlatformColor`, `DynamicColorIOS`). Fonts follow the `Text` style conventions, and each field falls back to the platform default.
|
|
701
|
-
|
|
702
|
-
```tsx
|
|
703
|
-
<SegmentedControl
|
|
704
|
-
segments={segments}
|
|
705
|
-
selectedValue={selected}
|
|
706
|
-
onSelect={setSelected}
|
|
707
|
-
selectedSegmentColor="#FF6B35"
|
|
708
|
-
activeTintColor="white"
|
|
709
|
-
inactiveTintColor="#8E8E93"
|
|
710
|
-
labelStyle={{ fontWeight: '700', fontSize: 14 }}
|
|
711
|
-
android={{ rippleColor: 'rgba(255, 107, 53, 0.25)', strokeColor: '#FF6B35' }}
|
|
712
|
-
/>
|
|
713
|
-
```
|
|
714
|
-
|
|
715
|
-
| Prop | iOS | Android |
|
|
716
|
-
| ---------------------- | -------------------------------------------- | -------------------------------------------- |
|
|
717
|
-
| `selectedSegmentColor` | `selectedSegmentTintColor` (the pill) | Checked button background |
|
|
718
|
-
| `activeTintColor` | Selected title / template image color | Checked button text and icon tint |
|
|
719
|
-
| `inactiveTintColor` | Normal title / template image color | Unchecked button text and icon tint |
|
|
720
|
-
| `labelStyle` | Title font (default: 13pt system) | Button typeface and size (default: theme) |
|
|
721
|
-
| `android.rippleColor` | — | Press ripple |
|
|
722
|
-
| `android.strokeColor` | — | Button outline |
|
|
723
|
-
|
|
724
|
-
Images with `tinted: false` keep their own colors and ignore the tint props.
|
|
725
|
-
|
|
726
|
-
### Badges
|
|
727
|
-
|
|
728
|
-
Give a segment a `badge` to show a count or short status at its top-right corner. Numbers render as-is, so format them yourself (`'99+'`); `undefined` hides the badge.
|
|
729
|
-
|
|
730
|
-
```tsx
|
|
731
41
|
<SegmentedControl
|
|
732
42
|
segments={[
|
|
733
|
-
{ label: '
|
|
734
|
-
{ label: '
|
|
735
|
-
{ label: 'Drafts', value: 'drafts', badge: 'new' },
|
|
43
|
+
{ label: 'Day', value: 'day' },
|
|
44
|
+
{ label: 'Week', value: 'week' },
|
|
736
45
|
]}
|
|
737
|
-
selectedValue={
|
|
738
|
-
onSelect={
|
|
739
|
-
|
|
740
|
-
/>
|
|
46
|
+
selectedValue={range}
|
|
47
|
+
onSelect={setRange}
|
|
48
|
+
/>;
|
|
741
49
|
```
|
|
742
50
|
|
|
743
|
-
|
|
744
|
-
- **Android**: a Material `BadgeDrawable` attached to the button. Defaults to the theme's error color.
|
|
745
|
-
- Screen readers announce the badge with the segment label ("Inbox, 3").
|
|
746
|
-
|
|
747
|
-
---
|
|
748
|
-
|
|
749
|
-
## LiquidGlass
|
|
750
|
-
|
|
751
|
-
Native glass morphism effect using **UIGlassEffect** on iOS 26+. On Android and older iOS versions, renders as a regular View with optional fallback styling.
|
|
752
|
-
|
|
753
|
-
> **Note:** LiquidGlass requires **iOS 26+** (Xcode 16+). On older iOS versions and Android, the component renders children without the glass effect. Use `isLiquidGlassSupported` to check availability and provide fallback UI.
|
|
754
|
-
|
|
755
|
-
### Props
|
|
756
|
-
|
|
757
|
-
| Prop | Type | Description |
|
|
758
|
-
| -------------- | ----------- | ------------------------------------------------- |
|
|
759
|
-
| `cornerRadius` | `number` | Corner radius for the glass effect (default: `0`) |
|
|
760
|
-
| `children` | `ReactNode` | Content to render inside the glass container |
|
|
761
|
-
|
|
762
|
-
### iOS Props (`ios`)
|
|
763
|
-
|
|
764
|
-
| Prop | Type | Description |
|
|
765
|
-
| ------------- | -------------------------------- | ---------------------------------------------------- |
|
|
766
|
-
| `effect` | `'clear' \| 'regular' \| 'none'` | Glass effect intensity (default: `'regular'`) |
|
|
767
|
-
| `interactive` | `boolean` | Enable touch interaction feedback (default: `false`) |
|
|
768
|
-
| `tintColor` | `string` | Overlay tint color (hex string) |
|
|
769
|
-
| `colorScheme` | `'light' \| 'dark' \| 'system'` | Appearance mode (default: `'system'`) |
|
|
770
|
-
|
|
771
|
-
### Android Props (`android`)
|
|
772
|
-
|
|
773
|
-
| Prop | Type | Description |
|
|
774
|
-
| ------------------------- | -------- | ---------------------------------------------- |
|
|
775
|
-
| `fallbackBackgroundColor` | `string` | Background color when glass effect unavailable |
|
|
776
|
-
|
|
777
|
-
### Constants
|
|
51
|
+
That renders `UISegmentedControl` on iOS and Material 3 segmented buttons (`MaterialButtonToggleGroup`) on Android. The library needs the New Architecture: React Native 0.81+, or Expo SDK 54+ with a dev client (not Expo Go). See [Installation](#installation) and the [documentation site](https://jarx-concepts.github.io/react-native-platform-components).
|
|
778
52
|
|
|
779
|
-
|
|
780
|
-
| ------------------------ | --------- | ------------------------------------ |
|
|
781
|
-
| `isLiquidGlassSupported` | `boolean` | `true` on iOS 26+, `false` otherwise |
|
|
53
|
+
## Why this library
|
|
782
54
|
|
|
783
|
-
|
|
55
|
+
| You need | This library | Common alternative |
|
|
56
|
+
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
57
|
+
| Date and time pickers | `UIDatePicker` on iOS; `MaterialDatePicker` / `MaterialTimePicker` or the AppCompat dialogs on Android. Declarative `visible` prop, modal or embedded. | `@react-native-community/datetimepicker`: platform dialogs on Android; Material 3 pickers are an [open request](https://github.com/react-native-datetimepicker/datetimepicker/issues/790). |
|
|
58
|
+
| Segmented control | `UISegmentedControl` on iOS; Material 3 segmented buttons on Android. Icons and badges on both. | `@react-native-segmented-control/segmented-control`: native on iOS, drawn in JavaScript on Android. |
|
|
59
|
+
| Context menu | `UIContextMenuInteraction` on iOS; `PopupMenu` on Android. Long-press gesture or modal trigger, icons on both. | `zeego`: native on both platforms, through two additional native dependencies (`react-native-ios-context-menu`, `@react-native-menu/menu`). |
|
|
60
|
+
| Selection menu | System menus on iOS; Material exposed dropdown or `Spinner` on Android. Headless or inline. | `@react-native-picker/picker`: wheel picker on iOS, dialog or dropdown `Spinner` on Android; no menu-style presentation. |
|
|
61
|
+
| Liquid glass | `UIGlassEffect` on iOS 26+, a fallback `View` elsewhere, `isLiquidGlassSupported` flag. | `@callstack/liquid-glass`, `expo-glass-effect`: same idea on iOS; here it ships with the components above. |
|
|
62
|
+
| All of the above | One package, one API shape (platform-only props under `ios={{ }}` and `android={{ }}`), Fabric + Codegen typed bindings, Expo config plugin, TypeScript. | Four or five packages with different conventions, install steps and upgrade cadences. |
|
|
784
63
|
|
|
785
|
-
|
|
786
|
-
- **`'clear'`**: More transparent, subtle glass effect
|
|
787
|
-
- **`'none'`**: No glass effect (useful for animating materialization/dematerialization)
|
|
788
|
-
|
|
789
|
-
### Platform Behavior
|
|
790
|
-
|
|
791
|
-
| Platform | iOS 26+ | iOS < 26 | Android |
|
|
792
|
-
| ------------- | ------------------- | ----------- | ------------ |
|
|
793
|
-
| Glass Effect | Full glass morphism | No effect | No effect |
|
|
794
|
-
| Corner Radius | Applied | Applied | Applied |
|
|
795
|
-
| Tint Color | Supported | Ignored | Ignored |
|
|
796
|
-
| Interactive | Supported | Ignored | Ignored |
|
|
797
|
-
| Fallback BG | N/A | Transparent | Configurable |
|
|
798
|
-
|
|
799
|
-
### Usage Tips
|
|
800
|
-
|
|
801
|
-
1. **Check support first**: Use `isLiquidGlassSupported` to conditionally render fallback UI
|
|
802
|
-
2. **Background content**: Glass effects work best over images or colorful backgrounds
|
|
803
|
-
3. **Interactive mode**: Only applies on mount; cannot be toggled after initial render
|
|
804
|
-
4. **Android fallback**: Set `android.fallbackBackgroundColor` for a semi-transparent background
|
|
805
|
-
|
|
806
|
-
---
|
|
807
|
-
|
|
808
|
-
## Design Philosophy
|
|
809
|
-
|
|
810
|
-
- **Native first** — no JS re-implementation of pickers
|
|
811
|
-
- **Headless-friendly** — works with any custom UI
|
|
812
|
-
- **Codegen-safe** — string unions & sentinel values for type safety
|
|
813
|
-
- **Predictable behavior** — no surprise re-renders or layout hacks
|
|
814
|
-
- **Platform conventions** — respects native UX patterns
|
|
815
|
-
|
|
816
|
-
---
|
|
817
|
-
|
|
818
|
-
## Theming
|
|
819
|
-
|
|
820
|
-
This library does not expose theming props. Components inherit their appearance from your app's native platform theme.
|
|
821
|
-
|
|
822
|
-
- **iOS**: Components follow system appearance (light/dark mode) and use system-defined styles (e.g., `UIBlurEffect` for menu backgrounds). These are not customizable per-component.
|
|
823
|
-
- **Android**: Components respect your app's Material Theme. Customize via your `styles.xml` or Material 3 theme configuration.
|
|
824
|
-
|
|
825
|
-
This is intentional. The goal is native fidelity, not pixel-level customization. If you need custom styling beyond what the platform theme provides, this library may not be the right fit.
|
|
826
|
-
|
|
827
|
-
---
|
|
828
|
-
|
|
829
|
-
## Color Formats
|
|
830
|
-
|
|
831
|
-
All color props in this library support the same formats as React Native's `backgroundColor`:
|
|
832
|
-
|
|
833
|
-
| Format | Example | Description |
|
|
834
|
-
| ------ | --------------------------------- | ---------------------------------- |
|
|
835
|
-
| Hex | `#RGB`, `#RRGGBB`, `#RRGGBBAA` | Standard hex colors |
|
|
836
|
-
| RGB | `rgb(255, 0, 0)` | RGB values (0-255) |
|
|
837
|
-
| RGBA | `rgba(255, 0, 0, 0.5)` | RGB with alpha (0-1) |
|
|
838
|
-
| HSL | `hsl(0, 100%, 50%)` | Hue (0-360), saturation, lightness |
|
|
839
|
-
| HSLA | `hsla(0, 100%, 50%, 0.5)` | HSL with alpha (0-1) |
|
|
840
|
-
| Named | `red`, `steelblue`, `transparent` | CSS named colors |
|
|
64
|
+
## Components
|
|
841
65
|
|
|
842
|
-
|
|
66
|
+
| Component | iOS | Android | Docs |
|
|
67
|
+
| -------------------- | -------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
68
|
+
| **DatePicker** | `UIDatePicker` | `MaterialDatePicker` / `MaterialTimePicker` or AppCompat dialogs | [DatePicker](https://jarx-concepts.github.io/react-native-platform-components/components/datepicker) |
|
|
69
|
+
| **ContextMenu** | `UIContextMenuInteraction` | `PopupMenu` | [ContextMenu](https://jarx-concepts.github.io/react-native-platform-components/components/contextmenu) |
|
|
70
|
+
| **SelectionMenu** | System menus | Material exposed dropdown or `Spinner` | [SelectionMenu](https://jarx-concepts.github.io/react-native-platform-components/components/selectionmenu) |
|
|
71
|
+
| **SegmentedControl** | `UISegmentedControl` | `MaterialButtonToggleGroup` (Material 3 segmented buttons) | [SegmentedControl](https://jarx-concepts.github.io/react-native-platform-components/components/segmentedcontrol) |
|
|
72
|
+
| **LiquidGlass** | `UIGlassEffect` (iOS 26+) | Fallback `View` | [LiquidGlass](https://jarx-concepts.github.io/react-native-platform-components/components/liquidglass) |
|
|
843
73
|
|
|
844
|
-
|
|
845
|
-
- `SegmentedControl`: `selectedSegmentColor`, `activeTintColor`, `inactiveTintColor`, `badgeStyle.backgroundColor`, `badgeStyle.color`, `android.rippleColor`, `android.strokeColor` (these also accept `PlatformColor` / `DynamicColorIOS`)
|
|
846
|
-
- `LiquidGlass`: `ios.tintColor`, `android.fallbackBackgroundColor`
|
|
74
|
+
**Have a component request?** If there's a native UI component you'd like to see added, [open an issue](https://github.com/JarX-Concepts/react-native-platform-components/issues/new) describing the component and its native APIs on iOS and Android.
|
|
847
75
|
|
|
848
|
-
|
|
849
|
-
// All of these are equivalent
|
|
850
|
-
<ContextMenu actions={[{ id: '1', title: 'Red', imageColor: '#FF0000' }]} />
|
|
851
|
-
<ContextMenu actions={[{ id: '1', title: 'Red', imageColor: 'rgb(255, 0, 0)' }]} />
|
|
852
|
-
<ContextMenu actions={[{ id: '1', title: 'Red', imageColor: 'hsl(0, 100%, 50%)' }]} />
|
|
853
|
-
<ContextMenu actions={[{ id: '1', title: 'Red', imageColor: 'red' }]} />
|
|
854
|
-
```
|
|
76
|
+
**Using it in a shipped app?** Open a PR to list it here.
|
|
855
77
|
|
|
856
78
|
---
|
|
857
79
|
|
|
858
|
-
##
|
|
859
|
-
|
|
860
|
-
> **⚠️ Your app may hard crash if you skip this section.** Android components require specific theme configuration. Components can crash immediately on mount if the required theme attributes are missing.
|
|
861
|
-
|
|
862
|
-
### Theme Requirements by Component
|
|
863
|
-
|
|
864
|
-
| Component | Mode | Required Theme | Crash if Missing |
|
|
865
|
-
| -------------------- | ---------------------------- | ------------------- | ---------------- |
|
|
866
|
-
| **SegmentedControl** | (always M3) | `Theme.Material3.*` | ✅ Yes |
|
|
867
|
-
| **DatePicker** | `android.material: 'm3'` | `Theme.Material3.*` | ✅ Yes |
|
|
868
|
-
| **DatePicker** | `android.material: 'system'` | `Theme.AppCompat.*` | ✅ Yes |
|
|
869
|
-
| **SelectionMenu** | `android.material: 'm3'` | `Theme.Material3.*` | ✅ Yes |
|
|
870
|
-
| **SelectionMenu** | `android.material: 'system'` | `Theme.AppCompat.*` | ✅ Yes |
|
|
871
|
-
| **ContextMenu** | — | Any | ❌ No |
|
|
872
|
-
| **LiquidGlass** | — | Any | ❌ No |
|
|
873
|
-
|
|
874
|
-
### Material 3 Theme Setup (Required for SegmentedControl)
|
|
875
|
-
|
|
876
|
-
`SegmentedControl` always uses Material 3 widgets (`MaterialButtonToggleGroup`). Your app **must** use a Material 3 theme or the app will crash on component mount.
|
|
877
|
-
|
|
878
|
-
**1. Update your app theme in `android/app/src/main/res/values/styles.xml`:**
|
|
879
|
-
|
|
880
|
-
```xml
|
|
881
|
-
<resources>
|
|
882
|
-
<!-- Base application theme - MUST inherit from Material3 -->
|
|
883
|
-
<style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
|
|
884
|
-
<!-- Material 3 requires these color attributes -->
|
|
885
|
-
<item name="colorPrimary">@color/md_theme_primary</item>
|
|
886
|
-
<item name="colorOnPrimary">@color/md_theme_onPrimary</item>
|
|
887
|
-
<item name="colorPrimaryContainer">@color/md_theme_primaryContainer</item>
|
|
888
|
-
<item name="colorOnPrimaryContainer">@color/md_theme_onPrimaryContainer</item>
|
|
889
|
-
<item name="colorSecondary">@color/md_theme_secondary</item>
|
|
890
|
-
<item name="colorOnSecondary">@color/md_theme_onSecondary</item>
|
|
891
|
-
<item name="colorSecondaryContainer">@color/md_theme_secondaryContainer</item>
|
|
892
|
-
<item name="colorOnSecondaryContainer">@color/md_theme_onSecondaryContainer</item>
|
|
893
|
-
<item name="colorTertiary">@color/md_theme_tertiary</item>
|
|
894
|
-
<item name="colorOnTertiary">@color/md_theme_onTertiary</item>
|
|
895
|
-
<item name="colorBackground">@color/md_theme_background</item>
|
|
896
|
-
<item name="colorOnBackground">@color/md_theme_onBackground</item>
|
|
897
|
-
<item name="colorSurface">@color/md_theme_surface</item>
|
|
898
|
-
<item name="colorOnSurface">@color/md_theme_onSurface</item>
|
|
899
|
-
<item name="colorError">@color/md_theme_error</item>
|
|
900
|
-
<item name="colorOnError">@color/md_theme_onError</item>
|
|
901
|
-
</style>
|
|
902
|
-
</resources>
|
|
903
|
-
```
|
|
904
|
-
|
|
905
|
-
**2. Define your Material 3 colors in `android/app/src/main/res/values/colors.xml`:**
|
|
906
|
-
|
|
907
|
-
```xml
|
|
908
|
-
<resources>
|
|
909
|
-
<!-- Generate these using Material Theme Builder: https://m3.material.io/theme-builder -->
|
|
910
|
-
<color name="md_theme_primary">#6750A4</color>
|
|
911
|
-
<color name="md_theme_onPrimary">#FFFFFF</color>
|
|
912
|
-
<color name="md_theme_primaryContainer">#EADDFF</color>
|
|
913
|
-
<color name="md_theme_onPrimaryContainer">#21005D</color>
|
|
914
|
-
<color name="md_theme_secondary">#625B71</color>
|
|
915
|
-
<color name="md_theme_onSecondary">#FFFFFF</color>
|
|
916
|
-
<color name="md_theme_secondaryContainer">#E8DEF8</color>
|
|
917
|
-
<color name="md_theme_onSecondaryContainer">#1D192B</color>
|
|
918
|
-
<color name="md_theme_tertiary">#7D5260</color>
|
|
919
|
-
<color name="md_theme_onTertiary">#FFFFFF</color>
|
|
920
|
-
<color name="md_theme_background">#FFFBFE</color>
|
|
921
|
-
<color name="md_theme_onBackground">#1C1B1F</color>
|
|
922
|
-
<color name="md_theme_surface">#FFFBFE</color>
|
|
923
|
-
<color name="md_theme_onSurface">#1C1B1F</color>
|
|
924
|
-
<color name="md_theme_error">#B3261E</color>
|
|
925
|
-
<color name="md_theme_onError">#FFFFFF</color>
|
|
926
|
-
</resources>
|
|
927
|
-
```
|
|
928
|
-
|
|
929
|
-
> **Tip:** Use Google's [Material Theme Builder](https://m3.material.io/theme-builder) to generate a complete color scheme.
|
|
930
|
-
|
|
931
|
-
### Common Crash Scenarios
|
|
932
|
-
|
|
933
|
-
#### Crash: `Cannot find theme attribute materialButtonOutlinedStyle`
|
|
934
|
-
|
|
935
|
-
**Cause:** Using `SegmentedControl` without a Material 3 theme.
|
|
936
|
-
|
|
937
|
-
**Fix:** Update your theme to inherit from `Theme.Material3.*`:
|
|
938
|
-
|
|
939
|
-
```xml
|
|
940
|
-
<!-- Change this -->
|
|
941
|
-
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
|
80
|
+
## Installation
|
|
942
81
|
|
|
943
|
-
|
|
944
|
-
|
|
82
|
+
```sh
|
|
83
|
+
npm install react-native-platform-components
|
|
84
|
+
# or
|
|
85
|
+
yarn add react-native-platform-components
|
|
945
86
|
```
|
|
946
87
|
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
**Cause:** Using `DatePicker` or `SelectionMenu` with `android.material: 'system'` while not extending AppCompat.
|
|
950
|
-
|
|
951
|
-
**Fix:** Ensure your theme inherits from `Theme.AppCompat.*` or `Theme.Material3.*` (which extends AppCompat), and your `MainActivity` extends `AppCompatActivity`.
|
|
952
|
-
|
|
953
|
-
### Mode Selection Guide
|
|
954
|
-
|
|
955
|
-
Choose the appropriate mode based on your app's theme:
|
|
88
|
+
**iOS:** `cd ios && pod install`. Nothing else to configure.
|
|
956
89
|
|
|
957
|
-
|
|
958
|
-
// If your app uses Theme.Material3.* (recommended)
|
|
959
|
-
<DatePicker android={{ material: 'm3' }} />
|
|
960
|
-
<SelectionMenu android={{ material: 'm3' }} />
|
|
961
|
-
<SegmentedControl /> // Always M3
|
|
962
|
-
|
|
963
|
-
// If your app uses Theme.AppCompat.*
|
|
964
|
-
<DatePicker android={{ material: 'system' }} />
|
|
965
|
-
<SelectionMenu android={{ material: 'system' }} />
|
|
966
|
-
// ⚠️ SegmentedControl will crash - upgrade to Material 3
|
|
967
|
-
```
|
|
90
|
+
**Android:** nothing to configure. The components work with the default AppCompat app theme; give the app a Material 3 theme to have `SegmentedControl` and the Material pickers use your colors. See [Android Theme Configuration](https://jarx-concepts.github.io/react-native-platform-components/guides/android-theme).
|
|
968
91
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
For Expo projects, the config plugin can configure your theme automatically. Add to `app.json`:
|
|
92
|
+
**Expo:** needs a dev client or EAS Build (native code, so not Expo Go). The config plugin sets up the Material 3 theme for you:
|
|
972
93
|
|
|
973
94
|
```json
|
|
974
95
|
{
|
|
@@ -976,106 +97,47 @@ For Expo projects, the config plugin can configure your theme automatically. Add
|
|
|
976
97
|
"plugins": [
|
|
977
98
|
[
|
|
978
99
|
"react-native-platform-components/app.plugin",
|
|
979
|
-
{
|
|
980
|
-
"android": {
|
|
981
|
-
"theme": "material3"
|
|
982
|
-
}
|
|
983
|
-
}
|
|
100
|
+
{ "android": { "theme": "material3" } }
|
|
984
101
|
]
|
|
985
102
|
]
|
|
986
103
|
}
|
|
987
104
|
}
|
|
988
105
|
```
|
|
989
106
|
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
## Icons
|
|
995
|
-
|
|
996
|
-
ContextMenu supports icons on menu items. Icons are specified by name and resolved differently on each platform. SegmentedControl accepts the same names, plus image assets and per-platform pairs; see [SegmentedControl Icon Support](#icon-support-1).
|
|
997
|
-
|
|
998
|
-
### iOS
|
|
999
|
-
|
|
1000
|
-
Use [SF Symbols](https://developer.apple.com/sf-symbols/) names. These are built into iOS and require no additional setup.
|
|
1001
|
-
|
|
1002
|
-
```tsx
|
|
1003
|
-
// Common SF Symbols
|
|
1004
|
-
image: 'doc.on.doc'; // Copy
|
|
1005
|
-
image: 'square.and.arrow.up'; // Share
|
|
1006
|
-
image: 'trash'; // Delete
|
|
1007
|
-
image: 'pencil'; // Edit
|
|
1008
|
-
image: 'checkmark.circle'; // Checkmark
|
|
1009
|
-
```
|
|
1010
|
-
|
|
1011
|
-
Browse available symbols using Apple's SF Symbols app or [sfsymbols.com](https://sfsymbols.com).
|
|
1012
|
-
|
|
1013
|
-
### Android
|
|
1014
|
-
|
|
1015
|
-
Use drawable resource names from your app's `res/drawable` directory. You must add these resources yourself.
|
|
1016
|
-
|
|
1017
|
-
```tsx
|
|
1018
|
-
// Reference drawable by name (without extension)
|
|
1019
|
-
image: 'content_copy'; // res/drawable/content_copy.xml
|
|
1020
|
-
image: 'share'; // res/drawable/share.xml
|
|
1021
|
-
image: 'delete'; // res/drawable/delete.xml
|
|
107
|
+
```sh
|
|
108
|
+
npx expo install react-native-platform-components
|
|
109
|
+
npx expo prebuild
|
|
110
|
+
npx expo run:ios # or run:android
|
|
1022
111
|
```
|
|
1023
112
|
|
|
1024
|
-
|
|
113
|
+
The library is built for the New Architecture (Fabric + Codegen) and does not support the old architecture.
|
|
1025
114
|
|
|
1026
|
-
|
|
1027
|
-
2. Use [Material Icons](https://fonts.google.com/icons) as a source — download SVG and convert to Android Vector Drawable
|
|
1028
|
-
3. Name the file to match the `image` prop value (e.g., `content_copy.xml` for `image: 'content_copy'`)
|
|
115
|
+
**Compatibility:**
|
|
1029
116
|
|
|
1030
|
-
|
|
117
|
+
| Platform | Minimum |
|
|
118
|
+
| ------------ | --------------------------------------------------------- |
|
|
119
|
+
| React Native | 0.81 with the New Architecture enabled |
|
|
120
|
+
| Expo SDK | 54, with a dev client or EAS Build (not Expo Go) |
|
|
121
|
+
| React | 19 |
|
|
122
|
+
| iOS | 13 (LiquidGlass needs iOS 26) |
|
|
123
|
+
| Android | API 24 (Android 7.0); Material Components 1.12 is bundled |
|
|
1031
124
|
|
|
1032
|
-
|
|
1033
|
-
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
1034
|
-
android:width="24dp"
|
|
1035
|
-
android:height="24dp"
|
|
1036
|
-
android:viewportWidth="24"
|
|
1037
|
-
android:viewportHeight="24">
|
|
1038
|
-
<path
|
|
1039
|
-
android:fillColor="@android:color/white"
|
|
1040
|
-
android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
|
|
1041
|
-
</vector>
|
|
1042
|
-
```
|
|
125
|
+
Full details: [Installation](https://jarx-concepts.github.io/react-native-platform-components/installation).
|
|
1043
126
|
|
|
1044
|
-
|
|
127
|
+
## Documentation
|
|
1045
128
|
|
|
1046
|
-
|
|
129
|
+
Everything else lives on the documentation site:
|
|
1047
130
|
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
id: 'copy',
|
|
1054
|
-
title: 'Copy',
|
|
1055
|
-
image: Platform.OS === 'ios' ? 'doc.on.doc' : 'content_copy',
|
|
1056
|
-
},
|
|
1057
|
-
{
|
|
1058
|
-
id: 'share',
|
|
1059
|
-
title: 'Share',
|
|
1060
|
-
image: Platform.OS === 'ios' ? 'square.and.arrow.up' : 'share',
|
|
1061
|
-
},
|
|
1062
|
-
{
|
|
1063
|
-
id: 'delete',
|
|
1064
|
-
title: 'Delete',
|
|
1065
|
-
image: Platform.OS === 'ios' ? 'trash' : 'delete',
|
|
1066
|
-
attributes: { destructive: true },
|
|
1067
|
-
},
|
|
1068
|
-
];
|
|
1069
|
-
```
|
|
1070
|
-
|
|
1071
|
-
---
|
|
131
|
+
- [Quick Start](https://jarx-concepts.github.io/react-native-platform-components/quick-start): copy-paste examples for every component
|
|
132
|
+
- [DatePicker](https://jarx-concepts.github.io/react-native-platform-components/components/datepicker), [ContextMenu](https://jarx-concepts.github.io/react-native-platform-components/components/contextmenu), [SelectionMenu](https://jarx-concepts.github.io/react-native-platform-components/components/selectionmenu), [SegmentedControl](https://jarx-concepts.github.io/react-native-platform-components/components/segmentedcontrol), [LiquidGlass](https://jarx-concepts.github.io/react-native-platform-components/components/liquidglass): props, platform options and behavior
|
|
133
|
+
- [Android Theme Configuration](https://jarx-concepts.github.io/react-native-platform-components/guides/android-theme): Material 3 setup and what happens without it
|
|
134
|
+
- [Icons](https://jarx-concepts.github.io/react-native-platform-components/guides/icons): SF Symbols, drawables and images
|
|
135
|
+
- [Theming and Colors](https://jarx-concepts.github.io/react-native-platform-components/guides/theming): design philosophy, theming, accepted color formats
|
|
1072
136
|
|
|
1073
137
|
## Contributing
|
|
1074
138
|
|
|
1075
139
|
See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
|
|
1076
140
|
|
|
1077
|
-
**Have a component request?** If there's a native UI component you'd like to see added, [open an issue](https://github.com/JarX-Concepts/react-native-platform-components/issues/new) describing the component and its native APIs on iOS and Android.
|
|
1078
|
-
|
|
1079
141
|
## License
|
|
1080
142
|
|
|
1081
143
|
MIT
|