1
- import { type FC , type ReactNode , useMemo , forwardRef } from "react" ;
2
- import { css , useTheme , type Interpolation , type Theme } from "@emotion/react" ;
1
+ import {
2
+ type FC ,
3
+ type ReactNode ,
4
+ useMemo ,
5
+ forwardRef ,
6
+ HTMLAttributes ,
7
+ } from "react" ;
8
+ import { useTheme , type Interpolation , type Theme } from "@emotion/react" ;
3
9
import type { ThemeRole } from "theme/experimental" ;
4
10
5
11
export type PillType = ThemeRole | keyof typeof themeOverrides ;
6
12
7
- export interface PillProps {
8
- className ?: string ;
13
+ export type PillProps = HTMLAttributes < HTMLDivElement > & {
9
14
icon ?: ReactNode ;
10
- text : ReactNode ;
11
15
type ?: PillType ;
12
- title ?: string ;
13
- }
16
+ } ;
14
17
15
18
const themeOverrides = {
16
19
neutral : ( theme ) => ( {
@@ -27,11 +30,14 @@ const themeStyles = (type: ThemeRole) => (theme: Theme) => {
27
30
} ;
28
31
} ;
29
32
33
+ const PILL_HEIGHT = 24 ;
34
+ const PILL_ICON_SIZE = 14 ;
35
+ const PILL_ICON_SPACING = ( PILL_HEIGHT - PILL_ICON_SIZE ) / 2 ;
36
+
30
37
export const Pill : FC < PillProps > = forwardRef < HTMLDivElement , PillProps > (
31
38
( props , ref ) => {
32
- const { icon, text = null , type = "neutral" , ...attrs } = props ;
39
+ const { icon, type = "neutral" , children , ...divProps } = props ;
33
40
const theme = useTheme ( ) ;
34
-
35
41
const typeStyles = useMemo ( ( ) => {
36
42
if ( type in themeOverrides ) {
37
43
return themeOverrides [ type as keyof typeof themeOverrides ] ;
@@ -44,47 +50,33 @@ export const Pill: FC<PillProps> = forwardRef<HTMLDivElement, PillProps>(
44
50
ref = { ref }
45
51
css = { [
46
52
{
53
+ fontSize : 12 ,
54
+ color : theme . experimental . l1 . text ,
47
55
cursor : "default" ,
48
56
display : "inline-flex" ,
49
57
alignItems : "center" ,
58
+ whiteSpace : "nowrap" ,
59
+ fontWeight : 400 ,
50
60
borderWidth : 1 ,
51
61
borderStyle : "solid" ,
52
62
borderRadius : 99999 ,
53
- fontSize : 12 ,
54
- color : theme . experimental . l1 . text ,
55
- height : 24 ,
56
- paddingLeft : icon ? 6 : 12 ,
63
+ lineHeight : 1 ,
64
+ height : PILL_HEIGHT ,
65
+ gap : PILL_ICON_SPACING ,
57
66
paddingRight : 12 ,
58
- whiteSpace : "nowrap" ,
59
- fontWeight : 400 ,
67
+ paddingLeft : icon ? PILL_ICON_SPACING : 12 ,
68
+
69
+ "& svg" : {
70
+ width : PILL_ICON_SIZE ,
71
+ height : PILL_ICON_SIZE ,
72
+ } ,
60
73
} ,
61
74
typeStyles ,
62
75
] }
63
- role = "status"
64
- { ...attrs }
76
+ { ...divProps }
65
77
>
66
- { icon && (
67
- < div
68
- css = { css `
69
- margin-right : 4px ;
70
- width : 14px ;
71
- height : 14px ;
72
- line-height : 0 ;
73
- display : flex;
74
- align-items : center;
75
- justify-content : center;
76
-
77
- & > img ,
78
- & > svg {
79
- width : 14px ;
80
- height : 14px ;
81
- }
82
- ` }
83
- >
84
- { icon }
85
- </ div >
86
- ) }
87
- { text }
78
+ { icon }
79
+ { children }
88
80
</ div >
89
81
) ;
90
82
} ,
0 commit comments