@utilitywarehouse/hearth-react-native 0.8.0 → 0.8.2
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 +22 -0
- package/build/components/Banner/Banner.js +27 -7
- package/build/components/Banner/Banner.props.d.ts +4 -9
- 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.js +12 -2
- 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/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/core/themes.d.ts +40 -0
- package/build/core/themes.js +20 -0
- package/docs/adding-shadows.mdx +43 -0
- package/package.json +3 -3
- package/src/components/Banner/Banner.docs.mdx +1 -1
- package/src/components/Banner/Banner.props.ts +4 -9
- package/src/components/Banner/Banner.stories.tsx +16 -0
- package/src/components/Banner/Banner.tsx +46 -31
- 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/HighlightBanner/HighlightBanner.docs.mdx +21 -2
- package/src/components/HighlightBanner/HighlightBanner.props.ts +1 -0
- package/src/components/HighlightBanner/HighlightBanner.stories.tsx +31 -1
- package/src/components/HighlightBanner/HighlightBanner.tsx +16 -4
- package/src/components/List/List.tsx +5 -3
- package/src/components/List/ListAction/ListActionTrailingIcon.tsx +2 -2
- 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/core/themes.ts +20 -0
|
@@ -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,6 +324,7 @@ export const VerticalLayout: Story = {
|
|
|
310
324
|
direction="vertical"
|
|
311
325
|
/>
|
|
312
326
|
<Banner
|
|
327
|
+
variant="emphasis"
|
|
313
328
|
image={{
|
|
314
329
|
light: {
|
|
315
330
|
uri: 'https://images.unsplash.com/photo-1506126613408-eca07ce68773?w=200&q=80',
|
|
@@ -320,6 +335,7 @@ export const VerticalLayout: Story = {
|
|
|
320
335
|
}}
|
|
321
336
|
heading="Featured Content"
|
|
322
337
|
description="Discover amazing content curated just for you."
|
|
338
|
+
shadowColor="brand"
|
|
323
339
|
direction="vertical"
|
|
324
340
|
button={
|
|
325
341
|
<Button size="sm" onPress={() => console.log('Learn More pressed')}>
|
|
@@ -46,24 +46,16 @@ const Banner = ({
|
|
|
46
46
|
if (illustration) {
|
|
47
47
|
return (
|
|
48
48
|
<ThemedImage
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
style={styles.
|
|
52
|
-
accessible
|
|
53
|
-
accessibilityLabel={heading}
|
|
49
|
+
{...illustration}
|
|
50
|
+
resizeMode="cover"
|
|
51
|
+
style={[styles.media, styles.imageWrapper, illustration.style]}
|
|
54
52
|
/>
|
|
55
53
|
);
|
|
56
54
|
}
|
|
57
55
|
if (image) {
|
|
58
56
|
return (
|
|
59
57
|
<View style={[styles.media, styles.imageWrapper]}>
|
|
60
|
-
<ThemedImage
|
|
61
|
-
light={image.light}
|
|
62
|
-
dark={image.dark}
|
|
63
|
-
style={styles.image}
|
|
64
|
-
accessible
|
|
65
|
-
accessibilityLabel={heading}
|
|
66
|
-
/>
|
|
58
|
+
<ThemedImage {...image} style={[styles.image, image.style]} />
|
|
67
59
|
</View>
|
|
68
60
|
);
|
|
69
61
|
}
|
|
@@ -84,21 +76,24 @@ const Banner = ({
|
|
|
84
76
|
<View style={styles.container}>
|
|
85
77
|
{renderIconOrImage()}
|
|
86
78
|
<View style={styles.contentContainer}>
|
|
87
|
-
<View style={styles.
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
79
|
+
<View style={styles.contentTextContainer}>
|
|
80
|
+
<View style={styles.textContainer}>
|
|
81
|
+
<Heading
|
|
82
|
+
size="sm"
|
|
83
|
+
style={styles.heading}
|
|
84
|
+
textAlign={hasIllustration && direction === 'vertical' ? 'center' : 'left'}
|
|
85
|
+
>
|
|
86
|
+
{heading}
|
|
87
|
+
</Heading>
|
|
88
|
+
<BodyText
|
|
89
|
+
size="md"
|
|
90
|
+
style={styles.description}
|
|
91
|
+
textAlign={hasIllustration && direction === 'vertical' ? 'center' : 'left'}
|
|
92
|
+
>
|
|
93
|
+
{description}
|
|
94
|
+
</BodyText>
|
|
95
|
+
</View>
|
|
96
|
+
|
|
102
97
|
{renderAction()}
|
|
103
98
|
</View>
|
|
104
99
|
{onPress && (
|
|
@@ -194,6 +189,7 @@ const styles = StyleSheet.create(theme => ({
|
|
|
194
189
|
},
|
|
195
190
|
},
|
|
196
191
|
imageWrapper: {
|
|
192
|
+
flexDirection: 'row',
|
|
197
193
|
variants: {
|
|
198
194
|
direction: {
|
|
199
195
|
horizontal: {},
|
|
@@ -205,8 +201,8 @@ const styles = StyleSheet.create(theme => ({
|
|
|
205
201
|
},
|
|
206
202
|
image: {
|
|
207
203
|
borderRadius: theme.borderRadius.md,
|
|
208
|
-
borderWidth: theme.borderWidth[1],
|
|
209
204
|
borderColor: theme.color.border.strong,
|
|
205
|
+
borderWidth: theme.borderWidth[1],
|
|
210
206
|
variants: {
|
|
211
207
|
direction: {
|
|
212
208
|
horizontal: { width: 160, height: 95 },
|
|
@@ -218,15 +214,34 @@ const styles = StyleSheet.create(theme => ({
|
|
|
218
214
|
},
|
|
219
215
|
},
|
|
220
216
|
contentContainer: {
|
|
221
|
-
flex: 1,
|
|
222
|
-
flexDirection: 'row',
|
|
223
217
|
alignItems: 'flex-start',
|
|
224
218
|
justifyContent: 'space-between',
|
|
225
219
|
gap: theme.space.lg,
|
|
220
|
+
variants: {
|
|
221
|
+
direction: {
|
|
222
|
+
horizontal: {
|
|
223
|
+
flex: 1,
|
|
224
|
+
flexDirection: 'row',
|
|
225
|
+
},
|
|
226
|
+
vertical: {
|
|
227
|
+
flexDirection: 'column',
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
},
|
|
226
231
|
},
|
|
227
232
|
textContainer: {
|
|
228
|
-
|
|
233
|
+
gap: theme.space.sm,
|
|
234
|
+
},
|
|
235
|
+
contentTextContainer: {
|
|
229
236
|
gap: theme.space.lg,
|
|
237
|
+
variants: {
|
|
238
|
+
direction: {
|
|
239
|
+
horizontal: {
|
|
240
|
+
flex: 1,
|
|
241
|
+
},
|
|
242
|
+
vertical: {},
|
|
243
|
+
},
|
|
244
|
+
},
|
|
230
245
|
},
|
|
231
246
|
heading: {
|
|
232
247
|
compoundVariants: [
|
|
@@ -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
|
+
};
|
|
@@ -11,7 +11,7 @@ import * as Stories from './HighlightBanner.stories';
|
|
|
11
11
|
|
|
12
12
|
# Highlight Banner
|
|
13
13
|
|
|
14
|
-
A `HighlightBanner` component is a specialised card layout designed for highlighting featured content with an image. It combines a colored heading banner, an image, and descriptive text with optional action buttons or links. Perfect for promotional content, featured articles, or important announcements.
|
|
14
|
+
A `HighlightBanner` component is a specialised card layout designed for highlighting featured content with an image. It combines a colored heading banner, an optional image, and descriptive text with optional action buttons or links. Perfect for promotional content, featured articles, or important announcements.
|
|
15
15
|
|
|
16
16
|
- [Playground](#playground)
|
|
17
17
|
- [Usage](#usage)
|
|
@@ -20,6 +20,7 @@ A `HighlightBanner` component is a specialised card layout designed for highligh
|
|
|
20
20
|
- [Examples](#examples)
|
|
21
21
|
- [With Button](#with-button)
|
|
22
22
|
- [With Link](#with-link)
|
|
23
|
+
- [Without Image](#without-image)
|
|
23
24
|
- [Color Variants](#color-variants)
|
|
24
25
|
- [Subtle Variant](#subtle-variant)
|
|
25
26
|
- [Different Images](#different-images)
|
|
@@ -78,7 +79,7 @@ const MyComponent = () => (
|
|
|
78
79
|
| button | `ReactElement` | Optional Button component displayed below description | `-` |
|
|
79
80
|
| variant | `'emphasis' \| 'subtle'` | Visual style variant with strong or subtle borders | `'emphasis'` |
|
|
80
81
|
|
|
81
|
-
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`.
|
|
82
83
|
|
|
83
84
|
## Variants
|
|
84
85
|
|
|
@@ -137,6 +138,24 @@ const MyComponent = () => (
|
|
|
137
138
|
);
|
|
138
139
|
```
|
|
139
140
|
|
|
141
|
+
### Without Image
|
|
142
|
+
|
|
143
|
+
Display the HighlightBanner without an image by omitting the `image` prop:
|
|
144
|
+
|
|
145
|
+
<Canvas of={Stories.WithoutImage} />
|
|
146
|
+
|
|
147
|
+
```jsx
|
|
148
|
+
import { HighlightBanner, Button } from '@utilitywarehouse/hearth-react-native';
|
|
149
|
+
|
|
150
|
+
const MyComponent = () => (
|
|
151
|
+
<HighlightBanner
|
|
152
|
+
heading="Content Without Image"
|
|
153
|
+
description="This HighlightBanner does not have an image, focusing solely on the text content."
|
|
154
|
+
button={<Button onPress={() => console.log('pressed')}>Discover More</Button>}
|
|
155
|
+
/>
|
|
156
|
+
);
|
|
157
|
+
```
|
|
158
|
+
|
|
140
159
|
### Color Variants
|
|
141
160
|
|
|
142
161
|
The component supports seven semantic color schemes that automatically apply the appropriate subtle background colors:
|
|
@@ -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',
|
|
@@ -174,6 +188,22 @@ export const ColorVariants: Story = {
|
|
|
174
188
|
},
|
|
175
189
|
};
|
|
176
190
|
|
|
191
|
+
export const WithoutImage: Story = {
|
|
192
|
+
render: args => {
|
|
193
|
+
return (
|
|
194
|
+
<View style={{ width: 400 }}>
|
|
195
|
+
<HighlightBanner
|
|
196
|
+
{...args}
|
|
197
|
+
image={undefined}
|
|
198
|
+
heading="Content Without Image"
|
|
199
|
+
description="This HighlightBanner does not have an image, focusing solely on the text content."
|
|
200
|
+
button={<Button onPress={() => console.log('pressed')}>Discover More</Button>}
|
|
201
|
+
/>
|
|
202
|
+
</View>
|
|
203
|
+
);
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
|
|
177
207
|
export const SubtleCard: Story = {
|
|
178
208
|
args: {
|
|
179
209
|
variant: 'subtle',
|
|
@@ -16,7 +16,7 @@ const HighlightBanner = ({
|
|
|
16
16
|
style,
|
|
17
17
|
...props
|
|
18
18
|
}: HighlightBannerProps) => {
|
|
19
|
-
styles.useVariants({ headingColor, variant });
|
|
19
|
+
styles.useVariants({ headingColor, variant, hasImage: Boolean(image) });
|
|
20
20
|
|
|
21
21
|
return (
|
|
22
22
|
<Card variant={variant} noPadding style={style} {...props}>
|
|
@@ -26,9 +26,11 @@ const HighlightBanner = ({
|
|
|
26
26
|
{heading}
|
|
27
27
|
</BodyText>
|
|
28
28
|
</View>
|
|
29
|
-
|
|
30
|
-
<
|
|
31
|
-
|
|
29
|
+
{!!image && (
|
|
30
|
+
<View style={styles.imageContainer(imageContainerHeight)}>
|
|
31
|
+
<Image resizeMode="cover" {...image} style={[styles.image, image?.style]} />
|
|
32
|
+
</View>
|
|
33
|
+
)}
|
|
32
34
|
<View style={styles.footer}>
|
|
33
35
|
<BodyText size="md" textAlign="center">
|
|
34
36
|
{description}
|
|
@@ -86,6 +88,11 @@ const styles = StyleSheet.create(theme => ({
|
|
|
86
88
|
borderColor: theme.color.border.subtle,
|
|
87
89
|
},
|
|
88
90
|
},
|
|
91
|
+
hasImage: {
|
|
92
|
+
false: {
|
|
93
|
+
borderBottomWidth: 0,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
89
96
|
},
|
|
90
97
|
},
|
|
91
98
|
imageContainer: (height: number = 200) => ({
|
|
@@ -109,6 +116,11 @@ const styles = StyleSheet.create(theme => ({
|
|
|
109
116
|
borderColor: theme.color.border.subtle,
|
|
110
117
|
},
|
|
111
118
|
},
|
|
119
|
+
hasImage: {
|
|
120
|
+
true: {
|
|
121
|
+
flex: 1,
|
|
122
|
+
},
|
|
123
|
+
},
|
|
112
124
|
},
|
|
113
125
|
},
|
|
114
126
|
linkContainer: {
|
|
@@ -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>
|
|
@@ -105,3 +105,21 @@ export const WithGrid: Story = {
|
|
|
105
105
|
</RadioGroup>
|
|
106
106
|
),
|
|
107
107
|
};
|
|
108
|
+
|
|
109
|
+
export const LongContent: Story = {
|
|
110
|
+
args: {
|
|
111
|
+
type: 'tile',
|
|
112
|
+
},
|
|
113
|
+
render: args => (
|
|
114
|
+
<RadioGroup {...args}>
|
|
115
|
+
<Radio aria-label="Label 1" label="Option 1" value="Option 1" nativeID="Radio-1" />
|
|
116
|
+
<Radio
|
|
117
|
+
aria-label="Label 2"
|
|
118
|
+
label="Option 2 with a very long content that spans multiple lines to test text wrapping"
|
|
119
|
+
value="Option 2"
|
|
120
|
+
nativeID="Radio-2"
|
|
121
|
+
/>
|
|
122
|
+
<Radio aria-label="Label 3" label="Option 3" value="Option 3" nativeID="Radio-3" />
|
|
123
|
+
</RadioGroup>
|
|
124
|
+
),
|
|
125
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
export const RadioCardGroupContext = createContext<{
|
|
4
|
+
flexDirection?: 'row' | 'column' | 'row-reverse' | 'column-reverse';
|
|
5
|
+
flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
6
|
+
justifyContent?:
|
|
7
|
+
| 'flex-start'
|
|
8
|
+
| 'flex-end'
|
|
9
|
+
| 'center'
|
|
10
|
+
| 'space-between'
|
|
11
|
+
| 'space-around'
|
|
12
|
+
| 'space-evenly';
|
|
13
|
+
alignItems?: 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline';
|
|
14
|
+
}>({});
|
|
15
|
+
|
|
16
|
+
export const useRadioCardGroupContext = () => useContext(RadioCardGroupContext);
|
|
@@ -68,3 +68,27 @@ export const Playground: Story = {
|
|
|
68
68
|
</RadioCardGroup>
|
|
69
69
|
),
|
|
70
70
|
};
|
|
71
|
+
|
|
72
|
+
export const LongContent: Story = {
|
|
73
|
+
args: {
|
|
74
|
+
flexDirection: 'column',
|
|
75
|
+
},
|
|
76
|
+
render: args => (
|
|
77
|
+
<RadioCardGroup {...args}>
|
|
78
|
+
<RadioCard aria-label="Label 1" label="Option 1" value="Option 1" nativeID="RadioCard-1">
|
|
79
|
+
<BodyText>Additional content</BodyText>
|
|
80
|
+
</RadioCard>
|
|
81
|
+
<RadioCard
|
|
82
|
+
aria-label="Label 2"
|
|
83
|
+
label="Option 2 with a very long content that should wrap into multiple lines to test the layout of the RadioCard component in such scenarios."
|
|
84
|
+
value="Option 2"
|
|
85
|
+
nativeID="RadioCard-2"
|
|
86
|
+
>
|
|
87
|
+
<BodyText>Additional content</BodyText>
|
|
88
|
+
</RadioCard>
|
|
89
|
+
<RadioCard aria-label="Label 3" label="Option 3" value="Option 3" nativeID="RadioCard-3">
|
|
90
|
+
<BodyText>Additional content</BodyText>
|
|
91
|
+
</RadioCard>
|
|
92
|
+
</RadioCardGroup>
|
|
93
|
+
),
|
|
94
|
+
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import { StyleSheet } from 'react-native-unistyles';
|
|
4
4
|
import { Grid } from '../Grid';
|
|
5
|
+
import { RadioCardGroupContext } from './RadioCardGroup.context';
|
|
6
|
+
import RadioCardGroupProps from './RadioCardGroup.props';
|
|
5
7
|
|
|
6
8
|
const RadioCardGroup = ({
|
|
7
9
|
children,
|
|
@@ -14,26 +16,33 @@ const RadioCardGroup = ({
|
|
|
14
16
|
columns,
|
|
15
17
|
...props
|
|
16
18
|
}: RadioCardGroupProps) => {
|
|
19
|
+
const context = useMemo(() => {
|
|
20
|
+
return { flexDirection, flexWrap, justifyContent, alignItems };
|
|
21
|
+
}, [flexDirection, flexWrap, justifyContent, alignItems]);
|
|
17
22
|
return columns ? (
|
|
18
|
-
<
|
|
19
|
-
{
|
|
20
|
-
|
|
23
|
+
<RadioCardGroupContext.Provider value={context}>
|
|
24
|
+
<Grid {...props} gap={gap} columns={columns} style={style}>
|
|
25
|
+
{children as any}
|
|
26
|
+
</Grid>
|
|
27
|
+
</RadioCardGroupContext.Provider>
|
|
21
28
|
) : (
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
<RadioCardGroupContext.Provider value={context}>
|
|
30
|
+
<View
|
|
31
|
+
{...props}
|
|
32
|
+
style={[
|
|
33
|
+
styles.containerGap(gap),
|
|
34
|
+
{
|
|
35
|
+
flexDirection,
|
|
36
|
+
flexWrap,
|
|
37
|
+
justifyContent,
|
|
38
|
+
alignItems,
|
|
39
|
+
},
|
|
40
|
+
style,
|
|
41
|
+
]}
|
|
42
|
+
>
|
|
43
|
+
{children}
|
|
44
|
+
</View>
|
|
45
|
+
</RadioCardGroupContext.Provider>
|
|
37
46
|
);
|
|
38
47
|
};
|
|
39
48
|
|