@@ -7,15 +7,13 @@ import {
77 SkipIcon ,
88 IssueDraftIcon ,
99 IssueOpenedIcon ,
10- QuestionIcon ,
1110 GitMergeQueueIcon ,
1211 AlertIcon ,
1312} from '@primer/octicons-react'
14- import styled from 'styled-components '
15- import { variant } from 'styled-system '
16- import { get } from '../constants '
13+ import type React from 'react '
14+ import { forwardRef } from 'react '
15+ import { clsx } from 'clsx '
1716import Octicon from '../Octicon'
18- import type { ComponentProps } from '../utils/types'
1917import classes from './StateLabel.module.css'
2018
2119const octiconMap = {
@@ -48,126 +46,34 @@ const labelMap: Record<keyof typeof octiconMap, 'Issue' | 'Issue, not planned' |
4846 closed : '' ,
4947}
5048
51- const colorVariants = variant ( {
52- prop : 'status' ,
53- variants : {
54- issueClosed : {
55- backgroundColor : 'done.emphasis' ,
56- color : 'fg.onEmphasis' ,
57- boxShadow : 'var(--boxShadow-thin, inset 0 0 0 1px) var(--borderColor-done-emphasis, transparent)' ,
58- } ,
59- issueClosedNotPlanned : {
60- backgroundColor : 'neutral.emphasis' ,
61- color : 'fg.onEmphasis' ,
62- boxShadow : 'var(--boxShadow-thin, inset 0 0 0 1px) var(--borderColor-neutral-emphasis, transparent)' ,
63- } ,
64- pullClosed : {
65- backgroundColor : 'closed.emphasis' ,
66- color : 'fg.onEmphasis' ,
67- boxShadow : 'var(--boxShadow-thin, inset 0 0 0 1px) var(--borderColor-closed-emphasis, transparent)' ,
68- } ,
69- pullMerged : {
70- backgroundColor : 'done.emphasis' ,
71- color : 'fg.onEmphasis' ,
72- boxShadow : 'var(--boxShadow-thin, inset 0 0 0 1px) var(--borderColor-done-emphasis, transparent)' ,
73- } ,
74- pullQueued : {
75- backgroundColor : 'attention.emphasis' ,
76- color : 'fg.onEmphasis' ,
77- boxShadow : 'var(--boxShadow-thin, inset 0 0 0 1px) var(--borderColor-attention-emphasis, transparent)' ,
78- } ,
79- issueOpened : {
80- backgroundColor : 'open.emphasis' ,
81- color : 'fg.onEmphasis' ,
82- boxShadow : 'var(--boxShadow-thin, inset 0 0 0 1px) var(--borderColor-open-emphasis, transparent)' ,
83- } ,
84- pullOpened : {
85- backgroundColor : 'open.emphasis' ,
86- color : 'fg.onEmphasis' ,
87- boxShadow : 'var(--boxShadow-thin, inset 0 0 0 1px) var(--borderColor-open-emphasis, transparent)' ,
88- } ,
89- draft : {
90- backgroundColor : 'neutral.emphasis' ,
91- color : 'fg.onEmphasis' ,
92- boxShadow : 'var(--boxShadow-thin, inset 0 0 0 1px) var(--borderColor-neutral-emphasis, transparent)' ,
93- } ,
94- issueDraft : {
95- backgroundColor : 'neutral.emphasis' ,
96- color : 'fg.onEmphasis' ,
97- boxShadow : 'var(--boxShadow-thin, inset 0 0 0 1px) var(--borderColor-neutral-emphasis, transparent)' ,
98- } ,
99- unavailable : {
100- backgroundColor : 'neutral.emphasis' ,
101- color : 'fg.onEmphasis' ,
102- boxShadow : 'var(--boxShadow-thin, inset 0 0 0 1px) var(--borderColor-neutral-emphasis, transparent)' ,
103- } ,
104- open : {
105- backgroundColor : 'open.emphasis' ,
106- color : 'fg.onEmphasis' ,
107- boxShadow : 'var(--boxShadow-thin, inset 0 0 0 1px) var(--borderColor-open-emphasis, transparent)' ,
108- } ,
109- closed : {
110- backgroundColor : 'done.emphasis' ,
111- color : 'fg.onEmphasis' ,
112- boxShadow : 'var(--boxShadow-thin, inset 0 0 0 1px) var(--borderColor-done-emphasis, transparent)' ,
113- } ,
114- } ,
115- } )
116-
117- const sizeVariants = variant ( {
118- prop : 'variant' ,
119- variants : {
120- small : {
121- paddingX : 2 ,
122- paddingY : 1 ,
123- fontSize : 0 ,
124- } ,
125- normal : {
126- paddingX : '12px' ,
127- paddingY : 2 ,
128- fontSize : 1 ,
129- } ,
130- } ,
131- } )
132-
133- type StyledStateLabelBaseProps = {
49+ export type StateLabelProps = React . HTMLAttributes < HTMLSpanElement > & {
13450 variant ?: 'small' | 'normal'
13551 status : keyof typeof octiconMap
13652}
13753
138- const StateLabelBase = styled . span < StyledStateLabelBaseProps > `
139- display: inline-flex;
140- align-items: center;
141- font-weight: ${ get ( 'fontWeights.bold' ) } ;
142- line-height: 16px;
143- color: ${ get ( 'colors.canvas.default' ) } ;
144- text-align: center;
145- border-radius: ${ get ( 'radii.3' ) } ;
146- ${ colorVariants } ;
147- ${ sizeVariants } ;
148- `
54+ const StateLabel = forwardRef < HTMLSpanElement , StateLabelProps > (
55+ ( { children, status, variant : variantProp = 'normal' , className, ...rest } , ref ) => {
56+ const octiconProps = variantProp === 'small' ? { width : '1em' } : { }
57+ // Open and closed statuses, we don't want to show an icon
58+ const noIconStatus = status === 'open' || status === 'closed'
14959
150- export type StateLabelProps = ComponentProps < typeof StateLabelBase >
60+ return (
61+ < span
62+ { ...rest }
63+ ref = { ref }
64+ className = { clsx ( classes . StateLabel , className ) }
65+ data-variant = { variantProp }
66+ data-status = { status }
67+ >
68+ { ! noIconStatus && (
69+ < Octicon { ...octiconProps } icon = { octiconMap [ status ] } aria-label = { labelMap [ status ] } className = { classes . Icon } />
70+ ) }
71+ { children }
72+ </ span >
73+ )
74+ } ,
75+ )
15176
152- function StateLabel ( { children, status, variant : variantProp = 'normal' , ...rest } : StateLabelProps ) {
153- const octiconProps = variantProp === 'small' ? { width : '1em' } : { }
154- // Open and closed statuses, we don't want to show an icon
155- const noIconStatus = status === 'open' || status === 'closed'
156- return (
157- < StateLabelBase { ...rest } variant = { variantProp } status = { status } >
158- { /* eslint-disable-next-line @typescript-eslint/no-unnecessary-condition */ }
159- { status && ! noIconStatus && (
160- < Octicon
161- { ...octiconProps }
162- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
163- icon = { octiconMap [ status ] || QuestionIcon }
164- aria-label = { labelMap [ status ] }
165- className = { classes . Icon }
166- />
167- ) }
168- { children }
169- </ StateLabelBase >
170- )
171- }
77+ StateLabel . displayName = 'StateLabel'
17278
17379export default StateLabel
0 commit comments