Skip to content

Commit

Permalink
feat(InlineMessage): Convert InlineMessage component to CSS Modules…
Browse files Browse the repository at this point in the history
… 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 <randall-krauskopf@users.noreply.github.com>
  • Loading branch information
randall-krauskopf and randall-krauskopf authored Nov 5, 2024
1 parent bc8be36 commit 209c9b0
Show file tree
Hide file tree
Showing 4 changed files with 128 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
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const meta = {

export default meta

// Previous Styled version of the component didn't accept an sx prop so no need to test if that works.
export const DevDefault = () => {
return <InlineMessage variant="unavailable">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 209c9b0

Please sign in to comment.