@utilitywarehouse/hearth-react-native 0.26.0 → 0.27.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/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +13 -13
- package/CHANGELOG.md +40 -0
- package/build/components/Banner/Banner.js +12 -1
- package/build/components/PillGroup/Pill.js +0 -1
- package/build/components/PillGroup/PillGroup.js +4 -1
- package/build/components/SegmentedControl/SegmentedControl.context.d.ts +14 -0
- package/build/components/SegmentedControl/SegmentedControl.context.js +9 -0
- package/build/components/SegmentedControl/SegmentedControl.d.ts +6 -0
- package/build/components/SegmentedControl/SegmentedControl.js +196 -0
- package/build/components/SegmentedControl/SegmentedControl.props.d.ts +18 -0
- package/build/components/SegmentedControl/SegmentedControl.props.js +1 -0
- package/build/components/SegmentedControl/SegmentedControlOption.d.ts +18 -0
- package/build/components/SegmentedControl/SegmentedControlOption.js +122 -0
- package/build/components/SegmentedControl/SegmentedControlOption.props.d.ts +12 -0
- package/build/components/SegmentedControl/SegmentedControlOption.props.js +1 -0
- package/build/components/SegmentedControl/index.d.ts +4 -0
- package/build/components/SegmentedControl/index.js +2 -0
- package/build/components/index.d.ts +1 -0
- package/build/components/index.js +1 -0
- package/docs/changelog.mdx +136 -0
- package/docs/components/AllComponents.web.tsx +14 -0
- package/package.json +4 -4
- package/src/components/Banner/Banner.tsx +12 -1
- package/src/components/PillGroup/Pill.tsx +0 -1
- package/src/components/PillGroup/PillGroup.tsx +4 -0
- package/src/components/SegmentedControl/SegmentedControl.context.ts +22 -0
- package/src/components/SegmentedControl/SegmentedControl.docs.mdx +90 -0
- package/src/components/SegmentedControl/SegmentedControl.figma.tsx +40 -0
- package/src/components/SegmentedControl/SegmentedControl.props.ts +20 -0
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +77 -0
- package/src/components/SegmentedControl/SegmentedControl.tsx +257 -0
- package/src/components/SegmentedControl/SegmentedControlOption.props.ts +14 -0
- package/src/components/SegmentedControl/SegmentedControlOption.tsx +213 -0
- package/src/components/SegmentedControl/index.ts +4 -0
- package/src/components/index.ts +1 -0
package/docs/changelog.mdx
CHANGED
|
@@ -9,6 +9,142 @@ import { BackToTopButton } from './components';
|
|
|
9
9
|
The changelog for the Hearth React Native library. Here you can find all the changes, improvements, and bug fixes for each version.
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
## 0.25.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- [#982](https://github.com/utilitywarehouse/hearth/pull/982) [`506b388`](https://github.com/utilitywarehouse/hearth/commit/506b388ae1ef1065f013024a14bd9e2599a6442d) Thanks [@jordmccord](https://github.com/jordmccord)! - 🌟 [FEATURE]: Add `TimePicker` and `TimePickerInput` components with 12/24-hour support and minute intervals.
|
|
17
|
+
|
|
18
|
+
Includes a shared time picker view, updated wheel behavior for native platforms, and polished visuals like gradient fades.
|
|
19
|
+
|
|
20
|
+
**Components affected**:
|
|
21
|
+
- `TimePicker`
|
|
22
|
+
- `TimePickerInput`
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import { TimePicker, TimePickerInput } from '@utilitywarehouse/hearth-react-native';
|
|
26
|
+
import { useRef, useState } from 'react';
|
|
27
|
+
import type { DateType } from '@utilitywarehouse/hearth-react-native';
|
|
28
|
+
|
|
29
|
+
const Example = () => {
|
|
30
|
+
const [value, setValue] = useState<DateType>();
|
|
31
|
+
const pickerRef = useRef(null);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<>
|
|
35
|
+
<TimePickerInput
|
|
36
|
+
value={value}
|
|
37
|
+
onChange={({ date }) => setValue(date ?? undefined)}
|
|
38
|
+
onClear={() => setValue(undefined)}
|
|
39
|
+
timePickerProps={{ use12Hours: true, minuteInterval: 5 }}
|
|
40
|
+
/>
|
|
41
|
+
<TimePicker
|
|
42
|
+
ref={pickerRef}
|
|
43
|
+
date={value}
|
|
44
|
+
onChange={({ date }) => setValue(date)}
|
|
45
|
+
use12Hours
|
|
46
|
+
minuteInterval={5}
|
|
47
|
+
/>
|
|
48
|
+
</>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 0.24.0
|
|
54
|
+
|
|
55
|
+
### Minor Changes
|
|
56
|
+
|
|
57
|
+
- [#977](https://github.com/utilitywarehouse/hearth/pull/977) [`9d2b534`](https://github.com/utilitywarehouse/hearth/commit/9d2b5348a5748cb613f537808069de2e86bd21d7) Thanks [@jordmccord](https://github.com/jordmccord)! - 🌟 [FEATURE]: Add `ProgressBar` component with linear and circular variants.
|
|
58
|
+
|
|
59
|
+
**Developer changes**:
|
|
60
|
+
|
|
61
|
+
Use `ProgressBar` with a default percentage label, or override the label to show a custom value:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { ProgressBar } from '@utilitywarehouse/hearth-react-native';
|
|
65
|
+
|
|
66
|
+
<ProgressBar value={42} label="Uploading documents" />
|
|
67
|
+
|
|
68
|
+
<ProgressBar
|
|
69
|
+
value={68}
|
|
70
|
+
max={100}
|
|
71
|
+
label="Data allowance"
|
|
72
|
+
variant="circular"
|
|
73
|
+
formatValueText={(value, { max }) => `${max - value}GB remaining`}
|
|
74
|
+
/>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Patch Changes
|
|
78
|
+
|
|
79
|
+
- [#978](https://github.com/utilitywarehouse/hearth/pull/978) [`26a1173`](https://github.com/utilitywarehouse/hearth/commit/26a11731a493a8b92ac2a3a183516376ab54663b) Thanks [@jordmccord](https://github.com/jordmccord)! - 💅 [ENHANCEMENT]: Tighten `Modal` prop types and fix brand background text styling
|
|
80
|
+
|
|
81
|
+
Improves TypeScript safety so `stickyFooter` is not allowed when `inNavModal` is true, and `background` can only be set when `inNavModal` is true. Also ensures headings, body text, and button content are correctly inverted when using the brand background.
|
|
82
|
+
|
|
83
|
+
**Components affected**:
|
|
84
|
+
- `Modal`
|
|
85
|
+
|
|
86
|
+
**Developer changes**:
|
|
87
|
+
No changes required unless you were relying on invalid prop combinations.
|
|
88
|
+
|
|
89
|
+
## 0.23.0
|
|
90
|
+
|
|
91
|
+
### Minor Changes
|
|
92
|
+
|
|
93
|
+
- [#975](https://github.com/utilitywarehouse/hearth/pull/975) [`102f04e`](https://github.com/utilitywarehouse/hearth/commit/102f04e0d560cf0faa21da5020c230e88e857251) Thanks [@jordmccord](https://github.com/jordmccord)! - 🌟 [FEATURE]: Add a `background` option for Modal when used inside navigation modals
|
|
94
|
+
|
|
95
|
+
Modal now supports a `background` prop with `default` and `brand` values. When `background="brand"` is used in a navigation modal, the buttons and close icon invert for contrast, and the content area is scrollable.
|
|
96
|
+
|
|
97
|
+
**Components affected**:
|
|
98
|
+
- `Modal`
|
|
99
|
+
|
|
100
|
+
**Developer changes**:
|
|
101
|
+
|
|
102
|
+
No changes required. To opt in to the brand background:
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<Modal background="brand" inNavModal>
|
|
106
|
+
...
|
|
107
|
+
</Modal>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 0.22.1
|
|
111
|
+
|
|
112
|
+
### Patch Changes
|
|
113
|
+
|
|
114
|
+
- [#971](https://github.com/utilitywarehouse/hearth/pull/971) [`be1dfeb`](https://github.com/utilitywarehouse/hearth/commit/be1dfebd4b43f2df8ef6c5eaa42a88364e796479) Thanks [@jordmccord](https://github.com/jordmccord)! - 💅 [ENHANCEMENT]: Improve VerificationInput OTP handling and accessibility
|
|
115
|
+
|
|
116
|
+
VerificationInput now uses a single hidden input to manage focus, selection, and paste behaviour across platforms, improving caret handling and bulk entry. Accessibility labels and hints are now derived from the form field to provide clearer screen reader output.
|
|
117
|
+
|
|
118
|
+
**Components affected**:
|
|
119
|
+
- `VerificationInput`
|
|
120
|
+
|
|
121
|
+
**Developer changes**:
|
|
122
|
+
|
|
123
|
+
No changes required.
|
|
124
|
+
|
|
125
|
+
## 0.22.0
|
|
126
|
+
|
|
127
|
+
### Minor Changes
|
|
128
|
+
|
|
129
|
+
- [#968](https://github.com/utilitywarehouse/hearth/pull/968) [`cee5811`](https://github.com/utilitywarehouse/hearth/commit/cee5811020af02fe754d8311ec8313c1793f108a) Thanks [@jordmccord](https://github.com/jordmccord)! - 🌟 [FEATURE]: Add `badge` support to Radio and Checkbox (including tiles).
|
|
130
|
+
|
|
131
|
+
**Components affected**:
|
|
132
|
+
- `Radio`
|
|
133
|
+
- `RadioTile`
|
|
134
|
+
- `Checkbox`
|
|
135
|
+
- `CheckboxTile`
|
|
136
|
+
|
|
137
|
+
**Developer changes**:
|
|
138
|
+
You can now pass a `badge` React node to render beneath helper text. No changes required unless you want to use the new prop.
|
|
139
|
+
|
|
140
|
+
### Patch Changes
|
|
141
|
+
|
|
142
|
+
- [#966](https://github.com/utilitywarehouse/hearth/pull/966) [`4e9f3f0`](https://github.com/utilitywarehouse/hearth/commit/4e9f3f0284e50da5ba4e49e132dac745a1a8a68d) Thanks [@jordmccord](https://github.com/jordmccord)! - 🐛 [FIX]: Allow Card layout props and remove forced alignment
|
|
143
|
+
|
|
144
|
+
Card now accepts flex layout and display props, and it no longer forces `alignItems: flex-start` on the root, so custom alignment works as expected.
|
|
145
|
+
|
|
146
|
+
- [#969](https://github.com/utilitywarehouse/hearth/pull/969) [`c5c988b`](https://github.com/utilitywarehouse/hearth/commit/c5c988b65f1133b85b822037b086a524bc1255e3) Thanks [@jordmccord](https://github.com/jordmccord)! - 🐛 [FIX]: Render the Modal footer in navigation modals
|
|
147
|
+
|
|
12
148
|
## 0.21.0
|
|
13
149
|
|
|
14
150
|
### Minor Changes
|
|
@@ -82,6 +82,8 @@ import {
|
|
|
82
82
|
RadioCardGroup,
|
|
83
83
|
RadioGroup,
|
|
84
84
|
SectionHeader,
|
|
85
|
+
SegmentedControl,
|
|
86
|
+
SegmentedControlOption,
|
|
85
87
|
Select,
|
|
86
88
|
Skeleton,
|
|
87
89
|
Spinner,
|
|
@@ -743,6 +745,18 @@ const AllComponents: React.FC = () => {
|
|
|
743
745
|
/>
|
|
744
746
|
</Center>
|
|
745
747
|
</ComponentWrapper>
|
|
748
|
+
<ComponentWrapper
|
|
749
|
+
name="Segmented Control"
|
|
750
|
+
link="/?path=/docs/components-segmented-control--docs"
|
|
751
|
+
>
|
|
752
|
+
<Center flex={1}>
|
|
753
|
+
<SegmentedControl defaultValue="day" alignSelf="center">
|
|
754
|
+
<SegmentedControlOption value="day">Day</SegmentedControlOption>
|
|
755
|
+
<SegmentedControlOption value="week">Week</SegmentedControlOption>
|
|
756
|
+
<SegmentedControlOption value="month">Month</SegmentedControlOption>
|
|
757
|
+
</SegmentedControl>
|
|
758
|
+
</Center>
|
|
759
|
+
</ComponentWrapper>
|
|
746
760
|
<ComponentWrapper name="Select" link="/?path=/docs/forms-select--docs">
|
|
747
761
|
<Center flex={1}>
|
|
748
762
|
<BottomSheetModalProvider>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@utilitywarehouse/hearth-react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "Utility Warehouse React Native UI library",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -57,10 +57,10 @@
|
|
|
57
57
|
"vite-plugin-svgr": "^4.5.0",
|
|
58
58
|
"vitest": "^3.2.4",
|
|
59
59
|
"@utilitywarehouse/hearth-fonts": "^0.0.4",
|
|
60
|
-
"@utilitywarehouse/hearth-react-icons": "^0.8.0",
|
|
61
|
-
"@utilitywarehouse/hearth-svg-assets": "^0.5.0",
|
|
62
60
|
"@utilitywarehouse/hearth-react-native-icons": "^0.8.0",
|
|
63
|
-
"@utilitywarehouse/hearth-
|
|
61
|
+
"@utilitywarehouse/hearth-svg-assets": "^0.5.0",
|
|
62
|
+
"@utilitywarehouse/hearth-tokens": "^0.2.3",
|
|
63
|
+
"@utilitywarehouse/hearth-react-icons": "^0.8.0"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
66
|
"@gorhom/bottom-sheet": "^5.0.0",
|
|
@@ -29,7 +29,7 @@ const Banner = ({
|
|
|
29
29
|
...props
|
|
30
30
|
}: BannerProps) => {
|
|
31
31
|
const hasIllustration = Boolean(illustration);
|
|
32
|
-
styles.useVariants({ direction, hasIllustration });
|
|
32
|
+
styles.useVariants({ direction, hasIllustration, isPressable: Boolean(onPress) });
|
|
33
33
|
|
|
34
34
|
const context = useMemo(
|
|
35
35
|
() => ({
|
|
@@ -174,6 +174,10 @@ const styles = StyleSheet.create(theme => ({
|
|
|
174
174
|
true: {},
|
|
175
175
|
false: {},
|
|
176
176
|
},
|
|
177
|
+
isPressable: {
|
|
178
|
+
true: {},
|
|
179
|
+
false: {},
|
|
180
|
+
},
|
|
177
181
|
},
|
|
178
182
|
compoundVariants: [
|
|
179
183
|
{
|
|
@@ -190,6 +194,13 @@ const styles = StyleSheet.create(theme => ({
|
|
|
190
194
|
alignItems: 'center',
|
|
191
195
|
},
|
|
192
196
|
},
|
|
197
|
+
{
|
|
198
|
+
direction: 'horizontal',
|
|
199
|
+
isPressable: false,
|
|
200
|
+
styles: {
|
|
201
|
+
flex: 1,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
193
204
|
],
|
|
194
205
|
},
|
|
195
206
|
media: {
|
|
@@ -42,6 +42,7 @@ export const PillGroup = ({
|
|
|
42
42
|
) : (
|
|
43
43
|
<ScrollView
|
|
44
44
|
horizontal
|
|
45
|
+
style={styles.scrollView}
|
|
45
46
|
contentContainerStyle={[styles.group, style]}
|
|
46
47
|
showsHorizontalScrollIndicator={false}
|
|
47
48
|
{...props}
|
|
@@ -56,6 +57,9 @@ export const PillGroup = ({
|
|
|
56
57
|
PillGroup.displayName = 'PillGroup';
|
|
57
58
|
|
|
58
59
|
const styles = StyleSheet.create(theme => ({
|
|
60
|
+
scrollView: {
|
|
61
|
+
flexGrow: 0,
|
|
62
|
+
},
|
|
59
63
|
group: {
|
|
60
64
|
flexDirection: 'row',
|
|
61
65
|
gap: theme.components.pill.group.gap,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
export type SegmentedControlContextValue = {
|
|
4
|
+
value?: string;
|
|
5
|
+
select: (value: string) => void;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
size: 'sm' | 'md';
|
|
8
|
+
registerOptionLayout: (
|
|
9
|
+
value: string,
|
|
10
|
+
layout: { x: number; y: number; width: number; height: number }
|
|
11
|
+
) => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const SegmentedControlContext = createContext<SegmentedControlContextValue | null>(null);
|
|
15
|
+
|
|
16
|
+
export const useSegmentedControlContext = () => {
|
|
17
|
+
const context = useContext(SegmentedControlContext);
|
|
18
|
+
if (!context) {
|
|
19
|
+
throw new Error('SegmentedControlOption must be used within SegmentedControl');
|
|
20
|
+
}
|
|
21
|
+
return context;
|
|
22
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Canvas, Controls, Meta } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import { SegmentedControl, SegmentedControlOption } from '../../';
|
|
3
|
+
import { BackToTopButton, UsageWrap, ViewFigmaButton } from '../../../docs/components';
|
|
4
|
+
import * as Stories from './SegmentedControl.stories';
|
|
5
|
+
|
|
6
|
+
<Meta title="Components / Segmented Control" />
|
|
7
|
+
|
|
8
|
+
<BackToTopButton />
|
|
9
|
+
|
|
10
|
+
<ViewFigmaButton url="https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=6185-1021&t=c7xg5X0N2EL0t87h-4" />
|
|
11
|
+
|
|
12
|
+
# Segmented Control
|
|
13
|
+
|
|
14
|
+
Segmented Control lets users switch between a small set of related options.
|
|
15
|
+
Each option is presented as an equal-priority segment in a single horizontal group.
|
|
16
|
+
|
|
17
|
+
- [Playground](#playground)
|
|
18
|
+
- [Usage](#usage)
|
|
19
|
+
- [Sizes](#sizes)
|
|
20
|
+
- [Props](#props)
|
|
21
|
+
- [Accessibility](#accessibility)
|
|
22
|
+
|
|
23
|
+
## Playground
|
|
24
|
+
|
|
25
|
+
<Canvas of={Stories.Playground} />
|
|
26
|
+
|
|
27
|
+
<Controls of={Stories.Playground} />
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
<UsageWrap>
|
|
32
|
+
<SegmentedControl defaultValue="day">
|
|
33
|
+
<SegmentedControlOption value="day">Day</SegmentedControlOption>
|
|
34
|
+
<SegmentedControlOption value="week">Week</SegmentedControlOption>
|
|
35
|
+
<SegmentedControlOption value="month">Month</SegmentedControlOption>
|
|
36
|
+
</SegmentedControl>
|
|
37
|
+
</UsageWrap>
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import { SegmentedControl, SegmentedControlOption } from '@utilitywarehouse/hearth-react-native';
|
|
41
|
+
|
|
42
|
+
const Example = () => {
|
|
43
|
+
return (
|
|
44
|
+
<SegmentedControl defaultValue="day">
|
|
45
|
+
<SegmentedControlOption value="day">Day</SegmentedControlOption>
|
|
46
|
+
<SegmentedControlOption value="week">Week</SegmentedControlOption>
|
|
47
|
+
<SegmentedControlOption value="month">Month</SegmentedControlOption>
|
|
48
|
+
</SegmentedControl>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Sizes
|
|
54
|
+
|
|
55
|
+
Figma defines two size variants for Segmented Control:
|
|
56
|
+
|
|
57
|
+
- `sm` maps to `SM-32`
|
|
58
|
+
- `md` maps to `MD-48`
|
|
59
|
+
|
|
60
|
+
<Canvas of={Stories.Sizes} />
|
|
61
|
+
|
|
62
|
+
## Props
|
|
63
|
+
|
|
64
|
+
### SegmentedControl
|
|
65
|
+
|
|
66
|
+
| Property | Type | Description | Default |
|
|
67
|
+
| --------------- | ------------------------- | -------------------------------------- | ------------ |
|
|
68
|
+
| `value` | `string` | Controlled selected option value. | - |
|
|
69
|
+
| `defaultValue` | `string` | Initial selected value (uncontrolled). | first option |
|
|
70
|
+
| `onValueChange` | `(value: string) => void` | Called when selected option changes. | - |
|
|
71
|
+
| `size` | `'sm' \| 'md'` | Size variant (`SM-32` / `MD-48`). | `'sm'` |
|
|
72
|
+
| `disabled` | `boolean` | Disables all options in the group. | `false` |
|
|
73
|
+
| `children` | `ReactNode` | `SegmentedControlOption` children. | required |
|
|
74
|
+
|
|
75
|
+
### SegmentedControlOption
|
|
76
|
+
|
|
77
|
+
| Property | Type | Description | Default |
|
|
78
|
+
| ---------- | ----------- | ------------------------------ | -------- |
|
|
79
|
+
| `value` | `string` | Unique value for this segment. | required |
|
|
80
|
+
| `children` | `ReactNode` | Option label/content. | required |
|
|
81
|
+
| `disabled` | `boolean` | Disables only this option. | `false` |
|
|
82
|
+
|
|
83
|
+
## Accessibility
|
|
84
|
+
|
|
85
|
+
SegmentedControl uses radio semantics so assistive technologies can understand it as a single-choice group.
|
|
86
|
+
|
|
87
|
+
- SegmentedControl root uses `accessibilityRole="radiogroup"`.
|
|
88
|
+
- Each SegmentedControlOption uses `accessibilityRole="radio"`.
|
|
89
|
+
- Option state is communicated with `accessibilityState={{ checked, disabled }}`.
|
|
90
|
+
- If `accessibilityLabel` is not provided on an option, the component falls back to the option text content and then to the option `value`.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import figma from '@figma/code-connect';
|
|
2
|
+
import { SegmentedControl, SegmentedControlOption } from '../';
|
|
3
|
+
|
|
4
|
+
figma.connect(
|
|
5
|
+
SegmentedControl,
|
|
6
|
+
'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=6185-1021&t=c7xg5X0N2EL0t87h-4',
|
|
7
|
+
{
|
|
8
|
+
props: {
|
|
9
|
+
size: figma.enum('Size', {
|
|
10
|
+
'SM-32': 'sm',
|
|
11
|
+
'MD-48': 'md',
|
|
12
|
+
}),
|
|
13
|
+
disabled: figma.enum('State', {
|
|
14
|
+
Disabled: true,
|
|
15
|
+
}),
|
|
16
|
+
options: figma.children('Option'),
|
|
17
|
+
},
|
|
18
|
+
example: props => (
|
|
19
|
+
<SegmentedControl defaultValue="option-1" size={props.size} disabled={props.disabled}>
|
|
20
|
+
{props.options}
|
|
21
|
+
</SegmentedControl>
|
|
22
|
+
),
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
figma.connect(
|
|
27
|
+
SegmentedControlOption,
|
|
28
|
+
'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=4340-1252&t=c7xg5X0N2EL0t87h-4',
|
|
29
|
+
{
|
|
30
|
+
props: {
|
|
31
|
+
label: figma.string('Label'),
|
|
32
|
+
value: figma.string('Value'),
|
|
33
|
+
},
|
|
34
|
+
example: props => (
|
|
35
|
+
<SegmentedControlOption value={props.value ?? 'option'}>
|
|
36
|
+
{props.label ?? 'Option'}
|
|
37
|
+
</SegmentedControlOption>
|
|
38
|
+
),
|
|
39
|
+
}
|
|
40
|
+
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { ViewProps } from 'react-native';
|
|
3
|
+
import type { FlexLayoutProps } from '../../types';
|
|
4
|
+
|
|
5
|
+
export interface SegmentedControlProps extends ViewProps, FlexLayoutProps {
|
|
6
|
+
/** Controlled selected option value. */
|
|
7
|
+
value?: string;
|
|
8
|
+
/** Initial selected option value for uncontrolled mode. */
|
|
9
|
+
defaultValue?: string;
|
|
10
|
+
/** Called when selected option changes. */
|
|
11
|
+
onValueChange?: (value: string) => void;
|
|
12
|
+
/** Size variant. */
|
|
13
|
+
size?: 'sm' | 'md';
|
|
14
|
+
/** Disables all options in the control. */
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
/** SegmentedControlOption children. */
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default SegmentedControlProps;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { BodyText, Flex, SegmentedControl, SegmentedControlOption } from '../';
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Stories / Segmented Control',
|
|
6
|
+
component: SegmentedControl,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
args: {
|
|
11
|
+
size: 'sm',
|
|
12
|
+
disabled: false,
|
|
13
|
+
},
|
|
14
|
+
argTypes: {
|
|
15
|
+
size: {
|
|
16
|
+
control: 'radio',
|
|
17
|
+
options: ['sm', 'md'],
|
|
18
|
+
},
|
|
19
|
+
disabled: {
|
|
20
|
+
control: 'boolean',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default meta;
|
|
26
|
+
|
|
27
|
+
export const Playground = {
|
|
28
|
+
render: (args: { size?: 'sm' | 'md'; disabled?: boolean }) => (
|
|
29
|
+
<SegmentedControl defaultValue="day" {...args}>
|
|
30
|
+
<SegmentedControlOption value="day">Day</SegmentedControlOption>
|
|
31
|
+
<SegmentedControlOption value="week">Week</SegmentedControlOption>
|
|
32
|
+
<SegmentedControlOption value="month">Month</SegmentedControlOption>
|
|
33
|
+
</SegmentedControl>
|
|
34
|
+
),
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const Sizes = {
|
|
38
|
+
render: () => (
|
|
39
|
+
<Flex spacing="sm" align="center">
|
|
40
|
+
<SegmentedControl defaultValue="one" size="sm">
|
|
41
|
+
<SegmentedControlOption value="one">Label</SegmentedControlOption>
|
|
42
|
+
<SegmentedControlOption value="two">Label</SegmentedControlOption>
|
|
43
|
+
<SegmentedControlOption value="three">Label</SegmentedControlOption>
|
|
44
|
+
</SegmentedControl>
|
|
45
|
+
<SegmentedControl defaultValue="one" size="md">
|
|
46
|
+
<SegmentedControlOption value="one">Label</SegmentedControlOption>
|
|
47
|
+
<SegmentedControlOption value="two">Label</SegmentedControlOption>
|
|
48
|
+
<SegmentedControlOption value="three">Label</SegmentedControlOption>
|
|
49
|
+
</SegmentedControl>
|
|
50
|
+
</Flex>
|
|
51
|
+
),
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const Controlled = {
|
|
55
|
+
render: () => {
|
|
56
|
+
const [value, setValue] = useState('annual');
|
|
57
|
+
return (
|
|
58
|
+
<Flex spacing="sm" align="center">
|
|
59
|
+
<SegmentedControl value={value} onValueChange={setValue}>
|
|
60
|
+
<SegmentedControlOption value="monthly">Monthly</SegmentedControlOption>
|
|
61
|
+
<SegmentedControlOption value="annual">Annual</SegmentedControlOption>
|
|
62
|
+
</SegmentedControl>
|
|
63
|
+
<BodyText size="sm">Selected: {value}</BodyText>
|
|
64
|
+
</Flex>
|
|
65
|
+
);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const Disabled = {
|
|
70
|
+
render: () => (
|
|
71
|
+
<SegmentedControl defaultValue="left" disabled>
|
|
72
|
+
<SegmentedControlOption value="left">Left</SegmentedControlOption>
|
|
73
|
+
<SegmentedControlOption value="center">Center</SegmentedControlOption>
|
|
74
|
+
<SegmentedControlOption value="right">Right</SegmentedControlOption>
|
|
75
|
+
</SegmentedControl>
|
|
76
|
+
),
|
|
77
|
+
};
|