Skip to content

Commit

Permalink
Merge 1ea68cf into d25d58a
Browse files Browse the repository at this point in the history
  • Loading branch information
randall-krauskopf authored Nov 4, 2024
2 parents d25d58a + 1ea68cf commit 34bffde
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 55 deletions.
5 changes: 5 additions & 0 deletions .changeset/silent-cherries-behave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/react": minor
---

Migrate 'InlineMessage' component to use CSS modules
4 changes: 4 additions & 0 deletions e2e/components/InlineMessage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ const stories = [
title: 'Multiline',
id: 'experimental-components-inlinemessage-features--multiline',
},
{
title: 'Dev Default',
id: 'experimental-components-inlinemessage-dev--dev-story',
},
]

const scenarios = matrix({
Expand Down
18 changes: 18 additions & 0 deletions packages/react/src/InlineMessage/InlineMessage.dev.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type {Meta} from '@storybook/react'
import React from 'react'
import {InlineMessage} from '.'

const meta = {
title: 'Experimental/Components/InlineMessage/Dev',
component: InlineMessage,
} satisfies Meta<typeof InlineMessage>

export default meta

export const DevDefault = () => {
return (
<InlineMessage variant="unavailable" sx={{border: '1px solid red'}}>
An example inline message
</InlineMessage>
)
}
42 changes: 42 additions & 0 deletions packages/react/src/InlineMessage/InlineMessage.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.InlineMessage {
display: grid;
/* stylelint-disable-next-line primer/typography */
font-size: var(--inline-message-fontSize);
/* stylelint-disable-next-line primer/typography */
line-height: var(--inline-message-lineHeight);
/* stylelint-disable-next-line primer/colors */
color: var(--inline-message-fgColor);
column-gap: 0.5rem;
grid-template-columns: auto 1fr;
align-items: start;

&[data-size='small'] {
--inline-message-fontSize: var(--text-body-size-small);
--inline-message-lineHeight: var(--text-body-lineHeight-small, 1.6666);
}

&[data-size='medium'] {
--inline-message-fontSize: var(--text-body-size-medium);
--inline-message-lineHeight: var(--text-body-lineHeight-medium, 1.4285);
}

&[data-variant='warning'] {
--inline-message-fgColor: var(--fgColor-attention);
}

&[data-variant='critical'] {
--inline-message-fgColor: var(--fgColor-danger);
}

&[data-variant='success'] {
--inline-message-fgColor: var(--fgColor-success);
}

&[data-variant='unavailable'] {
--inline-message-fgColor: var(--fgColor-muted);
}
}

.InlineMessageIcon {
min-height: calc(var(--inline-message-lineHeight) * var(--inline-message-fontSize));
}
135 changes: 80 additions & 55 deletions packages/react/src/InlineMessage/InlineMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,80 +1,105 @@
import {AlertFillIcon, AlertIcon, CheckCircleFillIcon, CheckCircleIcon} from '@primer/octicons-react'
import {clsx} from 'clsx'
import React from 'react'
import styled from 'styled-components'
import {get} from '../constants'

import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent'
import {useFeatureFlag} from '../FeatureFlags'
import classes from './InlineMessage.module.css'
import type {SxProp} from '../sx'
type MessageVariant = 'critical' | 'success' | 'unavailable' | 'warning'

export type InlineMessageProps = React.ComponentPropsWithoutRef<'div'> & {
/**
* Specify the size of the InlineMessage
*/
size?: 'small' | 'medium'
const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_team'

/**
* Specify the type of the InlineMessage
*/
variant: MessageVariant
}
export type InlineMessageProps = React.ComponentPropsWithoutRef<'div'> &
SxProp & {
/**
* Specify the size of the InlineMessage
*/
size?: 'small' | 'medium'

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

&[data-size='medium'] {
--inline-message-fontSize: var(--text-body-size-medium, ${get('fontSizes.1')});
--inline-message-lineHeight: var(--text-body-lineHeight-medium, 1.4285);
}
const StyledMessage = toggleStyledComponent(
CSS_MODULES_FEATURE_FLAG,
'div',
styled.div`
display: grid;
column-gap: 0.5rem;
grid-template-columns: auto 1fr;
align-items: start;
color: var(--inline-message-fgColor, ${get('colors.fg.muted')});
line-height: var(--inline-message-lineHeight);
font-size: var(--inline-message-fontSize, ${get('fontSizes.1')});
&[data-variant='warning'] {
--inline-message-fgColor: ${get('colors.attention.fg')};
}
&[data-size='small'] {
--inline-message-fontSize: var(--text-body-size-small, ${get('fontSizes.0')});
--inline-message-lineHeight: var(--text-body-lineHeight-small, 1.6666);
}
&[data-variant='critical'] {
--inline-message-fgColor: ${get('colors.danger.fg')};
}
&[data-size='medium'] {
--inline-message-fontSize: var(--text-body-size-medium, ${get('fontSizes.1')});
--inline-message-lineHeight: var(--text-body-lineHeight-medium, 1.4285);
}
&[data-variant='success'] {
--inline-message-fgColor: ${get('colors.success.fg')};
}
&[data-variant='warning'] {
--inline-message-fgColor: ${get('colors.attention.fg')};
}
&[data-variant='unavailable'] {
--inline-message-fgColor: ${get('colors.fg.muted')};
}
&[data-variant='critical'] {
--inline-message-fgColor: ${get('colors.danger.fg')};
}
&[data-variant='success'] {
--inline-message-fgColor: ${get('colors.success.fg')};
}
&[data-variant='unavailable'] {
--inline-message-fgColor: ${get('colors.fg.muted')};
}
& .InlineMessageIcon {
min-height: calc(var(--inline-message-lineHeight) * var(--inline-message-fontSize));
& .InlineMessageIcon {
min-height: calc(var(--inline-message-lineHeight) * var(--inline-message-fontSize));
}
`,
)

const variantToIcon = (enabled: boolean, variant: MessageVariant): React.ReactNode => {
const icons = {
warning: <AlertIcon className={enabled ? classes.InlineMessageIcon : 'InlineMessageIcon'} />,
critical: <AlertIcon className={enabled ? classes.InlineMessageIcon : 'InlineMessageIcon'} />,
success: <CheckCircleIcon className={enabled ? classes.InlineMessageIcon : 'InlineMessageIcon'} />,
unavailable: <AlertIcon className={enabled ? classes.InlineMessageIcon : 'InlineMessageIcon'} />,
}
`

const variantToIcon: Record<MessageVariant, React.ReactNode> = {
warning: <AlertIcon className="InlineMessageIcon" />,
critical: <AlertIcon className="InlineMessageIcon" />,
success: <CheckCircleIcon className="InlineMessageIcon" />,
unavailable: <AlertIcon className="InlineMessageIcon" />,
return icons[variant]
}

const variantToSmallIcon: Record<MessageVariant, React.ReactNode> = {
warning: <AlertFillIcon className="InlineMessageIcon" size={12} />,
critical: <AlertFillIcon className="InlineMessageIcon" size={12} />,
success: <CheckCircleFillIcon className="InlineMessageIcon" size={12} />,
unavailable: <AlertFillIcon className="InlineMessageIcon" size={12} />,
const variantToSmallIcon = (enabled: boolean, variant: MessageVariant): React.ReactNode => {
const icons = {
warning: <AlertFillIcon className={classes.InlineMessageIcon} size={12} />,
critical: <AlertFillIcon className={classes.InlineMessageIcon} size={12} />,
success: <CheckCircleFillIcon className={classes.InlineMessageIcon} size={12} />,
unavailable: <AlertFillIcon className={classes.InlineMessageIcon} size={12} />,
}
return icons[variant]
}

export function InlineMessage({children, size = 'medium', variant, ...rest}: InlineMessageProps) {
const icon = size === 'small' ? variantToSmallIcon[variant] : variantToIcon[variant]
export function InlineMessage({children, className, size = 'medium', variant, ...rest}: InlineMessageProps) {
const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG)

const icon = size === 'small' ? variantToSmallIcon(enabled, variant) : variantToIcon(enabled, variant)
return (
<StyledMessage {...rest} data-size={size} data-variant={variant}>
<StyledMessage
className={clsx(className, enabled && classes.InlineMessage)}
{...rest}
data-size={size}
data-variant={variant}
>
{icon}
{children}
</StyledMessage>
Expand Down

0 comments on commit 34bffde

Please sign in to comment.