@utilitywarehouse/hearth-react-native 0.8.1 → 0.9.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/.storybook/preview.tsx +1 -0
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +24 -0
- package/build/components/Banner/Banner.js +49 -10
- package/build/components/Banner/Banner.props.d.ts +4 -9
- package/build/components/BottomSheet/BottomSheetHandle.js +8 -0
- package/build/components/Card/Card.props.d.ts +1 -0
- package/build/components/Card/CardRoot.d.ts +1 -1
- package/build/components/Card/CardRoot.js +28 -1
- package/build/components/HighlightBanner/HighlightBanner.props.d.ts +1 -1
- package/build/components/List/List.js +1 -1
- package/build/components/List/ListAction/ListActionTrailingIcon.js +2 -2
- package/build/components/Menu/Menu.context.d.ts +5 -0
- package/build/components/Menu/Menu.context.js +9 -0
- package/build/components/Menu/Menu.d.ts +4 -0
- package/build/components/Menu/Menu.js +25 -0
- package/build/components/Menu/Menu.props.d.ts +21 -0
- package/build/components/Menu/Menu.props.js +1 -0
- package/build/components/Menu/MenuItem.d.ts +18 -0
- package/build/components/Menu/MenuItem.js +115 -0
- package/build/components/Menu/MenuItem.props.d.ts +27 -0
- package/build/components/Menu/MenuItem.props.js +1 -0
- package/build/components/Menu/MenuTrigger.d.ts +9 -0
- package/build/components/Menu/MenuTrigger.js +11 -0
- package/build/components/Menu/MenuTrigger.props.d.ts +12 -0
- package/build/components/Menu/MenuTrigger.props.js +1 -0
- package/build/components/Menu/index.d.ts +7 -0
- package/build/components/Menu/index.js +4 -0
- package/build/components/Modal/Modal.d.ts +1 -1
- package/build/components/Modal/Modal.js +32 -30
- package/build/components/Modal/Modal.props.d.ts +1 -0
- package/build/components/Modal/Modal.web.d.ts +1 -1
- package/build/components/Modal/Modal.web.js +25 -25
- package/build/components/RadioCard/RadioCardGroup.context.d.ts +12 -0
- package/build/components/RadioCard/RadioCardGroup.context.js +3 -0
- package/build/components/RadioCard/RadioCardGroup.js +15 -10
- package/build/components/RadioCard/RadioCardLabel.d.ts +1 -1
- package/build/components/RadioCard/RadioCardLabel.js +7 -1
- package/build/components/RadioCard/RadioCardRoot.js +13 -0
- package/build/components/index.d.ts +1 -0
- package/build/components/index.js +1 -0
- package/build/core/themes.d.ts +40 -0
- package/build/core/themes.js +20 -0
- package/build/tokens/components/dark/index.d.ts +3 -1
- package/build/tokens/components/dark/index.js +3 -1
- package/build/tokens/components/dark/input.d.ts +3 -0
- package/build/tokens/components/dark/input.js +3 -0
- package/build/tokens/components/dark/modal.d.ts +7 -4
- package/build/tokens/components/dark/modal.js +7 -4
- package/build/tokens/components/dark/rating.d.ts +8 -0
- package/build/tokens/components/dark/rating.js +7 -0
- package/build/tokens/components/dark/table.d.ts +0 -3
- package/build/tokens/components/dark/table.js +0 -3
- package/build/tokens/components/dark/time-picker.d.ts +29 -0
- package/build/tokens/components/dark/time-picker.js +28 -0
- package/build/tokens/components/dark/timeline.d.ts +27 -0
- package/build/tokens/components/dark/timeline.js +26 -0
- package/build/tokens/components/light/index.d.ts +3 -1
- package/build/tokens/components/light/index.js +3 -1
- package/build/tokens/components/light/input.d.ts +3 -0
- package/build/tokens/components/light/input.js +3 -0
- package/build/tokens/components/light/modal.d.ts +7 -4
- package/build/tokens/components/light/modal.js +7 -4
- package/build/tokens/components/light/rating.d.ts +8 -0
- package/build/tokens/components/light/rating.js +7 -0
- package/build/tokens/components/light/table.d.ts +0 -3
- package/build/tokens/components/light/table.js +0 -3
- package/build/tokens/components/light/time-picker.d.ts +29 -0
- package/build/tokens/components/light/time-picker.js +28 -0
- package/build/tokens/components/light/timeline.d.ts +27 -0
- package/build/tokens/components/light/timeline.js +26 -0
- package/docs/adding-shadows.mdx +43 -0
- package/docs/components/AllComponents.web.tsx +33 -0
- package/docs/components/BackToTopButton.tsx +1 -1
- package/package.json +3 -3
- package/src/components/Banner/Banner.docs.mdx +20 -11
- package/src/components/Banner/Banner.props.ts +4 -9
- package/src/components/Banner/Banner.stories.tsx +17 -4
- package/src/components/Banner/Banner.tsx +92 -37
- package/src/components/BottomSheet/BottomSheetHandle.tsx +12 -0
- package/src/components/Card/Card.docs.mdx +20 -1
- package/src/components/Card/Card.props.ts +9 -0
- package/src/components/Card/Card.stories.tsx +39 -0
- package/src/components/Card/CardRoot.tsx +29 -0
- package/src/components/Checkbox/CheckboxGroup.stories.tsx +19 -1
- package/src/components/DatePickerInput/DatePickerInput.docs.mdx +1 -1
- package/src/components/HighlightBanner/HighlightBanner.docs.mdx +1 -1
- package/src/components/HighlightBanner/HighlightBanner.props.ts +1 -0
- package/src/components/HighlightBanner/HighlightBanner.stories.tsx +15 -1
- package/src/components/List/List.tsx +5 -3
- package/src/components/List/ListAction/ListActionTrailingIcon.tsx +2 -2
- package/src/components/Menu/Menu.context.ts +15 -0
- package/src/components/Menu/Menu.docs.mdx +158 -0
- package/src/components/Menu/Menu.props.ts +24 -0
- package/src/components/Menu/Menu.stories.tsx +292 -0
- package/src/components/Menu/Menu.tsx +54 -0
- package/src/components/Menu/MenuItem.props.ts +29 -0
- package/src/components/Menu/MenuItem.tsx +145 -0
- package/src/components/Menu/MenuTrigger.props.ts +14 -0
- package/src/components/Menu/MenuTrigger.tsx +20 -0
- package/src/components/Menu/index.ts +7 -0
- package/src/components/Modal/Modal.docs.mdx +34 -5
- package/src/components/Modal/Modal.props.ts +1 -0
- package/src/components/Modal/Modal.stories.tsx +46 -0
- package/src/components/Modal/Modal.tsx +37 -33
- package/src/components/Modal/Modal.web.tsx +27 -27
- package/src/components/Radio/RadioGroup.stories.tsx +18 -0
- package/src/components/RadioCard/RadioCardGroup.context.ts +16 -0
- package/src/components/RadioCard/RadioCardGroup.stories.tsx +24 -0
- package/src/components/RadioCard/RadioCardGroup.tsx +28 -19
- package/src/components/RadioCard/RadioCardLabel.tsx +12 -1
- package/src/components/RadioCard/RadioCardRoot.tsx +15 -0
- package/src/components/index.ts +1 -0
- package/src/core/themes.ts +20 -0
- package/src/tokens/components/dark/index.ts +3 -1
- package/src/tokens/components/dark/input.ts +3 -0
- package/src/tokens/components/dark/modal.ts +7 -4
- package/src/tokens/components/dark/rating.ts +8 -0
- package/src/tokens/components/dark/table.ts +0 -3
- package/src/tokens/components/dark/time-picker.ts +29 -0
- package/src/tokens/components/dark/timeline.ts +27 -0
- package/src/tokens/components/light/index.ts +3 -1
- package/src/tokens/components/light/input.ts +3 -0
- package/src/tokens/components/light/modal.ts +7 -4
- package/src/tokens/components/light/rating.ts +8 -0
- package/src/tokens/components/light/table.ts +0 -3
- package/src/tokens/components/light/time-picker.ts +29 -0
- package/src/tokens/components/light/timeline.ts +27 -0
- package/build/tokens/components/dark/dialog.d.ts +0 -25
- package/build/tokens/components/dark/dialog.js +0 -24
- package/build/tokens/components/light/dialog.d.ts +0 -25
- package/build/tokens/components/light/dialog.js +0 -24
- package/src/tokens/components/dark/dialog.ts +0 -25
- package/src/tokens/components/light/dialog.ts +0 -25
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ComponentType, ReactElement } from 'react';
|
|
2
|
-
import
|
|
2
|
+
import { ImageProps } from 'react-native';
|
|
3
3
|
import type CardProps from '../Card/Card.props';
|
|
4
|
+
import { ThemedImageProps } from '../ThemedImage';
|
|
4
5
|
|
|
5
6
|
export type BannerDirection = 'horizontal' | 'vertical';
|
|
6
7
|
|
|
@@ -50,18 +51,12 @@ export interface BannerProps
|
|
|
50
51
|
* Illustration to display in the banner
|
|
51
52
|
* Mutually exclusive with icon and image
|
|
52
53
|
*/
|
|
53
|
-
illustration?:
|
|
54
|
-
light: ImageSourcePropType | ReactElement | ComponentType;
|
|
55
|
-
dark: ImageSourcePropType | ReactElement | ComponentType;
|
|
56
|
-
};
|
|
54
|
+
illustration?: ThemedImageProps | ImageProps;
|
|
57
55
|
/**
|
|
58
56
|
* Image to display in the banner
|
|
59
57
|
* Mutually exclusive with icon and illustration
|
|
60
58
|
*/
|
|
61
|
-
image?:
|
|
62
|
-
light: ImageSourcePropType | ReactElement | ComponentType;
|
|
63
|
-
dark: ImageSourcePropType | ReactElement | ComponentType;
|
|
64
|
-
};
|
|
59
|
+
image?: ThemedImageProps | ImageProps;
|
|
65
60
|
/**
|
|
66
61
|
* Heading text
|
|
67
62
|
*/
|
|
@@ -54,6 +54,20 @@ const meta = {
|
|
|
54
54
|
description: 'Icon container size',
|
|
55
55
|
options: ['sm', 'md', 'lg'],
|
|
56
56
|
},
|
|
57
|
+
shadowColor: {
|
|
58
|
+
control: 'select',
|
|
59
|
+
description: 'The shadow color of the banner',
|
|
60
|
+
options: [
|
|
61
|
+
'functional',
|
|
62
|
+
'brand',
|
|
63
|
+
'energy',
|
|
64
|
+
'broadband',
|
|
65
|
+
'mobile',
|
|
66
|
+
'insurance',
|
|
67
|
+
'cashback',
|
|
68
|
+
'pig',
|
|
69
|
+
],
|
|
70
|
+
},
|
|
57
71
|
},
|
|
58
72
|
args: {
|
|
59
73
|
heading: 'Welcome to Banner',
|
|
@@ -310,16 +324,15 @@ export const VerticalLayout: Story = {
|
|
|
310
324
|
direction="vertical"
|
|
311
325
|
/>
|
|
312
326
|
<Banner
|
|
327
|
+
variant="emphasis"
|
|
313
328
|
image={{
|
|
314
|
-
|
|
315
|
-
uri: 'https://images.unsplash.com/photo-1506126613408-eca07ce68773?w=200&q=80',
|
|
316
|
-
},
|
|
317
|
-
dark: {
|
|
329
|
+
source: {
|
|
318
330
|
uri: 'https://images.unsplash.com/photo-1506126613408-eca07ce68773?w=200&q=80',
|
|
319
331
|
},
|
|
320
332
|
}}
|
|
321
333
|
heading="Featured Content"
|
|
322
334
|
description="Discover amazing content curated just for you."
|
|
335
|
+
shadowColor="brand"
|
|
323
336
|
direction="vertical"
|
|
324
337
|
button={
|
|
325
338
|
<Button size="sm" onPress={() => console.log('Learn More pressed')}>
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { ChevronRightSmallIcon, CloseSmallIcon } from '@utilitywarehouse/hearth-react-native-icons';
|
|
2
|
-
import { Pressable, View } from 'react-native';
|
|
2
|
+
import { Image, ImageProps, Pressable, View } from 'react-native';
|
|
3
3
|
import { StyleSheet } from 'react-native-unistyles';
|
|
4
4
|
import { BodyText } from '../BodyText';
|
|
5
5
|
import { Card } from '../Card';
|
|
6
6
|
import { Heading } from '../Heading';
|
|
7
7
|
import { IconContainer } from '../IconContainer';
|
|
8
|
-
import { ThemedImage } from '../ThemedImage';
|
|
8
|
+
import { ThemedImage, ThemedImageProps } from '../ThemedImage';
|
|
9
9
|
import { UnstyledIconButton } from '../UnstyledIconButton';
|
|
10
10
|
import type BannerProps from './Banner.props';
|
|
11
11
|
|
|
12
|
+
const isThemedImageProps = (props: ThemedImageProps | ImageProps): props is ThemedImageProps => {
|
|
13
|
+
return 'light' in props && 'dark' in props;
|
|
14
|
+
};
|
|
15
|
+
|
|
12
16
|
const Banner = ({
|
|
13
17
|
icon,
|
|
14
18
|
iconContainerVariant = 'subtle',
|
|
@@ -44,26 +48,34 @@ const Banner = ({
|
|
|
44
48
|
);
|
|
45
49
|
}
|
|
46
50
|
if (illustration) {
|
|
51
|
+
if (isThemedImageProps(illustration)) {
|
|
52
|
+
return (
|
|
53
|
+
<ThemedImage
|
|
54
|
+
{...illustration}
|
|
55
|
+
resizeMode="cover"
|
|
56
|
+
style={[styles.media, styles.imageWrapper, illustration.style]}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
47
60
|
return (
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
style={styles.
|
|
52
|
-
accessible
|
|
53
|
-
accessibilityLabel={heading}
|
|
61
|
+
<Image
|
|
62
|
+
{...illustration}
|
|
63
|
+
resizeMode="cover"
|
|
64
|
+
style={[styles.media, styles.imageWrapper, illustration.style]}
|
|
54
65
|
/>
|
|
55
66
|
);
|
|
56
67
|
}
|
|
57
68
|
if (image) {
|
|
69
|
+
if (isThemedImageProps(image)) {
|
|
70
|
+
return (
|
|
71
|
+
<View style={[styles.media, styles.imageWrapper]}>
|
|
72
|
+
<ThemedImage {...image} style={[styles.image, image.style]} />
|
|
73
|
+
</View>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
58
76
|
return (
|
|
59
77
|
<View style={[styles.media, styles.imageWrapper]}>
|
|
60
|
-
<
|
|
61
|
-
light={image.light}
|
|
62
|
-
dark={image.dark}
|
|
63
|
-
style={styles.image}
|
|
64
|
-
accessible
|
|
65
|
-
accessibilityLabel={heading}
|
|
66
|
-
/>
|
|
78
|
+
<Image {...image} style={[styles.image, image.style]} />
|
|
67
79
|
</View>
|
|
68
80
|
);
|
|
69
81
|
}
|
|
@@ -82,23 +94,36 @@ const Banner = ({
|
|
|
82
94
|
|
|
83
95
|
const content = (
|
|
84
96
|
<View style={styles.container}>
|
|
97
|
+
{onClose && direction === 'vertical' && (
|
|
98
|
+
<UnstyledIconButton
|
|
99
|
+
icon={CloseSmallIcon}
|
|
100
|
+
size="sm"
|
|
101
|
+
onPress={onClose}
|
|
102
|
+
style={styles.closeButton}
|
|
103
|
+
accessibilityLabel="Close banner"
|
|
104
|
+
/>
|
|
105
|
+
)}
|
|
85
106
|
{renderIconOrImage()}
|
|
107
|
+
|
|
86
108
|
<View style={styles.contentContainer}>
|
|
87
|
-
<View style={styles.
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
109
|
+
<View style={styles.contentTextContainer}>
|
|
110
|
+
<View style={styles.textContainer}>
|
|
111
|
+
<Heading
|
|
112
|
+
size="sm"
|
|
113
|
+
style={styles.heading}
|
|
114
|
+
textAlign={hasIllustration && direction === 'vertical' ? 'center' : 'left'}
|
|
115
|
+
>
|
|
116
|
+
{heading}
|
|
117
|
+
</Heading>
|
|
118
|
+
<BodyText
|
|
119
|
+
size="md"
|
|
120
|
+
style={styles.description}
|
|
121
|
+
textAlign={hasIllustration && direction === 'vertical' ? 'center' : 'left'}
|
|
122
|
+
>
|
|
123
|
+
{description}
|
|
124
|
+
</BodyText>
|
|
125
|
+
</View>
|
|
126
|
+
|
|
102
127
|
{renderAction()}
|
|
103
128
|
</View>
|
|
104
129
|
{onPress && (
|
|
@@ -109,7 +134,7 @@ const Banner = ({
|
|
|
109
134
|
style={styles.chevron}
|
|
110
135
|
/>
|
|
111
136
|
)}
|
|
112
|
-
{onClose && (
|
|
137
|
+
{onClose && direction === 'horizontal' && (
|
|
113
138
|
<UnstyledIconButton
|
|
114
139
|
icon={CloseSmallIcon}
|
|
115
140
|
size="sm"
|
|
@@ -142,9 +167,9 @@ const Banner = ({
|
|
|
142
167
|
Banner.displayName = 'Banner';
|
|
143
168
|
|
|
144
169
|
const styles = StyleSheet.create(theme => ({
|
|
145
|
-
card: {},
|
|
170
|
+
card: { flexDirection: 'row', _web: { flexDirection: 'column' } },
|
|
146
171
|
pressable: {
|
|
147
|
-
|
|
172
|
+
flex: 1,
|
|
148
173
|
},
|
|
149
174
|
container: {
|
|
150
175
|
flexDirection: 'row',
|
|
@@ -194,6 +219,7 @@ const styles = StyleSheet.create(theme => ({
|
|
|
194
219
|
},
|
|
195
220
|
},
|
|
196
221
|
imageWrapper: {
|
|
222
|
+
flexDirection: 'row',
|
|
197
223
|
variants: {
|
|
198
224
|
direction: {
|
|
199
225
|
horizontal: {},
|
|
@@ -205,8 +231,8 @@ const styles = StyleSheet.create(theme => ({
|
|
|
205
231
|
},
|
|
206
232
|
image: {
|
|
207
233
|
borderRadius: theme.borderRadius.md,
|
|
208
|
-
borderWidth: theme.borderWidth[1],
|
|
209
234
|
borderColor: theme.color.border.strong,
|
|
235
|
+
borderWidth: theme.borderWidth[1],
|
|
210
236
|
variants: {
|
|
211
237
|
direction: {
|
|
212
238
|
horizontal: { width: 160, height: 95 },
|
|
@@ -218,15 +244,34 @@ const styles = StyleSheet.create(theme => ({
|
|
|
218
244
|
},
|
|
219
245
|
},
|
|
220
246
|
contentContainer: {
|
|
221
|
-
flex: 1,
|
|
222
|
-
flexDirection: 'row',
|
|
223
247
|
alignItems: 'flex-start',
|
|
224
248
|
justifyContent: 'space-between',
|
|
225
249
|
gap: theme.space.lg,
|
|
250
|
+
variants: {
|
|
251
|
+
direction: {
|
|
252
|
+
horizontal: {
|
|
253
|
+
flex: 1,
|
|
254
|
+
flexDirection: 'row',
|
|
255
|
+
},
|
|
256
|
+
vertical: {
|
|
257
|
+
flexDirection: 'column',
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
226
261
|
},
|
|
227
262
|
textContainer: {
|
|
228
|
-
|
|
263
|
+
gap: theme.space.sm,
|
|
264
|
+
},
|
|
265
|
+
contentTextContainer: {
|
|
229
266
|
gap: theme.space.lg,
|
|
267
|
+
variants: {
|
|
268
|
+
direction: {
|
|
269
|
+
horizontal: {
|
|
270
|
+
flex: 1,
|
|
271
|
+
},
|
|
272
|
+
vertical: {},
|
|
273
|
+
},
|
|
274
|
+
},
|
|
230
275
|
},
|
|
231
276
|
heading: {
|
|
232
277
|
compoundVariants: [
|
|
@@ -258,6 +303,16 @@ const styles = StyleSheet.create(theme => ({
|
|
|
258
303
|
},
|
|
259
304
|
closeButton: {
|
|
260
305
|
alignSelf: 'flex-start',
|
|
306
|
+
variants: {
|
|
307
|
+
direction: {
|
|
308
|
+
vertical: {
|
|
309
|
+
position: 'absolute',
|
|
310
|
+
top: 0,
|
|
311
|
+
right: 0,
|
|
312
|
+
},
|
|
313
|
+
horizontal: {},
|
|
314
|
+
},
|
|
315
|
+
},
|
|
261
316
|
},
|
|
262
317
|
}));
|
|
263
318
|
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { BottomSheetHandle as Handle } from '@gorhom/bottom-sheet';
|
|
2
2
|
import { BottomSheetDefaultHandleProps } from '@gorhom/bottom-sheet/lib/typescript/components/bottomSheetHandle/types';
|
|
3
|
+
import { Platform, View } from 'react-native';
|
|
3
4
|
import { StyleSheet, withUnistyles } from 'react-native-unistyles';
|
|
4
5
|
|
|
5
6
|
const StyledBottomSheetHandle = withUnistyles(Handle);
|
|
6
7
|
|
|
7
8
|
const BottomSheetHandle = ({ style, indicatorStyle, ...props }: BottomSheetDefaultHandleProps) => {
|
|
9
|
+
if (Platform.OS === 'web') {
|
|
10
|
+
return (
|
|
11
|
+
<View style={[styles.handle, style]}>
|
|
12
|
+
<View style={[styles.indicator, indicatorStyle]} />
|
|
13
|
+
</View>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
8
16
|
return (
|
|
9
17
|
<StyledBottomSheetHandle
|
|
10
18
|
style={[styles.handle, style]}
|
|
@@ -22,6 +30,10 @@ const styles = StyleSheet.create(theme => ({
|
|
|
22
30
|
paddingTop: theme.components.bottomSheet.padding,
|
|
23
31
|
paddingHorizontal: theme.components.bottomSheet.padding,
|
|
24
32
|
paddingBottom: theme.components.bottomSheet.gap,
|
|
33
|
+
_web: {
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
cursor: 'grab',
|
|
36
|
+
},
|
|
25
37
|
},
|
|
26
38
|
indicator: {
|
|
27
39
|
width: theme.components.bottomSheet.handle.width,
|
|
@@ -22,6 +22,7 @@ A Card component serves as a visual container that groups related content and ac
|
|
|
22
22
|
- [Variants](#variants)
|
|
23
23
|
- [Examples](#examples)
|
|
24
24
|
- [Interactive](#interactive)
|
|
25
|
+
- [With Shadow](#with-shadow)
|
|
25
26
|
- [With `CardAction`](#with-cardaction)
|
|
26
27
|
- [`CardAction` Playground](#cardaction-playground)
|
|
27
28
|
- [`CardAction` With Badge](#cardaction-with-badge)
|
|
@@ -64,7 +65,8 @@ const MyComponent = () => (
|
|
|
64
65
|
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | ----------------- |
|
|
65
66
|
| variant | `'subtle' \| 'emphasis' ` | The variant of the card. | `'subtle'` |
|
|
66
67
|
| colorScheme | `'neutralStrong' \| 'neutralSubtle' \| 'purple' \| 'energy'` <br /> `'broadband' \| 'mobile' \| 'insurance' \| 'cashback' \|` <br /> `'pig'` | The color scheme of the card. | `'neutralStrong'` |
|
|
67
|
-
|
|
|
68
|
+
| shadowColor | `'functional' \| 'brand' \| 'energy' \| 'broadband' \| 'mobile' `<br /> `'insurance' \| 'cashback' \| 'pig'` | The shadow color of the card. | `-` |
|
|
69
|
+
| noPadding | `boolean` | Whether or not the card has padding. | `false` |
|
|
68
70
|
| selected | `boolean` | Whether the card is selected. | `false` |
|
|
69
71
|
| onPress | `() => void` | Callback function to be called. | `-` |
|
|
70
72
|
| disabled | `boolean` | Whether the card is disabled. | `false` |
|
|
@@ -146,6 +148,23 @@ const MyComponent = () => (
|
|
|
146
148
|
);
|
|
147
149
|
```
|
|
148
150
|
|
|
151
|
+
### With Shadow
|
|
152
|
+
|
|
153
|
+
You can add shadow to the `Card` component by using the `shadowColor` prop. This prop accepts various semantic color options to match your design needs.
|
|
154
|
+
|
|
155
|
+
<Canvas of={Stories.WithShadow} />
|
|
156
|
+
|
|
157
|
+
```jsx
|
|
158
|
+
import { Card, BodyText, Heading } from '@utilitywarehouse/hearth-react-native';
|
|
159
|
+
|
|
160
|
+
const MyComponent = () => (
|
|
161
|
+
<Card shadowColor="functional" variant="emphasis">
|
|
162
|
+
<Heading size="lg">Card with Shadow</Heading>
|
|
163
|
+
<BodyText>This card has a shadow applied using the shadowColor prop.</BodyText>
|
|
164
|
+
</Card>
|
|
165
|
+
);
|
|
166
|
+
```
|
|
167
|
+
|
|
149
168
|
### With `CardAction`
|
|
150
169
|
|
|
151
170
|
You can use the `CardAction` component within a `Card` to create actionable items with consistent styling.
|
|
@@ -13,6 +13,15 @@ interface CardProps extends PressableProps {
|
|
|
13
13
|
| 'insurance'
|
|
14
14
|
| 'cashback'
|
|
15
15
|
| 'pig';
|
|
16
|
+
shadowColor?:
|
|
17
|
+
| 'functional'
|
|
18
|
+
| 'brand'
|
|
19
|
+
| 'energy'
|
|
20
|
+
| 'broadband'
|
|
21
|
+
| 'mobile'
|
|
22
|
+
| 'insurance'
|
|
23
|
+
| 'cashback'
|
|
24
|
+
| 'pig';
|
|
16
25
|
noPadding?: boolean;
|
|
17
26
|
disabled?: boolean;
|
|
18
27
|
space?: SpacingValues;
|
|
@@ -38,6 +38,20 @@ const meta = {
|
|
|
38
38
|
],
|
|
39
39
|
description: 'Use this value to set the Card color scheme.',
|
|
40
40
|
},
|
|
41
|
+
shadowColor: {
|
|
42
|
+
control: 'select',
|
|
43
|
+
options: [
|
|
44
|
+
'functional',
|
|
45
|
+
'brand',
|
|
46
|
+
'energy',
|
|
47
|
+
'broadband',
|
|
48
|
+
'mobile',
|
|
49
|
+
'insurance',
|
|
50
|
+
'cashback',
|
|
51
|
+
'pig',
|
|
52
|
+
],
|
|
53
|
+
description: 'Use this value to set the Card shadow color.',
|
|
54
|
+
},
|
|
41
55
|
},
|
|
42
56
|
args: {
|
|
43
57
|
children: 'This is a card',
|
|
@@ -208,6 +222,31 @@ export const Variants: Story = {
|
|
|
208
222
|
},
|
|
209
223
|
};
|
|
210
224
|
|
|
225
|
+
export const WithShadow: Story = {
|
|
226
|
+
args: {
|
|
227
|
+
shadowColor: 'functional',
|
|
228
|
+
},
|
|
229
|
+
parameters: {
|
|
230
|
+
controls: { exclude: ['variant'] },
|
|
231
|
+
},
|
|
232
|
+
render: ({ children, ...props }) => {
|
|
233
|
+
return (
|
|
234
|
+
<Flex space="lg">
|
|
235
|
+
<VariantTitle title="Subtle - White - Shadow">
|
|
236
|
+
<Card {...props} variant="subtle">
|
|
237
|
+
<BodyText>{children as string}</BodyText>
|
|
238
|
+
</Card>
|
|
239
|
+
</VariantTitle>
|
|
240
|
+
<VariantTitle title="Emphasis - White - Shadow">
|
|
241
|
+
<Card {...props} variant="emphasis">
|
|
242
|
+
<BodyText>{children as string}</BodyText>
|
|
243
|
+
</Card>
|
|
244
|
+
</VariantTitle>
|
|
245
|
+
</Flex>
|
|
246
|
+
);
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
|
|
211
250
|
export const Interactive: Story = {
|
|
212
251
|
parameters: {
|
|
213
252
|
controls: { exclude: ['variant', 'colorScheme'] },
|
|
@@ -104,12 +104,14 @@ const Card = ({
|
|
|
104
104
|
children,
|
|
105
105
|
variant = 'subtle',
|
|
106
106
|
colorScheme = 'neutralStrong',
|
|
107
|
+
shadowColor,
|
|
107
108
|
noPadding = false,
|
|
108
109
|
style,
|
|
109
110
|
states,
|
|
110
111
|
space,
|
|
111
112
|
disabled = false,
|
|
112
113
|
onPress,
|
|
114
|
+
|
|
113
115
|
...rest
|
|
114
116
|
}: CardProps & { states?: { active?: boolean; disabled?: boolean } }) => {
|
|
115
117
|
const { active } = states || { active: false };
|
|
@@ -165,6 +167,7 @@ const Card = ({
|
|
|
165
167
|
showPressed,
|
|
166
168
|
disabled,
|
|
167
169
|
space: hasActions || hasContent ? 'none' : space,
|
|
170
|
+
shadowColor,
|
|
168
171
|
});
|
|
169
172
|
|
|
170
173
|
const renderChildren = () => {
|
|
@@ -257,6 +260,32 @@ const styles = StyleSheet.create(theme => ({
|
|
|
257
260
|
borderWidth: theme.components.card.brand.borderWidth,
|
|
258
261
|
},
|
|
259
262
|
},
|
|
263
|
+
shadowColor: {
|
|
264
|
+
functional: {
|
|
265
|
+
boxShadow: theme.helpers.shadow.functional,
|
|
266
|
+
},
|
|
267
|
+
brand: {
|
|
268
|
+
boxShadow: theme.helpers.shadow.brand,
|
|
269
|
+
},
|
|
270
|
+
energy: {
|
|
271
|
+
boxShadow: theme.helpers.shadow.energy,
|
|
272
|
+
},
|
|
273
|
+
broadband: {
|
|
274
|
+
boxShadow: theme.helpers.shadow.broadband,
|
|
275
|
+
},
|
|
276
|
+
mobile: {
|
|
277
|
+
boxShadow: theme.helpers.shadow.mobile,
|
|
278
|
+
},
|
|
279
|
+
insurance: {
|
|
280
|
+
boxShadow: theme.helpers.shadow.insurance,
|
|
281
|
+
},
|
|
282
|
+
cashback: {
|
|
283
|
+
boxShadow: theme.helpers.shadow.cashback,
|
|
284
|
+
},
|
|
285
|
+
pig: {
|
|
286
|
+
boxShadow: theme.helpers.shadow.pig,
|
|
287
|
+
},
|
|
288
|
+
},
|
|
260
289
|
noPadding: {
|
|
261
290
|
true: {
|
|
262
291
|
padding: theme.components.card.mobile.paddingNone,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Checkbox, CheckboxGroup } from '.';
|
|
2
1
|
import { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Checkbox, CheckboxGroup } from '.';
|
|
3
3
|
|
|
4
4
|
const meta = {
|
|
5
5
|
title: 'Stories / CheckboxGroup',
|
|
@@ -80,3 +80,21 @@ export const Playground: Story = {
|
|
|
80
80
|
</CheckboxGroup>
|
|
81
81
|
),
|
|
82
82
|
};
|
|
83
|
+
|
|
84
|
+
export const LongContent: Story = {
|
|
85
|
+
args: {
|
|
86
|
+
type: 'tile',
|
|
87
|
+
},
|
|
88
|
+
render: args => (
|
|
89
|
+
<CheckboxGroup {...args}>
|
|
90
|
+
<Checkbox aria-label="Label 1" label="Option 1" value="Option 1" nativeID="Checkbox-1" />
|
|
91
|
+
<Checkbox
|
|
92
|
+
aria-label="Label 2"
|
|
93
|
+
label="Option 2 with a very long content that should wrap into multiple lines to test the layout of the checkbox component in such scenarios."
|
|
94
|
+
value="Option 2"
|
|
95
|
+
nativeID="Checkbox-2"
|
|
96
|
+
/>
|
|
97
|
+
<Checkbox aria-label="Label 3" label="Option 3" value="Option 3" nativeID="Checkbox-3" />
|
|
98
|
+
</CheckboxGroup>
|
|
99
|
+
),
|
|
100
|
+
};
|
|
@@ -232,6 +232,6 @@ Selection through the calendar always returns a JavaScript `Date` that is reform
|
|
|
232
232
|
### Best practices
|
|
233
233
|
|
|
234
234
|
- Always pair with `FormField` for proper label, helper text, and error message announcements.
|
|
235
|
-
- Use `openButtonLabel` to
|
|
235
|
+
- Use `openButtonLabel` to customise the calendar button announcement if the default doesn't fit your use case.
|
|
236
236
|
- Provide clear validation feedback through `FormField` when manual date entry doesn't match the expected format.
|
|
237
237
|
- Test with VoiceOver and TalkBack to ensure the date entry flow works smoothly in your specific context.
|
|
@@ -79,7 +79,7 @@ const MyComponent = () => (
|
|
|
79
79
|
| button | `ReactElement` | Optional Button component displayed below description | `-` |
|
|
80
80
|
| variant | `'emphasis' \| 'subtle'` | Visual style variant with strong or subtle borders | `'emphasis'` |
|
|
81
81
|
|
|
82
|
-
The component also accepts all standard Card props except `noPadding`, `space`, `gap`, `rowGap`, `columnGap`, `flexDirection`, `flexWrap`, `alignItems`, and `justifyContent`.
|
|
82
|
+
The component also accepts all standard Card props except `noPadding`, `colorScheme`, `space`, `gap`, `rowGap`, `columnGap`, `flexDirection`, `flexWrap`, `alignItems`, and `justifyContent`.
|
|
83
83
|
|
|
84
84
|
## Variants
|
|
85
85
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Meta, StoryObj } from '@storybook/react-
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react-native';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import { Button } from '../Button';
|
|
4
4
|
import { Flex } from '../Flex';
|
|
@@ -30,6 +30,20 @@ const meta = {
|
|
|
30
30
|
description: 'The variant style of the HighlightBanner',
|
|
31
31
|
options: ['emphasis', 'subtle'],
|
|
32
32
|
},
|
|
33
|
+
shadowColor: {
|
|
34
|
+
control: 'select',
|
|
35
|
+
description: 'The shadow color of the card',
|
|
36
|
+
options: [
|
|
37
|
+
'functional',
|
|
38
|
+
'brand',
|
|
39
|
+
'energy',
|
|
40
|
+
'broadband',
|
|
41
|
+
'mobile',
|
|
42
|
+
'insurance',
|
|
43
|
+
'cashback',
|
|
44
|
+
'pig',
|
|
45
|
+
],
|
|
46
|
+
},
|
|
33
47
|
},
|
|
34
48
|
args: {
|
|
35
49
|
heading: 'Featured Content',
|
|
@@ -69,9 +69,11 @@ const List = ({ children, heading, helperText, headerTrailingContent, ...props }
|
|
|
69
69
|
{container === 'none' ? (
|
|
70
70
|
<View>{updatedChildren}</View>
|
|
71
71
|
) : (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
React.Children.count(updatedChildren) > 0 && (
|
|
73
|
+
<Card {...containerToCard} noPadding style={styles.card}>
|
|
74
|
+
<>{updatedChildren}</>
|
|
75
|
+
</Card>
|
|
76
|
+
)
|
|
75
77
|
)}
|
|
76
78
|
</View>
|
|
77
79
|
</ListContext.Provider>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface IMenuContext {
|
|
4
|
+
close: () => void;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const MenuContext = createContext<IMenuContext | undefined>(undefined);
|
|
8
|
+
|
|
9
|
+
export const useMenuContext = () => {
|
|
10
|
+
const context = useContext(MenuContext);
|
|
11
|
+
if (!context) {
|
|
12
|
+
throw new Error('useMenuContext must be used within a Menu component');
|
|
13
|
+
}
|
|
14
|
+
return context;
|
|
15
|
+
};
|