|
1 | 1 | import {AlertFillIcon, AlertIcon, CheckCircleFillIcon, CheckCircleIcon} from '@primer/octicons-react'
|
| 2 | +import {clsx} from 'clsx' |
2 | 3 | import React from 'react'
|
3 | 4 | import styled from 'styled-components'
|
4 | 5 | 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' |
6 | 10 | type MessageVariant = 'critical' | 'success' | 'unavailable' | 'warning'
|
7 | 11 |
|
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' |
13 | 13 |
|
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' |
19 | 20 |
|
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 |
32 | 25 | }
|
33 | 26 |
|
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')}); |
38 | 38 |
|
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 | + } |
42 | 43 |
|
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 | + } |
46 | 48 |
|
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 | + } |
50 | 52 |
|
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 | + } |
54 | 64 |
|
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'} />, |
57 | 77 | }
|
58 |
| -` |
59 | 78 |
|
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] |
65 | 80 | }
|
66 | 81 |
|
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] |
72 | 90 | }
|
73 | 91 |
|
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) |
76 | 96 | 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 | + > |
78 | 103 | {icon}
|
79 | 104 | {children}
|
80 | 105 | </StyledMessage>
|
|
0 commit comments