Skip to content

Commit 9f1982c

Browse files
JanHamaraJán Hamara
and
Ján Hamara
authored
feat: implement compound component approach for InfoBanner (#336)
* feat(infobanner): implement compound component approach for infobanner * feat(infobanner): remove export declaration conflict * feat(infobanner): add modifications from MR suggestions removing linklist --------- Co-authored-by: Ján Hamara <[email protected]>
1 parent f41bd14 commit 9f1982c

File tree

4 files changed

+112
-8
lines changed

4 files changed

+112
-8
lines changed

src/components/InfoBanner/InfoBanner.tsx

+21-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import styled from 'styled-components';
33
import { variant as styledVariant } from 'styled-system';
44
import { get } from '../../utils/themeGet';
5+
import { theme } from '../../essentials/theme';
56
import {
67
CheckCircleSolidIcon,
78
CloseCircleSolidIcon,
@@ -12,6 +13,7 @@ import {
1213
import { BoxProps, Box } from '../Box/Box';
1314
import { Link } from '../Link/Link';
1415
import { Text } from '../Text/Text';
16+
import { Headline } from '../Headline/Headline';
1517
import { Spaces } from '../../essentials';
1618

1719
interface InfoBannerProps extends BoxProps {
@@ -106,21 +108,34 @@ const emphasizedIconColorVariants = styledVariant({
106108
}
107109
});
108110

109-
const RoundedBox = styled(Box)<BoxWithVariant>`
111+
export const RoundedBox = styled(Box).attrs({ theme })<BoxWithVariant>`
110112
display: flex;
111113
flex-direction: row;
112114
justify-content: flex-start;
113115
border-radius: ${get('radii.3')};
114116
border: 0.0625rem solid;
115117
padding: ${`${Spaces[1]} ${Spaces[2]} ${Spaces[1]} ${Spaces[1]}`};
116118
${({ emphasized }) => (emphasized ? emphasizedBannerVariants : bannerVariants)};
119+
120+
--info-banner-text-color: ${({ emphasized, variant }) =>
121+
emphasized && variant !== 'warning'
122+
? get('semanticColors.text.primaryInverted')
123+
: get('semanticColors.text.primary')};
124+
--info-banner-link-color: ${({ emphasized, variant }) =>
125+
emphasized && variant !== 'warning'
126+
? get('semanticColors.text.primaryInverted')
127+
: get('semanticColors.text.link')};
128+
--info-banner-link-hover-color: ${({ emphasized, variant }) =>
129+
emphasized && variant !== 'warning'
130+
? get('semanticColors.text.tertiary')
131+
: get('semanticColors.text.linkHover')};
117132
`;
118133

119-
const IconBox = styled(Box)<BoxWithVariant>`
134+
export const IconBox = styled(Box)<BoxWithVariant>`
120135
${({ emphasized }) => (emphasized ? emphasizedIconColorVariants : iconColorVariants)};
121136
`;
122137

123-
const ICON_VARIANTS: {
138+
export const ICON_VARIANTS: {
124139
[key in InfoBannerVariants]: React.FC<IconProps>;
125140
} = {
126141
warning: WarningSolidIcon,
@@ -129,7 +144,7 @@ const ICON_VARIANTS: {
129144
error: CloseCircleSolidIcon
130145
};
131146

132-
const ROLE_VARIANTS: {
147+
export const ROLE_VARIANTS: {
133148
[key in InfoBannerVariants]: string;
134149
} = {
135150
error: 'alert',
@@ -156,9 +171,9 @@ const InfoBanner = ({
156171
<BannerIcon size={20} color="inherit" />
157172
</IconBox>
158173
<Box display="flex" flexDirection="column">
159-
<Text fontWeight="bold" textAlign="left" inverted={isInverted}>
174+
<Headline as="h4" textAlign="left" inverted={isInverted}>
160175
{title}
161-
</Text>
176+
</Headline>
162177
<Text fontSize="small" textAlign="left" inverted={isInverted}>
163178
{description}
164179
</Text>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import React, { ReactNode } from 'react';
2+
import styled from 'styled-components';
3+
4+
import { BoxProps, Box } from '../../Box/Box';
5+
import { Headline } from '../../Headline/Headline';
6+
import { Link as WaveLink } from '../../Link/Link';
7+
import { Text } from '../../Text/Text';
8+
9+
import { ICON_VARIANTS, IconBox, InfoBannerVariants, ROLE_VARIANTS, RoundedBox } from '../InfoBanner';
10+
11+
interface CardProps extends BoxProps {
12+
children: ReactNode;
13+
variant?: InfoBannerVariants;
14+
emphasized?: boolean;
15+
}
16+
17+
const StyledTitle = styled(Headline).attrs({ as: 'h4', textAlign: 'left' })`
18+
color: var(--info-banner-text-color);
19+
`;
20+
21+
const StyledDescription = styled(Text).attrs({ fontSize: 'small', textAlign: 'left' })`
22+
color: var(--info-banner-text-color);
23+
`;
24+
25+
const StyledLink = styled(WaveLink).attrs({ fontSize: 0, textAlign: 'left', target: '_blank', marginTop: '0.25rem' })`
26+
&:link,
27+
&:visited {
28+
color: var(--info-banner-link-color);
29+
}
30+
31+
&:hover,
32+
&:active {
33+
color: var(--info-banner-link-hover-color);
34+
}
35+
`;
36+
37+
const Title = ({ children }: { children: string }) => <StyledTitle>{children}</StyledTitle>;
38+
39+
const Description = ({ children }: { children: string }) => <StyledDescription>{children}</StyledDescription>;
40+
41+
const Link = ({ linkUrl, linkText }: { linkUrl: string; linkText: string }) => (
42+
<StyledLink href={linkUrl}>{linkText}</StyledLink>
43+
);
44+
45+
// TODO: Document this compound component properly when Storybook migration is complete
46+
const InfoBannerCard = ({ children, variant = 'info', emphasized, ...props }: CardProps): JSX.Element => {
47+
const BannerIcon = ICON_VARIANTS[variant];
48+
49+
return (
50+
<RoundedBox variant={variant} emphasized={emphasized} role={ROLE_VARIANTS[variant]} {...props}>
51+
<IconBox mr={1} variant={variant} emphasized={emphasized}>
52+
<BannerIcon size={20} color="inherit" />
53+
</IconBox>
54+
<Box display="flex" flexDirection="column">
55+
{children}
56+
</Box>
57+
</RoundedBox>
58+
);
59+
};
60+
61+
InfoBannerCard.Title = Title;
62+
InfoBannerCard.Description = Description;
63+
InfoBannerCard.Link = Link;
64+
65+
export { InfoBannerCard };

src/components/InfoBanner/docs/InfoBanner.mdx

+25-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ route: /components/info-banner
66

77
import { Playground } from 'docz';
88
import { InfoBanner } from '../InfoBanner'
9+
import { InfoBannerCard } from '../blocks/InfoBannerCard'
910
import { InfoBannerPropsTable } from './InfoBannerPropsTable'
1011
import { Combination } from '../../../docs/Combination'
1112
import { StyledSystemLinks } from '../../../docs/StyledSystemLinks'
@@ -22,11 +23,33 @@ The InfoBanner is used to communicate a vibrant message, state change or importa
2223

2324

2425
## Examples
25-
26-
<InfoBanner title='Please do not share details about this information.' description='In case of uncertainty please contact Fraud department.' />
26+
<InfoBanner mt={2} title='Please do not share details about this information.' description='In case of uncertainty please contact Fraud department.' />
2727
<br />
2828
<InfoBanner title='Possible Fraud' description='This passenger has more than 20 linked accounts.' variant='warning' />
2929

30+
<br/>
31+
32+
## Compound components approach
33+
34+
You may also use compound components approach to build up your InfoBanner (e.g. when you need multiple links in a single banner as below)
35+
36+
Available compound components:
37+
- **InfoBannerCard** (Wrapper)
38+
- **InfoBannerCard.Title**
39+
- **InfoBannerCard.Description**
40+
- **InfoBannerCard.Link**
41+
42+
The wrapper component (**InfoBannerCard**) accepts same props as **InfoBanner** component, if variant is applied, it's styling will get automatically applied to children compound components.
43+
44+
<Playground>
45+
<InfoBannerCard variant='warning'>
46+
<InfoBannerCard.Title>Issue with documents</InfoBannerCard.Title>
47+
<InfoBannerCard.Description>Your uploaded documents don't match the records. Please check the following sources:</InfoBannerCard.Description>
48+
<InfoBannerCard.Link linkText='Driver documents' linkUrl='https://wave.free-now.com' />
49+
<InfoBannerCard.Link linkText='Vehicle documents' linkUrl='https://wave.free-now.com' />
50+
<InfoBannerCard.Link linkText='Driver Profile' linkUrl='https://wave.free-now.com' />
51+
</InfoBannerCard>
52+
</Playground>
3053

3154
## Playground
3255

src/components/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,4 @@ export { SelectListProps } from './SelectList/types';
5555
export { Row, RowProps, Column, ColumnProps } from './Grid/Grid';
5656
export { Popover, PopoverProps } from './Popover/Popover';
5757
export { InfoBanner, InfoBannerProps, InfoBannerVariants } from './InfoBanner/InfoBanner';
58+
export { InfoBannerCard } from './InfoBanner/blocks/InfoBannerCard';

0 commit comments

Comments
 (0)