@studio-piot/native-ui 0.2.4 → 0.16.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 +22 -18
- package/dist/components/Button/Button.d.ts +20 -4
- package/dist/components/Button/Button.d.ts.map +1 -1
- package/dist/components/Button/Button.js +34 -21
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Button/buttonAppearance.d.ts +20 -0
- package/dist/components/Button/buttonAppearance.d.ts.map +1 -0
- package/dist/components/Button/buttonAppearance.js +28 -0
- package/dist/components/Button/buttonAppearance.js.map +1 -0
- package/dist/components/Button/buttonThemeRoles.d.ts +6 -0
- package/dist/components/Button/buttonThemeRoles.d.ts.map +1 -0
- package/dist/components/Button/buttonThemeRoles.js +8 -0
- package/dist/components/Button/buttonThemeRoles.js.map +1 -0
- package/dist/components/Button/index.d.ts +3 -1
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.js +4 -1
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Choice/Choice.d.ts +8 -0
- package/dist/components/Choice/Choice.d.ts.map +1 -0
- package/dist/components/Choice/Choice.js +60 -0
- package/dist/components/Choice/Choice.js.map +1 -0
- package/dist/components/Choice/choiceLayout.d.ts +7 -0
- package/dist/components/Choice/choiceLayout.d.ts.map +1 -0
- package/dist/components/Choice/choiceLayout.js +13 -0
- package/dist/components/Choice/choiceLayout.js.map +1 -0
- package/dist/components/Choice/choiceThemeRoles.d.ts +8 -0
- package/dist/components/Choice/choiceThemeRoles.d.ts.map +1 -0
- package/dist/components/Choice/choiceThemeRoles.js +10 -0
- package/dist/components/Choice/choiceThemeRoles.js.map +1 -0
- package/dist/components/Choice/index.d.ts +5 -0
- package/dist/components/Choice/index.d.ts.map +1 -0
- package/dist/components/Choice/index.js +10 -0
- package/dist/components/Choice/index.js.map +1 -0
- package/dist/components/Choice/types.d.ts +26 -0
- package/dist/components/Choice/types.d.ts.map +1 -0
- package/dist/components/Choice/types.js +3 -0
- package/dist/components/Choice/types.js.map +1 -0
- package/dist/components/ErrorBanner/ErrorBanner.d.ts +1 -1
- package/dist/components/ErrorBanner/ErrorBanner.d.ts.map +1 -1
- package/dist/components/ErrorBanner/ErrorBanner.js +19 -19
- package/dist/components/ErrorBanner/ErrorBanner.js.map +1 -1
- package/dist/components/ErrorBanner/errorBannerContext.d.ts +23 -3
- package/dist/components/ErrorBanner/errorBannerContext.d.ts.map +1 -1
- package/dist/components/ErrorBanner/errorBannerContext.js +9 -5
- package/dist/components/ErrorBanner/errorBannerContext.js.map +1 -1
- package/dist/components/ErrorBanner/errorBannerLayout.d.ts +18 -0
- package/dist/components/ErrorBanner/errorBannerLayout.d.ts.map +1 -0
- package/dist/components/ErrorBanner/errorBannerLayout.js +54 -0
- package/dist/components/ErrorBanner/errorBannerLayout.js.map +1 -0
- package/dist/components/ErrorBanner/icons.d.ts +7 -5
- package/dist/components/ErrorBanner/icons.d.ts.map +1 -1
- package/dist/components/ErrorBanner/icons.js +8 -4
- package/dist/components/ErrorBanner/icons.js.map +1 -1
- package/dist/components/ErrorBanner/index.d.ts +1 -1
- package/dist/components/ErrorBanner/index.d.ts.map +1 -1
- package/dist/components/ErrorBanner/index.js.map +1 -1
- package/dist/components/Form/Form.d.ts +9 -1
- package/dist/components/Form/Form.d.ts.map +1 -1
- package/dist/components/Form/Form.js +56 -78
- package/dist/components/Form/Form.js.map +1 -1
- package/dist/components/Form/FormCloseButton.d.ts +3 -1
- package/dist/components/Form/FormCloseButton.d.ts.map +1 -1
- package/dist/components/Form/FormCloseButton.js +5 -4
- package/dist/components/Form/FormCloseButton.js.map +1 -1
- package/dist/components/Form/FormErrorBanner.d.ts +15 -0
- package/dist/components/Form/FormErrorBanner.d.ts.map +1 -0
- package/dist/components/Form/FormErrorBanner.js +30 -0
- package/dist/components/Form/FormErrorBanner.js.map +1 -0
- package/dist/components/Form/FormSubmitFooter.d.ts +17 -0
- package/dist/components/Form/FormSubmitFooter.d.ts.map +1 -0
- package/dist/components/Form/FormSubmitFooter.js +32 -0
- package/dist/components/Form/FormSubmitFooter.js.map +1 -0
- package/dist/components/Form/formThemeRoles.d.ts +7 -0
- package/dist/components/Form/formThemeRoles.d.ts.map +1 -0
- package/dist/components/Form/formThemeRoles.js +9 -0
- package/dist/components/Form/formThemeRoles.js.map +1 -0
- package/dist/components/Form/index.d.ts +1 -0
- package/dist/components/Form/index.d.ts.map +1 -1
- package/dist/components/Form/index.js +3 -1
- package/dist/components/Form/index.js.map +1 -1
- package/dist/components/Form/types.d.ts +14 -10
- package/dist/components/Form/types.d.ts.map +1 -1
- package/dist/components/FormSheet/FormSheet.d.ts +10 -0
- package/dist/components/FormSheet/FormSheet.d.ts.map +1 -0
- package/dist/components/FormSheet/FormSheet.js +153 -0
- package/dist/components/FormSheet/FormSheet.js.map +1 -0
- package/dist/components/FormSheet/formSheetLayout.d.ts +32 -0
- package/dist/components/FormSheet/formSheetLayout.d.ts.map +1 -0
- package/dist/components/FormSheet/formSheetLayout.js +43 -0
- package/dist/components/FormSheet/formSheetLayout.js.map +1 -0
- package/dist/components/FormSheet/formSheetThemeRoles.d.ts +8 -0
- package/dist/components/FormSheet/formSheetThemeRoles.d.ts.map +1 -0
- package/dist/components/FormSheet/formSheetThemeRoles.js +10 -0
- package/dist/components/FormSheet/formSheetThemeRoles.js.map +1 -0
- package/dist/components/FormSheet/index.d.ts +5 -0
- package/dist/components/FormSheet/index.d.ts.map +1 -0
- package/dist/components/FormSheet/index.js +10 -0
- package/dist/components/FormSheet/index.js.map +1 -0
- package/dist/components/FormSheet/types.d.ts +64 -0
- package/dist/components/FormSheet/types.d.ts.map +1 -0
- package/dist/components/FormSheet/types.js +3 -0
- package/dist/components/FormSheet/types.js.map +1 -0
- package/dist/components/HeaderButton/HeaderCapsule.d.ts +4 -0
- package/dist/components/HeaderButton/HeaderCapsule.d.ts.map +1 -0
- package/dist/components/HeaderButton/HeaderCapsule.js +32 -0
- package/dist/components/HeaderButton/HeaderCapsule.js.map +1 -0
- package/dist/components/HeaderButton/HeaderGroup.d.ts +4 -0
- package/dist/components/HeaderButton/HeaderGroup.d.ts.map +1 -0
- package/dist/components/HeaderButton/HeaderGroup.js +23 -0
- package/dist/components/HeaderButton/HeaderGroup.js.map +1 -0
- package/dist/components/HeaderButton/HeaderIcon.d.ts +4 -0
- package/dist/components/HeaderButton/HeaderIcon.d.ts.map +1 -0
- package/dist/components/HeaderButton/HeaderIcon.js +28 -0
- package/dist/components/HeaderButton/HeaderIcon.js.map +1 -0
- package/dist/components/HeaderButton/headerButtonLayout.d.ts +21 -0
- package/dist/components/HeaderButton/headerButtonLayout.d.ts.map +1 -0
- package/dist/components/HeaderButton/headerButtonLayout.js +34 -0
- package/dist/components/HeaderButton/headerButtonLayout.js.map +1 -0
- package/dist/components/HeaderButton/headerButtonThemeRoles.d.ts +5 -0
- package/dist/components/HeaderButton/headerButtonThemeRoles.d.ts.map +1 -0
- package/dist/components/HeaderButton/headerButtonThemeRoles.js +7 -0
- package/dist/components/HeaderButton/headerButtonThemeRoles.js.map +1 -0
- package/dist/components/HeaderButton/index.d.ts +7 -0
- package/dist/components/HeaderButton/index.d.ts.map +1 -0
- package/dist/components/HeaderButton/index.js +14 -0
- package/dist/components/HeaderButton/index.js.map +1 -0
- package/dist/components/HeaderButton/types.d.ts +40 -0
- package/dist/components/HeaderButton/types.d.ts.map +1 -0
- package/dist/components/HeaderButton/types.js +3 -0
- package/dist/components/HeaderButton/types.js.map +1 -0
- package/dist/components/HeaderWash/HeaderWash.d.ts +10 -0
- package/dist/components/HeaderWash/HeaderWash.d.ts.map +1 -0
- package/dist/components/HeaderWash/HeaderWash.js +19 -0
- package/dist/components/HeaderWash/HeaderWash.js.map +1 -0
- package/dist/components/HeaderWash/headerWashGradient.d.ts +8 -0
- package/dist/components/HeaderWash/headerWashGradient.d.ts.map +1 -0
- package/dist/components/HeaderWash/headerWashGradient.js +21 -0
- package/dist/components/HeaderWash/headerWashGradient.js.map +1 -0
- package/dist/components/HeaderWash/index.d.ts +2 -0
- package/dist/components/HeaderWash/index.d.ts.map +1 -0
- package/dist/components/HeaderWash/index.js +6 -0
- package/dist/components/HeaderWash/index.js.map +1 -0
- package/dist/components/Page/Page.d.ts +13 -0
- package/dist/components/Page/Page.d.ts.map +1 -0
- package/dist/components/Page/Page.js +49 -0
- package/dist/components/Page/Page.js.map +1 -0
- package/dist/components/Page/PageBleed.d.ts +9 -0
- package/dist/components/Page/PageBleed.d.ts.map +1 -0
- package/dist/components/Page/PageBleed.js +12 -0
- package/dist/components/Page/PageBleed.js.map +1 -0
- package/dist/components/Page/index.d.ts +5 -0
- package/dist/components/Page/index.d.ts.map +1 -0
- package/dist/components/Page/index.js +10 -0
- package/dist/components/Page/index.js.map +1 -0
- package/dist/components/Page/pageContext.d.ts +4 -0
- package/dist/components/Page/pageContext.d.ts.map +1 -0
- package/dist/components/Page/pageContext.js +11 -0
- package/dist/components/Page/pageContext.js.map +1 -0
- package/dist/components/Page/pageInsets.d.ts +26 -0
- package/dist/components/Page/pageInsets.d.ts.map +1 -0
- package/dist/components/Page/pageInsets.js +37 -0
- package/dist/components/Page/pageInsets.js.map +1 -0
- package/dist/components/Page/pageLayout.d.ts +5 -0
- package/dist/components/Page/pageLayout.d.ts.map +1 -0
- package/dist/components/Page/pageLayout.js +8 -0
- package/dist/components/Page/pageLayout.js.map +1 -0
- package/dist/components/Page/pageThemeRoles.d.ts +5 -0
- package/dist/components/Page/pageThemeRoles.d.ts.map +1 -0
- package/dist/components/Page/pageThemeRoles.js +7 -0
- package/dist/components/Page/pageThemeRoles.js.map +1 -0
- package/dist/components/Page/types.d.ts +22 -0
- package/dist/components/Page/types.d.ts.map +1 -0
- package/dist/components/Page/types.js +3 -0
- package/dist/components/Page/types.js.map +1 -0
- package/dist/components/SegmentedControl/types.d.ts +0 -1
- package/dist/components/SegmentedControl/types.d.ts.map +1 -1
- package/dist/components/Select/Select.d.ts +1 -1
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.js +8 -9
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Select/selectThemeRoles.d.ts +2 -0
- package/dist/components/Select/selectThemeRoles.d.ts.map +1 -1
- package/dist/components/Select/selectThemeRoles.js +2 -0
- package/dist/components/Select/selectThemeRoles.js.map +1 -1
- package/dist/components/Select/types.d.ts +4 -0
- package/dist/components/Select/types.d.ts.map +1 -1
- package/dist/components/TabAccessoryButton/TabAccessoryButton.d.ts +8 -0
- package/dist/components/TabAccessoryButton/TabAccessoryButton.d.ts.map +1 -0
- package/dist/components/TabAccessoryButton/TabAccessoryButton.js +77 -0
- package/dist/components/TabAccessoryButton/TabAccessoryButton.js.map +1 -0
- package/dist/components/TabAccessoryButton/index.d.ts +5 -0
- package/dist/components/TabAccessoryButton/index.d.ts.map +1 -0
- package/dist/components/TabAccessoryButton/index.js +11 -0
- package/dist/components/TabAccessoryButton/index.js.map +1 -0
- package/dist/components/TabAccessoryButton/tabAccessoryLayout.d.ts +27 -0
- package/dist/components/TabAccessoryButton/tabAccessoryLayout.d.ts.map +1 -0
- package/dist/components/TabAccessoryButton/tabAccessoryLayout.js +38 -0
- package/dist/components/TabAccessoryButton/tabAccessoryLayout.js.map +1 -0
- package/dist/components/TabAccessoryButton/tabAccessoryThemeRoles.d.ts +14 -0
- package/dist/components/TabAccessoryButton/tabAccessoryThemeRoles.d.ts.map +1 -0
- package/dist/components/TabAccessoryButton/tabAccessoryThemeRoles.js +19 -0
- package/dist/components/TabAccessoryButton/tabAccessoryThemeRoles.js.map +1 -0
- package/dist/components/TabAccessoryButton/types.d.ts +27 -0
- package/dist/components/TabAccessoryButton/types.d.ts.map +1 -0
- package/dist/components/TabAccessoryButton/types.js +3 -0
- package/dist/components/TabAccessoryButton/types.js.map +1 -0
- package/dist/components/index.d.ts +9 -3
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +30 -1
- package/dist/components/index.js.map +1 -1
- package/dist/index.d.ts +11 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -2
- package/dist/index.js.map +1 -1
- package/dist/layout/HeaderInsetProbe.d.ts +15 -0
- package/dist/layout/HeaderInsetProbe.d.ts.map +1 -0
- package/dist/layout/HeaderInsetProbe.js +28 -0
- package/dist/layout/HeaderInsetProbe.js.map +1 -0
- package/dist/layout/headerInset.d.ts +26 -0
- package/dist/layout/headerInset.d.ts.map +1 -0
- package/dist/layout/headerInset.js +29 -0
- package/dist/layout/headerInset.js.map +1 -0
- package/dist/layout/index.d.ts +1 -0
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/layout/index.js +3 -1
- package/dist/layout/index.js.map +1 -1
- package/dist/layout/sheet.d.ts +3 -0
- package/dist/layout/sheet.d.ts.map +1 -0
- package/dist/layout/sheet.js +6 -0
- package/dist/layout/sheet.js.map +1 -0
- package/dist/theme/ThemeProvider.d.ts +4 -1
- package/dist/theme/ThemeProvider.d.ts.map +1 -1
- package/dist/theme/ThemeProvider.js +5 -2
- package/dist/theme/ThemeProvider.js.map +1 -1
- package/dist/theme/index.d.ts +2 -0
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +6 -1
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/resolveThemeSpacing.d.ts +12 -0
- package/dist/theme/resolveThemeSpacing.d.ts.map +1 -0
- package/dist/theme/resolveThemeSpacing.js +14 -0
- package/dist/theme/resolveThemeSpacing.js.map +1 -0
- package/dist/theme/types.d.ts +2 -0
- package/dist/theme/types.d.ts.map +1 -1
- package/dist/theme/useThemeSpacing.d.ts +4 -0
- package/dist/theme/useThemeSpacing.d.ts.map +1 -0
- package/dist/theme/useThemeSpacing.js +11 -0
- package/dist/theme/useThemeSpacing.js.map +1 -0
- package/docs/components/button.md +92 -38
- package/docs/components/choice.md +88 -0
- package/docs/components/error-banner.md +46 -3
- package/docs/components/form-sheet.md +140 -0
- package/docs/components/form.md +80 -45
- package/docs/components/header-button.md +310 -0
- package/docs/components/header-wash.md +40 -0
- package/docs/components/page.md +183 -0
- package/docs/components/select.md +2 -2
- package/docs/components/tab-accessory-button.md +146 -0
- package/docs/specifications/Liquid Glass header buttons in Expo Router.md +327 -0
- package/package.json +1 -1
- package/src/components/Button/Button.tsx +82 -38
- package/src/components/Button/buttonAppearance.test.ts +44 -0
- package/src/components/Button/buttonAppearance.ts +38 -0
- package/src/components/Button/buttonThemeRoles.test.ts +10 -0
- package/src/components/Button/buttonThemeRoles.ts +6 -0
- package/src/components/Button/index.ts +12 -1
- package/src/components/Choice/Choice.tsx +109 -0
- package/src/components/Choice/choiceLayout.test.ts +14 -0
- package/src/components/Choice/choiceLayout.ts +9 -0
- package/src/components/Choice/choiceThemeRoles.test.ts +14 -0
- package/src/components/Choice/choiceThemeRoles.ts +8 -0
- package/src/components/Choice/index.ts +4 -0
- package/src/components/Choice/types.ts +26 -0
- package/src/components/ErrorBanner/ErrorBanner.tsx +32 -22
- package/src/components/ErrorBanner/errorBannerContext.tsx +31 -6
- package/src/components/ErrorBanner/errorBannerLayout.test.ts +49 -0
- package/src/components/ErrorBanner/errorBannerLayout.ts +59 -0
- package/src/components/ErrorBanner/icons.tsx +25 -6
- package/src/components/ErrorBanner/index.ts +1 -0
- package/src/components/Form/Form.tsx +77 -173
- package/src/components/Form/FormCloseButton.tsx +12 -4
- package/src/components/Form/FormErrorBanner.tsx +57 -0
- package/src/components/Form/FormSubmitFooter.tsx +70 -0
- package/src/components/Form/formThemeRoles.test.ts +13 -0
- package/src/components/Form/formThemeRoles.ts +7 -0
- package/src/components/Form/index.ts +1 -0
- package/src/components/Form/types.ts +14 -10
- package/src/components/FormSheet/FormSheet.tsx +279 -0
- package/src/components/FormSheet/formSheetLayout.test.ts +66 -0
- package/src/components/FormSheet/formSheetLayout.ts +55 -0
- package/src/components/FormSheet/formSheetThemeRoles.test.ts +14 -0
- package/src/components/FormSheet/formSheetThemeRoles.ts +8 -0
- package/src/components/FormSheet/index.ts +7 -0
- package/src/components/FormSheet/types.ts +66 -0
- package/src/components/HeaderButton/HeaderCapsule.tsx +63 -0
- package/src/components/HeaderButton/HeaderGroup.tsx +36 -0
- package/src/components/HeaderButton/HeaderIcon.tsx +56 -0
- package/src/components/HeaderButton/headerButtonLayout.test.ts +47 -0
- package/src/components/HeaderButton/headerButtonLayout.ts +36 -0
- package/src/components/HeaderButton/headerButtonThemeRoles.test.ts +9 -0
- package/src/components/HeaderButton/headerButtonThemeRoles.ts +5 -0
- package/src/components/HeaderButton/index.ts +14 -0
- package/src/components/HeaderButton/types.ts +40 -0
- package/src/components/HeaderWash/HeaderWash.tsx +20 -0
- package/src/components/HeaderWash/headerWashGradient.test.ts +22 -0
- package/src/components/{Form/withAlpha.ts → HeaderWash/headerWashGradient.ts} +9 -0
- package/src/components/HeaderWash/index.ts +1 -0
- package/src/components/Page/Page.tsx +80 -0
- package/src/components/Page/PageBleed.tsx +14 -0
- package/src/components/Page/index.ts +4 -0
- package/src/components/Page/pageContext.ts +8 -0
- package/src/components/Page/pageInsets.test.ts +73 -0
- package/src/components/Page/pageInsets.ts +52 -0
- package/src/components/Page/pageThemeRoles.test.ts +9 -0
- package/src/components/Page/pageThemeRoles.ts +5 -0
- package/src/components/Page/types.ts +26 -0
- package/src/components/SegmentedControl/types.ts +0 -1
- package/src/components/Select/Select.tsx +11 -4
- package/src/components/Select/selectThemeRoles.test.ts +5 -0
- package/src/components/Select/selectThemeRoles.ts +2 -0
- package/src/components/Select/types.ts +4 -0
- package/src/components/TabAccessoryButton/TabAccessoryButton.tsx +150 -0
- package/src/components/TabAccessoryButton/index.ts +12 -0
- package/src/components/TabAccessoryButton/tabAccessoryLayout.test.ts +42 -0
- package/src/components/TabAccessoryButton/tabAccessoryLayout.ts +43 -0
- package/src/components/TabAccessoryButton/tabAccessoryThemeRoles.test.ts +28 -0
- package/src/components/TabAccessoryButton/tabAccessoryThemeRoles.ts +22 -0
- package/src/components/TabAccessoryButton/types.ts +27 -0
- package/src/components/index.ts +64 -2
- package/src/index.ts +61 -2
- package/src/layout/headerInset.test.ts +60 -0
- package/src/layout/headerInset.ts +41 -0
- package/src/layout/index.ts +1 -0
- package/src/layout/sheet.ts +2 -0
- package/src/theme/ThemeProvider.tsx +9 -1
- package/src/theme/index.ts +6 -0
- package/src/theme/resolveThemeSpacing.test.ts +29 -0
- package/src/theme/resolveThemeSpacing.ts +21 -0
- package/src/theme/types.ts +3 -0
- package/src/theme/useThemeSpacing.ts +8 -0
- package/src/components/Form/withAlpha.test.ts +0 -13
package/docs/components/form.md
CHANGED
|
@@ -1,87 +1,122 @@
|
|
|
1
1
|
# Form — usage
|
|
2
2
|
|
|
3
|
-
Full-screen
|
|
3
|
+
Full-screen form under the native stack header: keyboard-aware scroll, sticky submit footer, and the error banner. The title and close button come from the screen's stack options, like any other screen, so the header is native: the iOS 26 glass bar, the large title, back gestures. Colours default from `ThemeProvider`. Apps own the fields (e.g. `FieldText`).
|
|
4
4
|
|
|
5
|
-
For `ThemeProvider` and `useThemeColor`, see [theme provider and Button usage](./button.md).
|
|
5
|
+
For `ThemeProvider` and `useThemeColor`, see [theme provider and Button usage](./button.md). For a form over a map, see [FormSheet](./form-sheet.md).
|
|
6
6
|
|
|
7
7
|
## Peer dependencies
|
|
8
8
|
|
|
9
|
-
`Form` needs these installed in the app (same versions you already use for Expo):
|
|
10
|
-
|
|
11
9
|
- `react-native-keyboard-controller`
|
|
12
10
|
- `react-native-safe-area-context`
|
|
11
|
+
- `react-native-screens` (iOS overlay for the error banner)
|
|
13
12
|
|
|
14
13
|
Wrap the app (or the form route) with `KeyboardProvider` from `react-native-keyboard-controller` and a safe-area provider.
|
|
15
14
|
|
|
16
|
-
## Theme roles
|
|
17
|
-
|
|
18
|
-
| Usage | Theme role |
|
|
19
|
-
|---|---|
|
|
20
|
-
| Screen / fade ground | `background` |
|
|
21
|
-
| Title | `text` |
|
|
22
|
-
| Footer ground | `surface` |
|
|
23
|
-
| Submit fill | `buttonBackground` |
|
|
24
|
-
| Submit label | `buttonLabel` |
|
|
25
|
-
|
|
26
15
|
## Basic usage
|
|
27
16
|
|
|
28
17
|
```tsx
|
|
29
|
-
|
|
18
|
+
// app/(app)/create-activity/_layout.tsx
|
|
19
|
+
export default function Layout() {
|
|
20
|
+
return <Stack />;
|
|
21
|
+
}
|
|
22
|
+
```
|
|
30
23
|
|
|
31
|
-
|
|
24
|
+
```tsx
|
|
25
|
+
// app/(app)/create-activity/index.tsx
|
|
26
|
+
import { Form, FieldText, HeaderIcon } from "@studio-piot/native-ui";
|
|
27
|
+
import { router, Stack } from "expo-router";
|
|
28
|
+
import { SymbolView } from "expo-symbols";
|
|
29
|
+
|
|
30
|
+
export default function CreateActivity() {
|
|
32
31
|
return (
|
|
33
|
-
|
|
34
|
-
<
|
|
35
|
-
|
|
32
|
+
<>
|
|
33
|
+
<Stack.Screen
|
|
34
|
+
options={{
|
|
35
|
+
headerShown: true,
|
|
36
|
+
title: "New activity",
|
|
37
|
+
headerLeft: () => (
|
|
38
|
+
<HeaderIcon
|
|
39
|
+
label="Close"
|
|
40
|
+
icon={({ color, size }) => <SymbolView name="xmark" size={size} tintColor={color} />}
|
|
41
|
+
onPress={() => router.back()}
|
|
42
|
+
/>
|
|
43
|
+
),
|
|
44
|
+
}}
|
|
45
|
+
/>
|
|
46
|
+
<Form onSubmit={save} errors={errors}>
|
|
47
|
+
<FieldText name="name" label="Name" value={name} onChangeText={setName} />
|
|
48
|
+
</Form>
|
|
49
|
+
</>
|
|
36
50
|
);
|
|
37
51
|
}
|
|
38
52
|
```
|
|
39
53
|
|
|
40
|
-
|
|
54
|
+
- **Modal routes need their own stack.** On iOS a screen presented as a modal (`presentation: "modal"` or `"fullScreenModal"`) sits outside the navigation controller, so its header options are ignored and no header appears. Make the route a folder with its own `_layout.tsx` that returns a `<Stack />`, and put the screen in `index.tsx`. The parent still presents the folder as a modal, and the URL doesn't change.
|
|
55
|
+
- **Make `Form` the screen's root element.** Its scroll view must be a direct child of the screen so iOS insets it for the header and content scrolls behind the bar. A `<Stack.Screen>` next to it in a fragment is fine. Don't wrap `Form` in a `View`.
|
|
56
|
+
- **Header buttons.** Use `HeaderIcon` / `HeaderCapsule` for glass buttons, or `FormCloseButton` for a plain text "Cancel": `headerLeft: () => <FormCloseButton onPress={close} />`.
|
|
57
|
+
- **Large title.** `headerLargeTitle: true` works. The content starts under the large title and follows it as it collapses.
|
|
58
|
+
|
|
59
|
+
## Header fade
|
|
41
60
|
|
|
42
|
-
|
|
61
|
+
For a wash behind a transparent header, with fields fading as they scroll under it, use [`HeaderWash`](./header-wash.md) as the stack's `headerBackground`:
|
|
43
62
|
|
|
44
63
|
```tsx
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
closeButton={<FormCloseButton onPress={() => router.back()} />}
|
|
53
|
-
>
|
|
54
|
-
{children}
|
|
55
|
-
</Form>
|
|
64
|
+
<Stack
|
|
65
|
+
screenOptions={{
|
|
66
|
+
headerTransparent: true,
|
|
67
|
+
headerBackground: () => <HeaderWash />,
|
|
68
|
+
scrollEdgeEffects: { top: "hidden" },
|
|
69
|
+
}}
|
|
70
|
+
/>
|
|
56
71
|
```
|
|
57
72
|
|
|
58
|
-
|
|
73
|
+
On iOS the content still starts below the header and scrolls behind it. On Android a transparent toolbar overlaps the content, so keep the Android header opaque for forms, or pad the first field yourself.
|
|
74
|
+
|
|
75
|
+
## Error banner
|
|
76
|
+
|
|
77
|
+
Pass `errors` to show the banner (see [ErrorBanner](./error-banner.md)). A row scrolls its field clear of both the header and the banner. Pass `headerHeight={useHeaderHeight()}` (from `expo-router/react-navigation`) so that works with a large title or a custom header. Without it, `Form` assumes the status bar plus a standard bar.
|
|
78
|
+
|
|
79
|
+
- **iOS:** the banner covers the top of the screen, including the native header. It is drawn in a native overlay window (`FullWindowOverlay` from react-native-screens), because the header bar sits above all React content.
|
|
80
|
+
- **Android:** the native header doesn't overlap the screen, so the banner slides down directly below it.
|
|
81
|
+
|
|
82
|
+
## Theme roles
|
|
83
|
+
|
|
84
|
+
| Usage | Theme role |
|
|
85
|
+
|---|---|
|
|
86
|
+
| Scroll ground | `formBackground` |
|
|
87
|
+
| Footer ground | `formFooterBackground` |
|
|
88
|
+
| `FormCloseButton` label | `formClose` |
|
|
89
|
+
| Submit fill | `buttonBackground` |
|
|
90
|
+
| Submit label | `buttonLabel` |
|
|
91
|
+
|
|
92
|
+
The header's colours come from your stack options (`headerTintColor`, `headerTitleStyle`, `headerStyle`).
|
|
59
93
|
|
|
60
94
|
## Props
|
|
61
95
|
|
|
62
96
|
| Prop | Type | Default | Notes |
|
|
63
97
|
|---|---|---|---|
|
|
64
|
-
| `title` | `string` | — | Required. Header title |
|
|
65
98
|
| `children` | `ReactNode` | — | Required. Scroll body |
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
| `errors` | `FieldError[]` | `[]` | Field errors. The banner lists them and scrolls to each `name`. Editing a field dismisses the banner; the next submit shows it again. |
|
|
99
|
+
| `onSubmit` | `() => void` | — | Required. Sticky submit. Presents the error banner, then runs |
|
|
100
|
+
| `errors` | `FieldError[]` | `[]` | Field errors. The banner lists them and scrolls to each `name`. Editing a field dismisses the banner; the next submit shows it again |
|
|
69
101
|
| `submitLabel` | `string` | `"Save"` | |
|
|
70
102
|
| `submitting` | `boolean` | `false` | Loading on submit |
|
|
71
103
|
| `submitDisabled` | `boolean` | `false` | |
|
|
72
|
-
| `closeButton` | `ReactNode` | package Cancel | Slot for app Cancel |
|
|
73
104
|
| `submitRadius` | `ButtonRadius` | `"lg"` | Submit button radius |
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `footerBackgroundColor` | `string` | theme `
|
|
105
|
+
| `headerHeight` | `number` | status bar + standard bar | `useHeaderHeight()`. For scrolling an error's field clear of the header |
|
|
106
|
+
| `paddingHorizontal` | `number` | theme `spacing.screen` | Side inset for the content and footer |
|
|
107
|
+
| `backgroundColor` | `string` | theme `formBackground` | Optional override |
|
|
108
|
+
| `footerBackgroundColor` | `string` | theme `formFooterBackground` | Optional override |
|
|
78
109
|
| `buttonBackgroundColor` | `string` | theme `buttonBackground` | Optional override |
|
|
79
110
|
| `buttonLabelColor` | `string` | theme `buttonLabel` | Optional override |
|
|
80
111
|
|
|
112
|
+
The content starts `spacing.pageTop` below the header, the same as `Page`.
|
|
113
|
+
|
|
114
|
+
## Migrating from 0.12
|
|
115
|
+
|
|
116
|
+
`title`, `onClose`, `closeButton` and `titleColor` are gone, along with the `formTitle` role. Move them to the screen's stack options: `title`, `headerLeft`, and `headerTitleStyle`. Set `headerShown: true` if the route hid its header.
|
|
117
|
+
|
|
81
118
|
## Imports
|
|
82
119
|
|
|
83
120
|
```ts
|
|
84
|
-
import { Form, FormCloseButton, type FormProps } from "@studio-piot/native-ui";
|
|
121
|
+
import { Form, FormCloseButton, FORM_THEME_ROLES, type FormProps } from "@studio-piot/native-ui";
|
|
85
122
|
```
|
|
86
|
-
|
|
87
|
-
Header, scroll content, and footer share one horizontal inset (default `16`). Override with `paddingHorizontal` when a screen needs a different gutter; apps keep their own layout tokens and do not import the package default.
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# HeaderIcon, HeaderCapsule, HeaderGroup — usage
|
|
2
|
+
|
|
3
|
+
Content for native stack header buttons (`headerLeft` / `headerRight` in Expo Router or React Navigation). On iOS 26 the native stack wraps whatever those functions return in a `UIBarButtonItem` and draws the Liquid Glass background itself. These components supply the content only: an icon, or an icon and a label.
|
|
4
|
+
|
|
5
|
+
- **No background or border of their own on iOS 26+.** A styled button inside the glass gives two shapes, one inside the other.
|
|
6
|
+
- **The shape follows the content.** `HeaderIcon` is 36×36, which gives a circle. `HeaderCapsule` is wider than tall, which gives a pill.
|
|
7
|
+
- **One function, one glass shape.** Everything returned by `headerRight` shares one capsule; `HeaderGroup` lays several buttons out inside it.
|
|
8
|
+
- **Fallback.** Android and iOS 18 and earlier have no glass. The same code shows plain icons there. Pass `fallbackBackgroundColor` to draw a circle or pill on those platforms only.
|
|
9
|
+
|
|
10
|
+
The package has no Expo dependency, so the icon is a render function. It receives the resolved `color` and `size`; return an expo-symbols `SymbolView` or any other icon component.
|
|
11
|
+
|
|
12
|
+
## HeaderIcon (round)
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { HeaderIcon } from "@studio-piot/native-ui";
|
|
16
|
+
import { SymbolView } from "expo-symbols";
|
|
17
|
+
import { router, Stack } from "expo-router";
|
|
18
|
+
|
|
19
|
+
<Stack.Screen
|
|
20
|
+
name="index"
|
|
21
|
+
options={{
|
|
22
|
+
headerLeft: () => (
|
|
23
|
+
<HeaderIcon
|
|
24
|
+
label="Close"
|
|
25
|
+
size={18}
|
|
26
|
+
icon={({ color, size }) => (
|
|
27
|
+
<SymbolView name="xmark" size={size} weight="semibold" tintColor={color} />
|
|
28
|
+
)}
|
|
29
|
+
onPress={() => router.back()}
|
|
30
|
+
/>
|
|
31
|
+
),
|
|
32
|
+
}}
|
|
33
|
+
/>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`label` is required: it is the accessibility label, and VoiceOver has nothing else to read on an icon-only button.
|
|
37
|
+
|
|
38
|
+
## HeaderCapsule (icon and label)
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
headerLeft: () => (
|
|
42
|
+
<HeaderCapsule
|
|
43
|
+
label="Close"
|
|
44
|
+
icon={({ color, size }) => (
|
|
45
|
+
<SymbolView name="xmark" size={size} weight="semibold" tintColor={color} />
|
|
46
|
+
)}
|
|
47
|
+
onPress={() => router.back()}
|
|
48
|
+
/>
|
|
49
|
+
),
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`icon` is optional; without it the capsule shows the label only.
|
|
53
|
+
|
|
54
|
+
## HeaderGroup (bundled)
|
|
55
|
+
|
|
56
|
+
Several buttons in one `HeaderGroup` share a single glass capsule. Each keeps its own size and action.
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
headerRight: () => (
|
|
60
|
+
<HeaderGroup>
|
|
61
|
+
<HeaderIcon
|
|
62
|
+
label="Saved routes"
|
|
63
|
+
size={19}
|
|
64
|
+
icon={({ color, size }) => <SymbolView name="bookmark" size={size} tintColor={color} />}
|
|
65
|
+
onPress={() => router.push("/new-activity/saved-routes")}
|
|
66
|
+
/>
|
|
67
|
+
<HeaderIcon
|
|
68
|
+
label="Settings"
|
|
69
|
+
icon={({ color, size }) => <SymbolView name="gearshape" size={size} tintColor={color} />}
|
|
70
|
+
onPress={() => router.push("/settings")}
|
|
71
|
+
/>
|
|
72
|
+
</HeaderGroup>
|
|
73
|
+
),
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
To get two separate glass circles instead of one shared capsule, each button has to be its own native bar button item, which needs the native bar-button-items API in your Expo Router or react-native-screens version.
|
|
77
|
+
|
|
78
|
+
## Full layout
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
// app/new-activity/_layout.tsx
|
|
82
|
+
import {
|
|
83
|
+
HeaderCapsule,
|
|
84
|
+
HeaderGroup,
|
|
85
|
+
HeaderIcon,
|
|
86
|
+
type HeaderButtonIcon,
|
|
87
|
+
useThemeColor,
|
|
88
|
+
} from "@studio-piot/native-ui";
|
|
89
|
+
import { router, Stack } from "expo-router";
|
|
90
|
+
import { SFSymbol, SymbolView } from "expo-symbols";
|
|
91
|
+
|
|
92
|
+
const symbol =
|
|
93
|
+
(name: SFSymbol): HeaderButtonIcon =>
|
|
94
|
+
({ color, size }) => <SymbolView name={name} size={size} weight="semibold" tintColor={color} />;
|
|
95
|
+
|
|
96
|
+
export default function NewActivityLayout() {
|
|
97
|
+
const background = useThemeColor("background");
|
|
98
|
+
const text = useThemeColor("text");
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<Stack
|
|
102
|
+
screenOptions={{
|
|
103
|
+
headerTintColor: text,
|
|
104
|
+
headerTitleStyle: { color: text },
|
|
105
|
+
headerStyle: { backgroundColor: background },
|
|
106
|
+
headerShadowVisible: false,
|
|
107
|
+
contentStyle: { backgroundColor: background },
|
|
108
|
+
}}
|
|
109
|
+
>
|
|
110
|
+
<Stack.Screen
|
|
111
|
+
name="index"
|
|
112
|
+
options={{
|
|
113
|
+
title: "New activity",
|
|
114
|
+
headerBackVisible: false,
|
|
115
|
+
headerLeft: () => (
|
|
116
|
+
<HeaderCapsule label="Close" icon={symbol("xmark")} onPress={() => router.back()} />
|
|
117
|
+
),
|
|
118
|
+
headerRight: () => (
|
|
119
|
+
<HeaderGroup>
|
|
120
|
+
<HeaderIcon
|
|
121
|
+
label="Saved routes"
|
|
122
|
+
size={19}
|
|
123
|
+
icon={symbol("bookmark")}
|
|
124
|
+
onPress={() => router.push("/new-activity/saved-routes")}
|
|
125
|
+
/>
|
|
126
|
+
<HeaderIcon
|
|
127
|
+
label="Settings"
|
|
128
|
+
icon={symbol("gearshape")}
|
|
129
|
+
onPress={() => router.push("/settings")}
|
|
130
|
+
/>
|
|
131
|
+
</HeaderGroup>
|
|
132
|
+
),
|
|
133
|
+
}}
|
|
134
|
+
/>
|
|
135
|
+
<Stack.Screen name="running" options={{ title: "Running" }} />
|
|
136
|
+
</Stack>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
A small `symbol()` helper like this keeps call sites short. Child screens keep the default back button.
|
|
142
|
+
|
|
143
|
+
**Buttons that need screen state.** Set the options in the screen file instead of the layout:
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
export default function RunningScreen() {
|
|
147
|
+
const [favourite, setFavourite] = useState(false);
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<>
|
|
151
|
+
<Stack.Screen
|
|
152
|
+
options={{
|
|
153
|
+
headerRight: () => (
|
|
154
|
+
<HeaderIcon
|
|
155
|
+
label={favourite ? "Remove favourite" : "Add favourite"}
|
|
156
|
+
icon={symbol(favourite ? "heart.fill" : "heart")}
|
|
157
|
+
onPress={() => setFavourite((f) => !f)}
|
|
158
|
+
/>
|
|
159
|
+
),
|
|
160
|
+
}}
|
|
161
|
+
/>
|
|
162
|
+
{/* screen content */}
|
|
163
|
+
</>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Android and older iOS
|
|
169
|
+
|
|
170
|
+
SF Symbols are iOS only. Pick the icon per platform inside the render function, or use an icon set that works everywhere:
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
icon={({ color, size }) =>
|
|
174
|
+
Platform.OS === "ios" ? (
|
|
175
|
+
<SymbolView name="xmark" size={size} tintColor={color} />
|
|
176
|
+
) : (
|
|
177
|
+
<MaterialIcons name="close" size={size + 4} color={color} />
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Without glass the buttons are plain icons. For a visible shape on those platforms only:
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
<HeaderIcon label="Close" icon={symbol("xmark")} fallbackBackgroundColor="#0000000F" onPress={close} />
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
On iOS 26+ `fallbackBackgroundColor` is ignored, so you never get a shape inside the glass. Inside a `HeaderGroup`, put `fallbackBackgroundColor` on the group, not on each icon. `supportsLiquidGlass(Platform.OS, Platform.Version)` is exported if you need the same check elsewhere.
|
|
189
|
+
|
|
190
|
+
## Actions
|
|
191
|
+
|
|
192
|
+
Every button takes an `onPress`, so any function works.
|
|
193
|
+
|
|
194
|
+
| Goal | Call | Notes |
|
|
195
|
+
|---|---|---|
|
|
196
|
+
| Go back one screen | `router.back()` | From the first screen of a nested stack, this closes the modal |
|
|
197
|
+
| Close the modal | `router.dismiss()` | When the stack is presented with `presentation: "modal"` |
|
|
198
|
+
| Close the whole flow from a deep screen | `router.dismissAll()` | Then `router.back()` to leave the modal |
|
|
199
|
+
| Open another screen | `router.push("/path")` | Adds to the history |
|
|
200
|
+
| Swap the current screen | `router.replace("/path")` | No back step |
|
|
201
|
+
| Open a sheet | `router.push("/sheet-route")` | Set `presentation: "formSheet"` on that route |
|
|
202
|
+
| Share | `Share.share({ message })` | From `react-native` |
|
|
203
|
+
| Toggle state | `setState(...)` | Define the button in the screen file |
|
|
204
|
+
|
|
205
|
+
**Safe close** — closes the modal whether or not there is something to go back to:
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
export function closeFlow() {
|
|
209
|
+
if (router.canDismiss()) {
|
|
210
|
+
router.dismissAll();
|
|
211
|
+
}
|
|
212
|
+
router.back();
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Confirm before discarding:**
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
function confirmClose(hasChanges: boolean) {
|
|
220
|
+
if (!hasChanges) return router.back();
|
|
221
|
+
|
|
222
|
+
Alert.alert("Discard activity?", "Your changes will be lost.", [
|
|
223
|
+
{ text: "Keep editing", style: "cancel" },
|
|
224
|
+
{ text: "Discard", style: "destructive", onPress: () => router.back() },
|
|
225
|
+
]);
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Haptic tap** — wrap `onPress`:
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
onPress={() => {
|
|
233
|
+
Haptics.selectionAsync();
|
|
234
|
+
router.back();
|
|
235
|
+
}}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Theme roles
|
|
239
|
+
|
|
240
|
+
Apps must add this key to both light and dark maps when `color` is omitted.
|
|
241
|
+
|
|
242
|
+
| Usage | Role |
|
|
243
|
+
|---|---|
|
|
244
|
+
| Icon tint and capsule label | `headerButton` |
|
|
245
|
+
|
|
246
|
+
Usually the same value as the header's `headerTintColor`.
|
|
247
|
+
|
|
248
|
+
## Props
|
|
249
|
+
|
|
250
|
+
### HeaderIcon
|
|
251
|
+
|
|
252
|
+
| Prop | Type | Default | Notes |
|
|
253
|
+
|---|---|---|---|
|
|
254
|
+
| `icon` | `HeaderButtonIcon` | — | Required. `({ color, size }) => ReactNode` |
|
|
255
|
+
| `label` | `string` | — | Required. Accessibility label |
|
|
256
|
+
| `onPress` | `() => void` | — | Required |
|
|
257
|
+
| `size` | `number` | `17` | Icon box. Range 15–20; above ~24 the icon crowds the circle |
|
|
258
|
+
| `color` | `string` | theme `headerButton` | Optional override |
|
|
259
|
+
| `fallbackBackgroundColor` | `string` | — | Circle on non-glass platforms only |
|
|
260
|
+
| `disabled` | `boolean` | `false` | 40% opacity; not pressable |
|
|
261
|
+
| `hitSlop` | `number` | `6` | Bigger tap area without changing the glass size |
|
|
262
|
+
| `style` | view style | — | Button box |
|
|
263
|
+
|
|
264
|
+
### HeaderCapsule
|
|
265
|
+
|
|
266
|
+
| Prop | Type | Default | Notes |
|
|
267
|
+
|---|---|---|---|
|
|
268
|
+
| `label` | `string` | — | Required. Shown text and accessibility label |
|
|
269
|
+
| `onPress` | `() => void` | — | Required |
|
|
270
|
+
| `icon` | `HeaderButtonIcon` | — | Optional, before the label |
|
|
271
|
+
| `iconSize` | `number` | `15` | Close to the height of the 16pt label |
|
|
272
|
+
| `fontSize` | `number` | `16` | Label weight is 600, matching system bar button text |
|
|
273
|
+
| `color` | `string` | theme `headerButton` | Optional override |
|
|
274
|
+
| `fallbackBackgroundColor` | `string` | — | Pill on non-glass platforms only |
|
|
275
|
+
| `disabled` | `boolean` | `false` | 40% opacity; not pressable |
|
|
276
|
+
| `hitSlop` | `number` | `6` | |
|
|
277
|
+
| `style` | view style | — | Button row |
|
|
278
|
+
|
|
279
|
+
### HeaderGroup
|
|
280
|
+
|
|
281
|
+
| Prop | Type | Default | Notes |
|
|
282
|
+
|---|---|---|---|
|
|
283
|
+
| `children` | `ReactNode` | — | Usually `HeaderIcon`s |
|
|
284
|
+
| `fallbackBackgroundColor` | `string` | — | Shared pill on non-glass platforms only |
|
|
285
|
+
| `style` | view style | — | Row; gap between children is 4 |
|
|
286
|
+
|
|
287
|
+
## Gotchas
|
|
288
|
+
|
|
289
|
+
- **Thin symbols look smaller.** `xmark` fills less of its box than `gearshape` at the same size; go about 1pt bigger on thin symbols.
|
|
290
|
+
- **`SymbolView` `size` is a box, not a font size.** Wide or tall symbols are shrunk to fit; check alignment on a device.
|
|
291
|
+
- **An empty `View` still shows glass.** `headerLeft: () => <View />` draws an empty circle. Hide the button with `headerLeft: undefined`.
|
|
292
|
+
|
|
293
|
+
## Imports
|
|
294
|
+
|
|
295
|
+
```ts
|
|
296
|
+
import {
|
|
297
|
+
HeaderCapsule,
|
|
298
|
+
HeaderGroup,
|
|
299
|
+
HeaderIcon,
|
|
300
|
+
HEADER_BUTTON_THEME_ROLES,
|
|
301
|
+
supportsLiquidGlass,
|
|
302
|
+
type HeaderButtonIcon,
|
|
303
|
+
type HeaderCapsuleProps,
|
|
304
|
+
type HeaderGroupProps,
|
|
305
|
+
type HeaderIconProps,
|
|
306
|
+
} from "@studio-piot/native-ui";
|
|
307
|
+
|
|
308
|
+
// Or components only:
|
|
309
|
+
import { HeaderIcon } from "@studio-piot/native-ui/components";
|
|
310
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# HeaderWash — usage
|
|
2
|
+
|
|
3
|
+
A background for a transparent native header: your screen colour, nearly opaque at the top, fading to clear at the bottom of the header. The native title and buttons sit on the wash, and content fades as it scrolls up under the bar.
|
|
4
|
+
|
|
5
|
+
Use it as the stack's `headerBackground`, together with `headerTransparent: true`:
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
// app/(app)/create-activity/_layout.tsx
|
|
9
|
+
import { HeaderWash } from "@studio-piot/native-ui";
|
|
10
|
+
import { Stack } from "expo-router";
|
|
11
|
+
|
|
12
|
+
export default function Layout() {
|
|
13
|
+
return (
|
|
14
|
+
<Stack
|
|
15
|
+
screenOptions={{
|
|
16
|
+
headerTransparent: true,
|
|
17
|
+
headerBackground: () => <HeaderWash />,
|
|
18
|
+
// iOS 26 adds its own soft edge under a transparent bar; hide it so the two don't stack.
|
|
19
|
+
scrollEdgeEffects: { top: "hidden" },
|
|
20
|
+
}}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- **Sizing and stacking come from the native stack.** With `headerTransparent: true`, the stack draws `headerBackground` above the screen content and sizes it to the header's measured height, including a large title as it collapses.
|
|
27
|
+
- **Colour.** Defaults to the `formBackground` role, so it matches `Form`. Pass `color` to match another screen.
|
|
28
|
+
- **Content.** The screen's scroll view still starts below the header (`Form` and `Page` do this), so nothing sits under the wash until you scroll.
|
|
29
|
+
|
|
30
|
+
## Props
|
|
31
|
+
|
|
32
|
+
| Prop | Type | Default | Notes |
|
|
33
|
+
|---|---|---|---|
|
|
34
|
+
| `color` | `string` | theme `formBackground` | The wash colour, opaque end |
|
|
35
|
+
|
|
36
|
+
## Imports
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { HeaderWash } from "@studio-piot/native-ui";
|
|
40
|
+
```
|