Skip to content

Commit 209c9b0

Browse files
feat(InlineMessage): Convert InlineMessage component to CSS Modules behind feature flag (#5204)
* initial commit * add changeset * key icon classnames off of Feature Flag * refactor * add dev story to vrt tests * style fix and remove !important * fix dev id * test(vrt): update snapshots * fix dev story --------- Co-authored-by: randall-krauskopf <[email protected]>
1 parent bc8be36 commit 209c9b0

File tree

4 files changed

+128
-55
lines changed

4 files changed

+128
-55
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/react": minor
3+
---
4+
5+
Migrate 'InlineMessage' component to use CSS modules

packages/react/src/InlineMessage/InlineMessage.dev.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const meta = {
99

1010
export default meta
1111

12+
// Previous Styled version of the component didn't accept an sx prop so no need to test if that works.
1213
export const DevDefault = () => {
1314
return <InlineMessage variant="unavailable">An example inline message</InlineMessage>
1415
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
.InlineMessage {
2+
display: grid;
3+
/* stylelint-disable-next-line primer/typography */
4+
font-size: var(--inline-message-fontSize);
5+
/* stylelint-disable-next-line primer/typography */
6+
line-height: var(--inline-message-lineHeight);
7+
/* stylelint-disable-next-line primer/colors */
8+
color: var(--inline-message-fgColor);
9+
column-gap: 0.5rem;
10+
grid-template-columns: auto 1fr;
11+
align-items: start;
12+
13+
&[data-size='small'] {
14+
--inline-message-fontSize: var(--text-body-size-small);
15+
--inline-message-lineHeight: var(--text-body-lineHeight-small, 1.6666);
16+
}
17+
18+
&[data-size='medium'] {
19+
--inline-message-fontSize: var(--text-body-size-medium);
20+
--inline-message-lineHeight: var(--text-body-lineHeight-medium, 1.4285);
21+
}
22+
23+
&[data-variant='warning'] {
24+
--inline-message-fgColor: var(--fgColor-attention);
25+
}
26+
27+
&[data-variant='critical'] {
28+
--inline-message-fgColor: var(--fgColor-danger);
29+
}
30+
31+
&[data-variant='success'] {
32+
--inline-message-fgColor: var(--fgColor-success);
33+
}
34+
35+
&[data-variant='unavailable'] {
36+
--inline-message-fgColor: var(--fgColor-muted);
37+
}
38+
}
39+
40+
.InlineMessageIcon {
41+
min-height: calc(var(--inline-message-lineHeight) * var(--inline-message-fontSize));
42+
}

packages/react/src/InlineMessage/InlineMessage.tsx

Lines changed: 80 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,105 @@
11
import {AlertFillIcon, AlertIcon, CheckCircleFillIcon, CheckCircleIcon} from '@primer/octicons-react'
2+
import {clsx} from 'clsx'
23
import React from 'react'
34
import styled from 'styled-components'
45
import {get} from '../constants'
5-
6+
import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent'
7+
import {useFeatureFlag} from '../FeatureFlags'
8+
import classes from './InlineMessage.module.css'
9+
import type {SxProp} from '../sx'
610
type MessageVariant = 'critical' | 'success' | 'unavailable' | 'warning'
711

8-
export type InlineMessageProps = React.ComponentPropsWithoutRef<'div'> & {
9-
/**
10-
* Specify the size of the InlineMessage
11-
*/
12-
size?: 'small' | 'medium'
12+
const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_team'
1313

14-
/**
15-
* Specify the type of the InlineMessage
16-
*/
17-
variant: MessageVariant
18-
}
14+
export type InlineMessageProps = React.ComponentPropsWithoutRef<'div'> &
15+
SxProp & {
16+
/**
17+
* Specify the size of the InlineMessage
18+
*/
19+
size?: 'small' | 'medium'
1920

20-
const StyledMessage = styled.div`
21-
display: grid;
22-
column-gap: 0.5rem;
23-
grid-template-columns: auto 1fr;
24-
align-items: start;
25-
color: var(--inline-message-fgColor, ${get('colors.fg.muted')});
26-
line-height: var(--inline-message-lineHeight);
27-
font-size: var(--inline-message-fontSize, ${get('fontSizes.1')});
28-
29-
&[data-size='small'] {
30-
--inline-message-fontSize: var(--text-body-size-small, ${get('fontSizes.0')});
31-
--inline-message-lineHeight: var(--text-body-lineHeight-small, 1.6666);
21+
/**
22+
* Specify the type of the InlineMessage
23+
*/
24+
variant: MessageVariant
3225
}
3326

34-
&[data-size='medium'] {
35-
--inline-message-fontSize: var(--text-body-size-medium, ${get('fontSizes.1')});
36-
--inline-message-lineHeight: var(--text-body-lineHeight-medium, 1.4285);
37-
}
27+
const StyledMessage = toggleStyledComponent(
28+
CSS_MODULES_FEATURE_FLAG,
29+
'div',
30+
styled.div`
31+
display: grid;
32+
column-gap: 0.5rem;
33+
grid-template-columns: auto 1fr;
34+
align-items: start;
35+
color: var(--inline-message-fgColor, ${get('colors.fg.muted')});
36+
line-height: var(--inline-message-lineHeight);
37+
font-size: var(--inline-message-fontSize, ${get('fontSizes.1')});
3838
39-
&[data-variant='warning'] {
40-
--inline-message-fgColor: ${get('colors.attention.fg')};
41-
}
39+
&[data-size='small'] {
40+
--inline-message-fontSize: var(--text-body-size-small, ${get('fontSizes.0')});
41+
--inline-message-lineHeight: var(--text-body-lineHeight-small, 1.6666);
42+
}
4243
43-
&[data-variant='critical'] {
44-
--inline-message-fgColor: ${get('colors.danger.fg')};
45-
}
44+
&[data-size='medium'] {
45+
--inline-message-fontSize: var(--text-body-size-medium, ${get('fontSizes.1')});
46+
--inline-message-lineHeight: var(--text-body-lineHeight-medium, 1.4285);
47+
}
4648
47-
&[data-variant='success'] {
48-
--inline-message-fgColor: ${get('colors.success.fg')};
49-
}
49+
&[data-variant='warning'] {
50+
--inline-message-fgColor: ${get('colors.attention.fg')};
51+
}
5052
51-
&[data-variant='unavailable'] {
52-
--inline-message-fgColor: ${get('colors.fg.muted')};
53-
}
53+
&[data-variant='critical'] {
54+
--inline-message-fgColor: ${get('colors.danger.fg')};
55+
}
56+
57+
&[data-variant='success'] {
58+
--inline-message-fgColor: ${get('colors.success.fg')};
59+
}
60+
61+
&[data-variant='unavailable'] {
62+
--inline-message-fgColor: ${get('colors.fg.muted')};
63+
}
5464
55-
& .InlineMessageIcon {
56-
min-height: calc(var(--inline-message-lineHeight) * var(--inline-message-fontSize));
65+
& .InlineMessageIcon {
66+
min-height: calc(var(--inline-message-lineHeight) * var(--inline-message-fontSize));
67+
}
68+
`,
69+
)
70+
71+
const variantToIcon = (enabled: boolean, variant: MessageVariant): React.ReactNode => {
72+
const icons = {
73+
warning: <AlertIcon className={enabled ? classes.InlineMessageIcon : 'InlineMessageIcon'} />,
74+
critical: <AlertIcon className={enabled ? classes.InlineMessageIcon : 'InlineMessageIcon'} />,
75+
success: <CheckCircleIcon className={enabled ? classes.InlineMessageIcon : 'InlineMessageIcon'} />,
76+
unavailable: <AlertIcon className={enabled ? classes.InlineMessageIcon : 'InlineMessageIcon'} />,
5777
}
58-
`
5978

60-
const variantToIcon: Record<MessageVariant, React.ReactNode> = {
61-
warning: <AlertIcon className="InlineMessageIcon" />,
62-
critical: <AlertIcon className="InlineMessageIcon" />,
63-
success: <CheckCircleIcon className="InlineMessageIcon" />,
64-
unavailable: <AlertIcon className="InlineMessageIcon" />,
79+
return icons[variant]
6580
}
6681

67-
const variantToSmallIcon: Record<MessageVariant, React.ReactNode> = {
68-
warning: <AlertFillIcon className="InlineMessageIcon" size={12} />,
69-
critical: <AlertFillIcon className="InlineMessageIcon" size={12} />,
70-
success: <CheckCircleFillIcon className="InlineMessageIcon" size={12} />,
71-
unavailable: <AlertFillIcon className="InlineMessageIcon" size={12} />,
82+
const variantToSmallIcon = (enabled: boolean, variant: MessageVariant): React.ReactNode => {
83+
const icons = {
84+
warning: <AlertFillIcon className={classes.InlineMessageIcon} size={12} />,
85+
critical: <AlertFillIcon className={classes.InlineMessageIcon} size={12} />,
86+
success: <CheckCircleFillIcon className={classes.InlineMessageIcon} size={12} />,
87+
unavailable: <AlertFillIcon className={classes.InlineMessageIcon} size={12} />,
88+
}
89+
return icons[variant]
7290
}
7391

74-
export function InlineMessage({children, size = 'medium', variant, ...rest}: InlineMessageProps) {
75-
const icon = size === 'small' ? variantToSmallIcon[variant] : variantToIcon[variant]
92+
export function InlineMessage({children, className, size = 'medium', variant, ...rest}: InlineMessageProps) {
93+
const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG)
94+
95+
const icon = size === 'small' ? variantToSmallIcon(enabled, variant) : variantToIcon(enabled, variant)
7696
return (
77-
<StyledMessage {...rest} data-size={size} data-variant={variant}>
97+
<StyledMessage
98+
className={clsx(className, enabled && classes.InlineMessage)}
99+
{...rest}
100+
data-size={size}
101+
data-variant={variant}
102+
>
78103
{icon}
79104
{children}
80105
</StyledMessage>

0 commit comments

Comments
 (0)