@utilitywarehouse/hearth-react-native 0.8.1 → 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 +16 -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.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 +2 -2
- 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 +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/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
package/.storybook/preview.tsx
CHANGED
package/.turbo/turbo-build.log
CHANGED
package/.turbo/turbo-lint.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @utilitywarehouse/hearth-react-native@0.8.
|
|
2
|
+
> @utilitywarehouse/hearth-react-native@0.8.2 lint /home/runner/work/hearth/hearth/packages/react-native
|
|
3
3
|
> TIMING=1 eslint --max-warnings 0
|
|
4
4
|
|
|
5
5
|
Rule | Time (ms) | Relative
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @utilitywarehouse/hearth-react-native
|
|
2
2
|
|
|
3
|
+
## 0.8.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#652](https://github.com/utilitywarehouse/hearth/pull/652) [`5119703`](https://github.com/utilitywarehouse/hearth/commit/5119703a31f663cc8c0a8bb2c6ba5b10f9bf72d6) Thanks [@jordmccord](https://github.com/jordmccord)! - Fixes `RadioCard` label wrapping issue
|
|
8
|
+
|
|
9
|
+
- [#648](https://github.com/utilitywarehouse/hearth/pull/648) [`c90ea5c`](https://github.com/utilitywarehouse/hearth/commit/c90ea5ce165f27ccfc9774ec58ac642d02b349d1) Thanks [@jordmccord](https://github.com/jordmccord)! - Fixes `ListAction` icon size
|
|
10
|
+
|
|
11
|
+
- [#648](https://github.com/utilitywarehouse/hearth/pull/648) [`c90ea5c`](https://github.com/utilitywarehouse/hearth/commit/c90ea5ce165f27ccfc9774ec58ac642d02b349d1) Thanks [@jordmccord](https://github.com/jordmccord)! - Fixes `Banner` text gap size
|
|
12
|
+
|
|
13
|
+
- [#651](https://github.com/utilitywarehouse/hearth/pull/651) [`4ee77b7`](https://github.com/utilitywarehouse/hearth/commit/4ee77b75e58ac4abbeba375ecb367d8899c7f1a0) Thanks [@jordmccord](https://github.com/jordmccord)! - Fixes `Banner` image and height issue
|
|
14
|
+
|
|
15
|
+
- [#649](https://github.com/utilitywarehouse/hearth/pull/649) [`7374535`](https://github.com/utilitywarehouse/hearth/commit/737453598ad5e885b35b5fcd2e4c4ccff4910c43) Thanks [@jordmccord](https://github.com/jordmccord)! - Fixes `List` to only show `Card` container if it has children
|
|
16
|
+
|
|
17
|
+
- [#648](https://github.com/utilitywarehouse/hearth/pull/648) [`c90ea5c`](https://github.com/utilitywarehouse/hearth/commit/c90ea5ce165f27ccfc9774ec58ac642d02b349d1) Thanks [@jordmccord](https://github.com/jordmccord)! - Adds `shadowColor` prop to `Card` and exposes helpers in theme
|
|
18
|
+
|
|
3
19
|
## 0.8.1
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -16,10 +16,10 @@ const Banner = ({ icon, iconContainerVariant = 'subtle', iconContainerSize = 'md
|
|
|
16
16
|
return (_jsx(IconContainer, { icon: icon, variant: iconContainerVariant, size: iconContainerSize, color: iconContainerColor, style: styles.media }));
|
|
17
17
|
}
|
|
18
18
|
if (illustration) {
|
|
19
|
-
return (_jsx(ThemedImage, {
|
|
19
|
+
return (_jsx(ThemedImage, { ...illustration, resizeMode: "cover", style: [styles.media, styles.imageWrapper, illustration.style] }));
|
|
20
20
|
}
|
|
21
21
|
if (image) {
|
|
22
|
-
return (_jsx(View, { style: [styles.media, styles.imageWrapper], children: _jsx(ThemedImage, {
|
|
22
|
+
return (_jsx(View, { style: [styles.media, styles.imageWrapper], children: _jsx(ThemedImage, { ...image, style: [styles.image, image.style] }) }));
|
|
23
23
|
}
|
|
24
24
|
return null;
|
|
25
25
|
};
|
|
@@ -32,7 +32,7 @@ const Banner = ({ icon, iconContainerVariant = 'subtle', iconContainerSize = 'md
|
|
|
32
32
|
}
|
|
33
33
|
return null;
|
|
34
34
|
};
|
|
35
|
-
const content = (_jsxs(View, { style: styles.container, children: [renderIconOrImage(), _jsxs(View, { style: styles.contentContainer, children: [_jsxs(View, { style: styles.textContainer, children: [_jsx(Heading, { size: "sm", style: styles.heading, textAlign: hasIllustration && direction === 'vertical' ? 'center' : 'left', children: heading }), _jsx(BodyText, { size: "md", style: styles.description, textAlign: hasIllustration && direction === 'vertical' ? 'center' : 'left', children: description }), renderAction()] }), onPress && (_jsx(UnstyledIconButton, { icon: ChevronRightSmallIcon, size: "sm", onPress: onPress, style: styles.chevron })), onClose && (_jsx(UnstyledIconButton, { icon: CloseSmallIcon, size: "sm", onPress: onClose, style: styles.closeButton, accessibilityLabel: "Close banner" }))] })] }));
|
|
35
|
+
const content = (_jsxs(View, { style: styles.container, children: [renderIconOrImage(), _jsxs(View, { style: styles.contentContainer, children: [_jsxs(View, { style: styles.contentTextContainer, children: [_jsxs(View, { style: styles.textContainer, children: [_jsx(Heading, { size: "sm", style: styles.heading, textAlign: hasIllustration && direction === 'vertical' ? 'center' : 'left', children: heading }), _jsx(BodyText, { size: "md", style: styles.description, textAlign: hasIllustration && direction === 'vertical' ? 'center' : 'left', children: description })] }), renderAction()] }), onPress && (_jsx(UnstyledIconButton, { icon: ChevronRightSmallIcon, size: "sm", onPress: onPress, style: styles.chevron })), onClose && (_jsx(UnstyledIconButton, { icon: CloseSmallIcon, size: "sm", onPress: onClose, style: styles.closeButton, accessibilityLabel: "Close banner" }))] })] }));
|
|
36
36
|
if (onPress) {
|
|
37
37
|
return (_jsx(Card, { variant: variant, style: [styles.card, style], ...props, children: _jsx(Pressable, { onPress: onPress, accessibilityRole: "button", style: styles.pressable, children: content }) }));
|
|
38
38
|
}
|
|
@@ -92,6 +92,7 @@ const styles = StyleSheet.create(theme => ({
|
|
|
92
92
|
},
|
|
93
93
|
},
|
|
94
94
|
imageWrapper: {
|
|
95
|
+
flexDirection: 'row',
|
|
95
96
|
variants: {
|
|
96
97
|
direction: {
|
|
97
98
|
horizontal: {},
|
|
@@ -103,8 +104,8 @@ const styles = StyleSheet.create(theme => ({
|
|
|
103
104
|
},
|
|
104
105
|
image: {
|
|
105
106
|
borderRadius: theme.borderRadius.md,
|
|
106
|
-
borderWidth: theme.borderWidth[1],
|
|
107
107
|
borderColor: theme.color.border.strong,
|
|
108
|
+
borderWidth: theme.borderWidth[1],
|
|
108
109
|
variants: {
|
|
109
110
|
direction: {
|
|
110
111
|
horizontal: { width: 160, height: 95 },
|
|
@@ -116,15 +117,34 @@ const styles = StyleSheet.create(theme => ({
|
|
|
116
117
|
},
|
|
117
118
|
},
|
|
118
119
|
contentContainer: {
|
|
119
|
-
flex: 1,
|
|
120
|
-
flexDirection: 'row',
|
|
121
120
|
alignItems: 'flex-start',
|
|
122
121
|
justifyContent: 'space-between',
|
|
123
122
|
gap: theme.space.lg,
|
|
123
|
+
variants: {
|
|
124
|
+
direction: {
|
|
125
|
+
horizontal: {
|
|
126
|
+
flex: 1,
|
|
127
|
+
flexDirection: 'row',
|
|
128
|
+
},
|
|
129
|
+
vertical: {
|
|
130
|
+
flexDirection: 'column',
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
},
|
|
124
134
|
},
|
|
125
135
|
textContainer: {
|
|
126
|
-
|
|
136
|
+
gap: theme.space.sm,
|
|
137
|
+
},
|
|
138
|
+
contentTextContainer: {
|
|
127
139
|
gap: theme.space.lg,
|
|
140
|
+
variants: {
|
|
141
|
+
direction: {
|
|
142
|
+
horizontal: {
|
|
143
|
+
flex: 1,
|
|
144
|
+
},
|
|
145
|
+
vertical: {},
|
|
146
|
+
},
|
|
147
|
+
},
|
|
128
148
|
},
|
|
129
149
|
heading: {
|
|
130
150
|
compoundVariants: [
|
|
@@ -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
|
export type BannerDirection = 'horizontal' | 'vertical';
|
|
5
6
|
export interface BannerProps extends Omit<CardProps, 'noPadding' | 'variant' | 'colorScheme' | 'space' | 'gap' | 'rowGap' | 'columnGap' | 'flexDirection' | 'flexWrap' | 'alignItems' | 'justifyContent'> {
|
|
6
7
|
/**
|
|
@@ -27,18 +28,12 @@ export interface BannerProps extends Omit<CardProps, 'noPadding' | 'variant' | '
|
|
|
27
28
|
* Illustration to display in the banner
|
|
28
29
|
* Mutually exclusive with icon and image
|
|
29
30
|
*/
|
|
30
|
-
illustration?:
|
|
31
|
-
light: ImageSourcePropType | ReactElement | ComponentType;
|
|
32
|
-
dark: ImageSourcePropType | ReactElement | ComponentType;
|
|
33
|
-
};
|
|
31
|
+
illustration?: ThemedImageProps & ImageProps;
|
|
34
32
|
/**
|
|
35
33
|
* Image to display in the banner
|
|
36
34
|
* Mutually exclusive with icon and illustration
|
|
37
35
|
*/
|
|
38
|
-
image?:
|
|
39
|
-
light: ImageSourcePropType | ReactElement | ComponentType;
|
|
40
|
-
dark: ImageSourcePropType | ReactElement | ComponentType;
|
|
41
|
-
};
|
|
36
|
+
image?: ThemedImageProps & ImageProps;
|
|
42
37
|
/**
|
|
43
38
|
* Heading text
|
|
44
39
|
*/
|
|
@@ -3,6 +3,7 @@ import { SpaceValue, SpacingValues } from '../../types';
|
|
|
3
3
|
interface CardProps extends PressableProps {
|
|
4
4
|
variant?: 'emphasis' | 'subtle';
|
|
5
5
|
colorScheme?: 'neutralStrong' | 'neutralSubtle' | 'brand' | 'energy' | 'broadband' | 'mobile' | 'insurance' | 'cashback' | 'pig';
|
|
6
|
+
shadowColor?: 'functional' | 'brand' | 'energy' | 'broadband' | 'mobile' | 'insurance' | 'cashback' | 'pig';
|
|
6
7
|
noPadding?: boolean;
|
|
7
8
|
disabled?: boolean;
|
|
8
9
|
space?: SpacingValues;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import CardProps from './Card.props';
|
|
2
2
|
declare const Card: {
|
|
3
|
-
({ children, variant, colorScheme, noPadding, style, states, space, disabled, onPress, ...rest }: CardProps & {
|
|
3
|
+
({ children, variant, colorScheme, shadowColor, noPadding, style, states, space, disabled, onPress, ...rest }: CardProps & {
|
|
4
4
|
states?: {
|
|
5
5
|
active?: boolean;
|
|
6
6
|
disabled?: boolean;
|
|
@@ -83,7 +83,7 @@ const collectChildActionHandlers = (children) => React.Children.toArray(children
|
|
|
83
83
|
}
|
|
84
84
|
return handlers;
|
|
85
85
|
}, []);
|
|
86
|
-
const Card = ({ children, variant = 'subtle', colorScheme = 'neutralStrong', noPadding = false, style, states, space, disabled = false, onPress, ...rest }) => {
|
|
86
|
+
const Card = ({ children, variant = 'subtle', colorScheme = 'neutralStrong', shadowColor, noPadding = false, style, states, space, disabled = false, onPress, ...rest }) => {
|
|
87
87
|
const { active } = states || { active: false };
|
|
88
88
|
const childActionHandlers = collectChildActionHandlers(children);
|
|
89
89
|
const hasActions = checkForComponentType(children, 'CardAction');
|
|
@@ -123,6 +123,7 @@ const Card = ({ children, variant = 'subtle', colorScheme = 'neutralStrong', noP
|
|
|
123
123
|
showPressed,
|
|
124
124
|
disabled,
|
|
125
125
|
space: hasActions || hasContent ? 'none' : space,
|
|
126
|
+
shadowColor,
|
|
126
127
|
});
|
|
127
128
|
const renderChildren = () => {
|
|
128
129
|
// Default: render children as-is
|
|
@@ -190,6 +191,32 @@ const styles = StyleSheet.create(theme => ({
|
|
|
190
191
|
borderWidth: theme.components.card.brand.borderWidth,
|
|
191
192
|
},
|
|
192
193
|
},
|
|
194
|
+
shadowColor: {
|
|
195
|
+
functional: {
|
|
196
|
+
boxShadow: theme.helpers.shadow.functional,
|
|
197
|
+
},
|
|
198
|
+
brand: {
|
|
199
|
+
boxShadow: theme.helpers.shadow.brand,
|
|
200
|
+
},
|
|
201
|
+
energy: {
|
|
202
|
+
boxShadow: theme.helpers.shadow.energy,
|
|
203
|
+
},
|
|
204
|
+
broadband: {
|
|
205
|
+
boxShadow: theme.helpers.shadow.broadband,
|
|
206
|
+
},
|
|
207
|
+
mobile: {
|
|
208
|
+
boxShadow: theme.helpers.shadow.mobile,
|
|
209
|
+
},
|
|
210
|
+
insurance: {
|
|
211
|
+
boxShadow: theme.helpers.shadow.insurance,
|
|
212
|
+
},
|
|
213
|
+
cashback: {
|
|
214
|
+
boxShadow: theme.helpers.shadow.cashback,
|
|
215
|
+
},
|
|
216
|
+
pig: {
|
|
217
|
+
boxShadow: theme.helpers.shadow.pig,
|
|
218
|
+
},
|
|
219
|
+
},
|
|
193
220
|
noPadding: {
|
|
194
221
|
true: {
|
|
195
222
|
padding: theme.components.card.mobile.paddingNone,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ReactElement } from 'react';
|
|
2
2
|
import { ImageProps } from 'react-native';
|
|
3
3
|
import CardProps from '../Card/Card.props';
|
|
4
|
-
interface HighlightBannerProps extends Omit<CardProps, 'noPadding' | 'variant' | 'space' | 'gap' | 'rowGap' | 'columnGap' | 'flexDirection' | 'flexWrap' | 'alignItems' | 'justifyContent'> {
|
|
4
|
+
interface HighlightBannerProps extends Omit<CardProps, 'noPadding' | 'variant' | 'space' | 'gap' | 'rowGap' | 'columnGap' | 'flexDirection' | 'flexWrap' | 'alignItems' | 'justifyContent' | 'colorScheme'> {
|
|
5
5
|
heading?: string;
|
|
6
6
|
headingColor?: 'pig' | 'energy' | 'broadband' | 'mobile' | 'insurance' | 'cashback' | 'highlight';
|
|
7
7
|
variant?: 'emphasis' | 'subtle';
|
|
@@ -44,7 +44,7 @@ const List = ({ children, heading, helperText, headerTrailingContent, ...props }
|
|
|
44
44
|
const updatedChildren = markFirstListItem(children);
|
|
45
45
|
const value = useMemo(() => ({ loading, disabled, container }), [loading, disabled, container]);
|
|
46
46
|
styles.useVariants({ disabled });
|
|
47
|
-
return (_jsx(ListContext.Provider, { value: value, children: _jsxs(View, { ...props, style: [styles.container, props.style], children: [heading ? (_jsx(SectionHeader, { heading: heading, helperText: helperText, trailingContent: headerTrailingContent })) : null, container === 'none' ? (_jsx(View, { children: updatedChildren })) : (_jsx(Card, { ...containerToCard, noPadding: true, style: styles.card, children: _jsx(_Fragment, { children: updatedChildren }) }))] }) }));
|
|
47
|
+
return (_jsx(ListContext.Provider, { value: value, children: _jsxs(View, { ...props, style: [styles.container, props.style], children: [heading ? (_jsx(SectionHeader, { heading: heading, helperText: helperText, trailingContent: headerTrailingContent })) : null, container === 'none' ? (_jsx(View, { children: updatedChildren })) : (React.Children.count(updatedChildren) > 0 && (_jsx(Card, { ...containerToCard, noPadding: true, style: styles.card, children: _jsx(_Fragment, { children: updatedChildren }) })))] }) }));
|
|
48
48
|
};
|
|
49
49
|
List.displayName = 'List';
|
|
50
50
|
const styles = StyleSheet.create(theme => ({
|
|
@@ -12,8 +12,8 @@ ListActionTrailingIcon.displayName = 'ListActionTrailingIcon';
|
|
|
12
12
|
const styles = StyleSheet.create(theme => ({
|
|
13
13
|
icon: {
|
|
14
14
|
color: theme.color.icon.primary,
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
minWidth: 20,
|
|
16
|
+
minHeight: 20,
|
|
17
17
|
},
|
|
18
18
|
}));
|
|
19
19
|
export default ListActionTrailingIcon;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const RadioCardGroupContext: import("react").Context<{
|
|
2
|
+
flexDirection?: "row" | "column" | "row-reverse" | "column-reverse";
|
|
3
|
+
flexWrap?: "nowrap" | "wrap" | "wrap-reverse";
|
|
4
|
+
justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly";
|
|
5
|
+
alignItems?: "flex-start" | "flex-end" | "center" | "stretch" | "baseline";
|
|
6
|
+
}>;
|
|
7
|
+
export declare const useRadioCardGroupContext: () => {
|
|
8
|
+
flexDirection?: "row" | "column" | "row-reverse" | "column-reverse";
|
|
9
|
+
flexWrap?: "nowrap" | "wrap" | "wrap-reverse";
|
|
10
|
+
justifyContent?: "flex-start" | "flex-end" | "center" | "space-between" | "space-around" | "space-evenly";
|
|
11
|
+
alignItems?: "flex-start" | "flex-end" | "center" | "stretch" | "baseline";
|
|
12
|
+
};
|
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
2
3
|
import { View } from 'react-native';
|
|
3
4
|
import { StyleSheet } from 'react-native-unistyles';
|
|
4
5
|
import { Grid } from '../Grid';
|
|
6
|
+
import { RadioCardGroupContext } from './RadioCardGroup.context';
|
|
5
7
|
const RadioCardGroup = ({ children, gap = '200', style, flexDirection = 'row', flexWrap, justifyContent, alignItems, columns, ...props }) => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
const context = useMemo(() => {
|
|
9
|
+
return { flexDirection, flexWrap, justifyContent, alignItems };
|
|
10
|
+
}, [flexDirection, flexWrap, justifyContent, alignItems]);
|
|
11
|
+
return columns ? (_jsx(RadioCardGroupContext.Provider, { value: context, children: _jsx(Grid, { ...props, gap: gap, columns: columns, style: style, children: children }) })) : (_jsx(RadioCardGroupContext.Provider, { value: context, children: _jsx(View, { ...props, style: [
|
|
12
|
+
styles.containerGap(gap),
|
|
13
|
+
{
|
|
14
|
+
flexDirection,
|
|
15
|
+
flexWrap,
|
|
16
|
+
justifyContent,
|
|
17
|
+
alignItems,
|
|
18
|
+
},
|
|
19
|
+
style,
|
|
20
|
+
], children: children }) }));
|
|
16
21
|
};
|
|
17
22
|
const styles = StyleSheet.create(theme => ({
|
|
18
23
|
containerGap: (gap) => ({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import LabelProps from '../Label/Label.props';
|
|
2
2
|
declare const RadioCardLabel: {
|
|
3
|
-
({ children, ...props }: LabelProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
({ children, style, ...props }: LabelProps): import("react/jsx-runtime").JSX.Element;
|
|
4
4
|
displayName: string;
|
|
5
5
|
};
|
|
6
6
|
export default RadioCardLabel;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
2
3
|
import { Label } from '../Label';
|
|
3
|
-
const RadioCardLabel = ({ children, ...props }) => _jsx(Label, { ...props, children: children });
|
|
4
|
+
const RadioCardLabel = ({ children, style, ...props }) => (_jsx(Label, { ...props, style: [styles.label, style], children: children }));
|
|
5
|
+
const styles = StyleSheet.create({
|
|
6
|
+
label: {
|
|
7
|
+
flexShrink: 1,
|
|
8
|
+
},
|
|
9
|
+
});
|
|
4
10
|
RadioCardLabel.displayName = 'RadioCardLabel';
|
|
5
11
|
export default RadioCardLabel;
|
|
@@ -3,14 +3,17 @@ import { useMemo } from 'react';
|
|
|
3
3
|
import { StyleSheet } from 'react-native-unistyles';
|
|
4
4
|
import { Pressable } from 'react-native';
|
|
5
5
|
import { RadioCardContext } from './RadioCard.context';
|
|
6
|
+
import { useRadioCardGroupContext } from './RadioCardGroup.context';
|
|
6
7
|
const RadioCardRoot = ({ children, style, states, ...props }) => {
|
|
7
8
|
const { checked, active } = states ?? {};
|
|
9
|
+
const { flexDirection } = useRadioCardGroupContext() ?? {};
|
|
8
10
|
const value = useMemo(() => ({
|
|
9
11
|
checked,
|
|
10
12
|
active,
|
|
11
13
|
}), [checked, active]);
|
|
12
14
|
styles.useVariants({
|
|
13
15
|
selected: checked,
|
|
16
|
+
flexDirection,
|
|
14
17
|
});
|
|
15
18
|
return (_jsx(RadioCardContext.Provider, { value: value, children: _jsx(Pressable, { ...props, style: [styles.container, style], children: children }) }));
|
|
16
19
|
};
|
|
@@ -37,6 +40,16 @@ const styles = StyleSheet.create(theme => ({
|
|
|
37
40
|
margin: -theme.components.card.selectable.borderWidthSelected / 2,
|
|
38
41
|
},
|
|
39
42
|
},
|
|
43
|
+
flexDirection: {
|
|
44
|
+
row: {},
|
|
45
|
+
column: {
|
|
46
|
+
width: '100%',
|
|
47
|
+
},
|
|
48
|
+
'row-reverse': {},
|
|
49
|
+
'column-reverse': {
|
|
50
|
+
width: '100%',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
40
53
|
},
|
|
41
54
|
_web: {
|
|
42
55
|
'_focus-visible': {
|
package/build/core/themes.d.ts
CHANGED
|
@@ -2,6 +2,16 @@ import { DimensionValue } from 'react-native';
|
|
|
2
2
|
import { components } from '../tokens';
|
|
3
3
|
export declare const lightTheme: {
|
|
4
4
|
readonly helpers: {
|
|
5
|
+
shadow: {
|
|
6
|
+
functional: string;
|
|
7
|
+
brand: string;
|
|
8
|
+
energy: string;
|
|
9
|
+
broadband: string;
|
|
10
|
+
mobile: string;
|
|
11
|
+
insurance: string;
|
|
12
|
+
cashback: string;
|
|
13
|
+
pig: string;
|
|
14
|
+
};
|
|
5
15
|
focusVisible: {
|
|
6
16
|
outlineStyle: string;
|
|
7
17
|
outlineWidth: number;
|
|
@@ -1352,6 +1362,16 @@ export declare const lightTheme: {
|
|
|
1352
1362
|
};
|
|
1353
1363
|
export declare const darkTheme: {
|
|
1354
1364
|
readonly helpers: {
|
|
1365
|
+
shadow: {
|
|
1366
|
+
functional: string;
|
|
1367
|
+
brand: string;
|
|
1368
|
+
energy: string;
|
|
1369
|
+
broadband: string;
|
|
1370
|
+
mobile: string;
|
|
1371
|
+
insurance: string;
|
|
1372
|
+
cashback: string;
|
|
1373
|
+
pig: string;
|
|
1374
|
+
};
|
|
1355
1375
|
focusVisible: {
|
|
1356
1376
|
outlineStyle: string;
|
|
1357
1377
|
outlineWidth: number;
|
|
@@ -2714,6 +2734,16 @@ export declare const darkTheme: {
|
|
|
2714
2734
|
export declare const themes: {
|
|
2715
2735
|
readonly light: {
|
|
2716
2736
|
readonly helpers: {
|
|
2737
|
+
shadow: {
|
|
2738
|
+
functional: string;
|
|
2739
|
+
brand: string;
|
|
2740
|
+
energy: string;
|
|
2741
|
+
broadband: string;
|
|
2742
|
+
mobile: string;
|
|
2743
|
+
insurance: string;
|
|
2744
|
+
cashback: string;
|
|
2745
|
+
pig: string;
|
|
2746
|
+
};
|
|
2717
2747
|
focusVisible: {
|
|
2718
2748
|
outlineStyle: string;
|
|
2719
2749
|
outlineWidth: number;
|
|
@@ -4064,6 +4094,16 @@ export declare const themes: {
|
|
|
4064
4094
|
};
|
|
4065
4095
|
readonly dark: {
|
|
4066
4096
|
readonly helpers: {
|
|
4097
|
+
shadow: {
|
|
4098
|
+
functional: string;
|
|
4099
|
+
brand: string;
|
|
4100
|
+
energy: string;
|
|
4101
|
+
broadband: string;
|
|
4102
|
+
mobile: string;
|
|
4103
|
+
insurance: string;
|
|
4104
|
+
cashback: string;
|
|
4105
|
+
pig: string;
|
|
4106
|
+
};
|
|
4067
4107
|
focusVisible: {
|
|
4068
4108
|
outlineStyle: string;
|
|
4069
4109
|
outlineWidth: number;
|
package/build/core/themes.js
CHANGED
|
@@ -254,6 +254,16 @@ const shared = {
|
|
|
254
254
|
};
|
|
255
255
|
const lightHelpers = {
|
|
256
256
|
...shared.helpers,
|
|
257
|
+
shadow: {
|
|
258
|
+
functional: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.default}`,
|
|
259
|
+
brand: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.brand}`,
|
|
260
|
+
energy: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.energy}`,
|
|
261
|
+
broadband: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.broadband}`,
|
|
262
|
+
mobile: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.mobile}`,
|
|
263
|
+
insurance: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.insurance}`,
|
|
264
|
+
cashback: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.cashback}`,
|
|
265
|
+
pig: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.pig}`,
|
|
266
|
+
},
|
|
257
267
|
focusVisible: {
|
|
258
268
|
outlineStyle: 'solid',
|
|
259
269
|
outlineWidth: 2,
|
|
@@ -286,6 +296,16 @@ export const lightTheme = {
|
|
|
286
296
|
};
|
|
287
297
|
const darkHelpers = {
|
|
288
298
|
...shared.helpers,
|
|
299
|
+
shadow: {
|
|
300
|
+
functional: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.default}`,
|
|
301
|
+
brand: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.brand}`,
|
|
302
|
+
energy: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.energy}`,
|
|
303
|
+
broadband: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.broadband}`,
|
|
304
|
+
mobile: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.mobile}`,
|
|
305
|
+
insurance: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.insurance}`,
|
|
306
|
+
cashback: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.cashback}`,
|
|
307
|
+
pig: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.pig}`,
|
|
308
|
+
},
|
|
289
309
|
focusVisible: {
|
|
290
310
|
outlineStyle: 'solid',
|
|
291
311
|
outlineWidth: 2,
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Meta } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import { BackToTopButton, NextPrevPage } from './components';
|
|
3
|
+
|
|
4
|
+
<Meta title="Guides / Adding Shadows" />
|
|
5
|
+
<BackToTopButton />
|
|
6
|
+
|
|
7
|
+
# Adding Shadows
|
|
8
|
+
|
|
9
|
+
You can add shadows to your components in Hearth React Native using the Unistyles styling system. Shadows help create depth and visual hierarchy in your UI.
|
|
10
|
+
|
|
11
|
+
- [Using Predefined Shadows](#using-predefined-shadows)
|
|
12
|
+
- [Components with Shadow Props](#components-with-shadow-props)
|
|
13
|
+
|
|
14
|
+
## Using Predefined Shadows
|
|
15
|
+
|
|
16
|
+
Hearth provides a set of predefined shadow styles that you can easily apply to your components. These shadows are defined in the theme and can be accessed via the `theme.helpers.shadow` object.
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { View } from 'react-native';
|
|
20
|
+
import { StyleSheet, Input } from '@utilitywarehouse/hearth-react-native';
|
|
21
|
+
|
|
22
|
+
const styles = StyleSheet.create(theme => ({
|
|
23
|
+
input: {
|
|
24
|
+
boxShadow: theme.helpers.shadow.functional, // Apply a predefined shadow
|
|
25
|
+
},
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
const MyComponent = () => (
|
|
29
|
+
<View>
|
|
30
|
+
<Input placeholder="Input with shadow" style={styles.input} />
|
|
31
|
+
</View>
|
|
32
|
+
);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Components with Shadow Props
|
|
36
|
+
|
|
37
|
+
Some Hearth components, like `Card`, allow you to specify shadow colors directly via props. You can use the `shadowColor` prop to set the shadow color based on the theme.
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import { Card } from '@utilitywarehouse/hearth-react-native';
|
|
41
|
+
|
|
42
|
+
const MyComponent = () => <Card shadowColor="brand">{/* Card content */}</Card>;
|
|
43
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@utilitywarehouse/hearth-react-native",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Utility Warehouse React Native UI library",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
"vite": "^7.1.3",
|
|
57
57
|
"vite-plugin-svgr": "^4.5.0",
|
|
58
58
|
"vitest": "^3.2.4",
|
|
59
|
+
"@utilitywarehouse/hearth-fonts": "^0.0.4",
|
|
59
60
|
"@utilitywarehouse/hearth-react-icons": "^0.7.3",
|
|
60
61
|
"@utilitywarehouse/hearth-react-native-icons": "^0.7.3",
|
|
61
62
|
"@utilitywarehouse/hearth-svg-assets": "^0.2.0",
|
|
62
|
-
"@utilitywarehouse/hearth-fonts": "^0.0.4",
|
|
63
63
|
"@utilitywarehouse/hearth-tokens": "^0.1.3"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
@@ -24,7 +24,7 @@ The `Banner` component is a versatile card-based component for displaying inform
|
|
|
24
24
|
- [With Link](#with-link)
|
|
25
25
|
- [Pressable](#pressable)
|
|
26
26
|
- [With Close Button](#with-close-button)
|
|
27
|
-
- [Vertical Layout](#vertical-layout)
|
|
27
|
+
- [Vertical Layout](#vertical-layout-1)
|
|
28
28
|
- [Color Schemes](#color-schemes)
|
|
29
29
|
- [Complex Examples](#complex-examples)
|
|
30
30
|
|
|
@@ -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,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
|
+
};
|
|
@@ -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>
|
|
@@ -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
|
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native-unistyles';
|
|
1
2
|
import { Label } from '../Label';
|
|
2
3
|
import LabelProps from '../Label/Label.props';
|
|
3
4
|
|
|
4
|
-
const RadioCardLabel = ({ children, ...props }: LabelProps) =>
|
|
5
|
+
const RadioCardLabel = ({ children, style, ...props }: LabelProps) => (
|
|
6
|
+
<Label {...props} style={[styles.label, style]}>
|
|
7
|
+
{children}
|
|
8
|
+
</Label>
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
const styles = StyleSheet.create({
|
|
12
|
+
label: {
|
|
13
|
+
flexShrink: 1,
|
|
14
|
+
},
|
|
15
|
+
});
|
|
5
16
|
|
|
6
17
|
RadioCardLabel.displayName = 'RadioCardLabel';
|
|
7
18
|
|
|
@@ -4,6 +4,7 @@ import { StyleSheet } from 'react-native-unistyles';
|
|
|
4
4
|
import { Pressable, ViewStyle } from 'react-native';
|
|
5
5
|
import { RadioCardContext } from './RadioCard.context';
|
|
6
6
|
import type RadioCardProps from './RadioCard.props';
|
|
7
|
+
import { useRadioCardGroupContext } from './RadioCardGroup.context';
|
|
7
8
|
|
|
8
9
|
const RadioCardRoot = ({
|
|
9
10
|
children,
|
|
@@ -13,6 +14,8 @@ const RadioCardRoot = ({
|
|
|
13
14
|
}: RadioCardProps & { states?: { disabled?: boolean; checked?: boolean; active?: boolean } }) => {
|
|
14
15
|
const { checked, active } = states ?? {};
|
|
15
16
|
|
|
17
|
+
const { flexDirection } = useRadioCardGroupContext() ?? {};
|
|
18
|
+
|
|
16
19
|
const value = useMemo(
|
|
17
20
|
() => ({
|
|
18
21
|
checked,
|
|
@@ -23,6 +26,7 @@ const RadioCardRoot = ({
|
|
|
23
26
|
|
|
24
27
|
styles.useVariants({
|
|
25
28
|
selected: checked,
|
|
29
|
+
flexDirection,
|
|
26
30
|
});
|
|
27
31
|
|
|
28
32
|
return (
|
|
@@ -39,6 +43,7 @@ RadioCardRoot.displayName = 'RadioCardRoot';
|
|
|
39
43
|
const styles = StyleSheet.create(theme => ({
|
|
40
44
|
container: {
|
|
41
45
|
flexDirection: 'column',
|
|
46
|
+
|
|
42
47
|
gap: theme.components.card.selectable.gap,
|
|
43
48
|
borderRadius: theme.components.card.borderRadius,
|
|
44
49
|
backgroundColor: theme.color.surface.neutral.strong,
|
|
@@ -58,6 +63,16 @@ const styles = StyleSheet.create(theme => ({
|
|
|
58
63
|
margin: -theme.components.card.selectable.borderWidthSelected / 2,
|
|
59
64
|
},
|
|
60
65
|
},
|
|
66
|
+
flexDirection: {
|
|
67
|
+
row: {},
|
|
68
|
+
column: {
|
|
69
|
+
width: '100%',
|
|
70
|
+
},
|
|
71
|
+
'row-reverse': {},
|
|
72
|
+
'column-reverse': {
|
|
73
|
+
width: '100%',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
61
76
|
},
|
|
62
77
|
_web: {
|
|
63
78
|
'_focus-visible': {
|
package/src/core/themes.ts
CHANGED
|
@@ -269,6 +269,16 @@ const shared = {
|
|
|
269
269
|
|
|
270
270
|
const lightHelpers = {
|
|
271
271
|
...shared.helpers,
|
|
272
|
+
shadow: {
|
|
273
|
+
functional: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.default}`,
|
|
274
|
+
brand: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.brand}`,
|
|
275
|
+
energy: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.energy}`,
|
|
276
|
+
broadband: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.broadband}`,
|
|
277
|
+
mobile: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.mobile}`,
|
|
278
|
+
insurance: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.insurance}`,
|
|
279
|
+
cashback: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.cashback}`,
|
|
280
|
+
pig: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${light.shadow.pig}`,
|
|
281
|
+
},
|
|
272
282
|
focusVisible: {
|
|
273
283
|
outlineStyle: 'solid',
|
|
274
284
|
outlineWidth: 2,
|
|
@@ -303,6 +313,16 @@ export const lightTheme = {
|
|
|
303
313
|
|
|
304
314
|
const darkHelpers = {
|
|
305
315
|
...shared.helpers,
|
|
316
|
+
shadow: {
|
|
317
|
+
functional: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.default}`,
|
|
318
|
+
brand: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.brand}`,
|
|
319
|
+
energy: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.energy}`,
|
|
320
|
+
broadband: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.broadband}`,
|
|
321
|
+
mobile: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.mobile}`,
|
|
322
|
+
insurance: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.insurance}`,
|
|
323
|
+
cashback: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.cashback}`,
|
|
324
|
+
pig: `${shadow.mobile.md.x}px ${shadow.mobile.md.y}px ${shadow.mobile.md.spread}px ${dark.shadow.pig}`,
|
|
325
|
+
},
|
|
306
326
|
focusVisible: {
|
|
307
327
|
outlineStyle: 'solid',
|
|
308
328
|
outlineWidth: 2,
|