1
1
import React from 'react'
2
- import styled from 'styled-components'
3
2
import { clsx } from 'clsx'
4
3
import type { StyledWrapperProps } from '../internal/components/TextInputWrapper'
5
4
import TextInputWrapper from '../internal/components/TextInputWrapper'
6
- import { toggleStyledComponent } from '../internal/utils/toggleStyledComponent'
7
- import { useFeatureFlag } from '../FeatureFlags'
8
5
import type { ForwardRefComponent as PolymorphicForwardRefComponent } from '../utils/polymorphic'
9
6
10
7
import classes from './Select.module.css'
11
8
12
9
export type SelectProps = Omit <
13
- Omit < React . ComponentPropsWithoutRef < 'select' > , 'size' > & Omit < StyledWrapperProps , 'variant' > ,
10
+ Omit < React . ComponentProps < 'select' > , 'size' > & Omit < StyledWrapperProps , 'variant' > ,
14
11
'multiple' | 'hasLeadingVisual' | 'hasTrailingVisual' | 'as'
15
12
> & {
16
13
placeholder ?: string
17
14
}
18
15
19
- const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_ga'
20
-
21
- const arrowRightOffset = '4px'
22
-
23
- const StyledSelect = toggleStyledComponent (
24
- CSS_MODULES_FEATURE_FLAG ,
25
- 'select' ,
26
- styled . select `
27
- appearance: none;
28
- border-radius: inherit;
29
- border: 0;
30
- color: currentColor;
31
- font-size: inherit;
32
- outline: none;
33
- width: 100%;
34
-
35
- /* Firefox hacks: */
36
- /* 1. Makes Firefox's native dropdown menu's background match the theme.
37
-
38
- background-color should be 'transparent', but Firefox uses the background-color on
39
- <select> to determine the background color used for the dropdown menu.
40
-
41
- 2. Adds 1px margins to the <select> so the background color doesn't hide the focus outline created with an inset box-shadow.
42
- */
43
- background-color: inherit;
44
- margin-top: 1px;
45
- margin-left: 1px;
46
- margin-bottom: 1px;
47
-
48
- /* 2. Prevents visible overlap of partially transparent background colors.
49
-
50
- 'colors.input.disabledBg' happens to be partially transparent in light mode, so we use a
51
- transparent background-color on a disabled <select>. */
52
- &:disabled {
53
- background-color: transparent;
54
- }
55
-
56
- /* 3. Maintain dark bg color in Firefox on Windows high-contrast mode
57
-
58
- Firefox makes the <select>'s background color white when setting 'background-color: transparent;' */
59
- @media screen and (forced-colors: active) {
60
- &:disabled {
61
- background-color: -moz-combobox;
62
- }
63
- }
64
- ` ,
65
- )
66
-
67
16
const ArrowIndicatorSVG : React . FC < React . PropsWithChildren < { className ?: string } > > = ( { className} ) => {
68
17
return (
69
18
< svg
@@ -79,83 +28,33 @@ const ArrowIndicatorSVG: React.FC<React.PropsWithChildren<{className?: string}>>
79
28
)
80
29
}
81
30
82
- const StyledArrowIndicatorSVG = styled ( ArrowIndicatorSVG ) `
83
- pointer-events: none;
84
- position: absolute;
85
- right: ${ arrowRightOffset } ;
86
- top: 50%;
87
- transform: translateY(-50%);
88
- `
89
-
90
31
const ArrowIndicator : React . FC < { className ?: string } > = ( { className} ) => {
91
- const enabled = useFeatureFlag ( CSS_MODULES_FEATURE_FLAG )
92
- if ( enabled ) {
93
- return < ArrowIndicatorSVG className = { clsx ( classes . ArrowIndicator , className ) } />
94
- }
95
-
96
- return < StyledArrowIndicatorSVG />
32
+ return < ArrowIndicatorSVG className = { clsx ( classes . ArrowIndicator , className ) } />
97
33
}
98
34
99
35
const Select = React . forwardRef < HTMLSelectElement , SelectProps > (
100
- ( { block, children, contrast, disabled, placeholder, size, required, validationStatus, ...rest } : SelectProps , ref ) => {
101
- const enabled = useFeatureFlag ( CSS_MODULES_FEATURE_FLAG )
102
- if ( enabled ) {
103
- return (
104
- < TextInputWrapper
105
- block = { block }
106
- contrast = { contrast }
107
- disabled = { disabled }
108
- size = { size }
109
- validationStatus = { validationStatus }
110
- className = { classes . TextInputWrapper }
111
- sx = { rest . sx }
112
- >
113
- < StyledSelect
114
- ref = { ref }
115
- required = { required }
116
- disabled = { disabled }
117
- aria-invalid = { validationStatus === 'error' ? 'true' : 'false' }
118
- data-hasplaceholder = { Boolean ( placeholder ) }
119
- defaultValue = { placeholder ?? undefined }
120
- className = { clsx ( classes . Select , disabled && classes . Disabled ) }
121
- { ...rest }
122
- >
123
- { placeholder && (
124
- < option value = "" disabled = { required } hidden = { required } >
125
- { placeholder }
126
- </ option >
127
- ) }
128
- { children }
129
- </ StyledSelect >
130
- < ArrowIndicator className = { classes . ArrowIndicator } />
131
- </ TextInputWrapper >
132
- )
133
- }
134
-
36
+ (
37
+ { block, children, contrast, disabled, placeholder, size, required, validationStatus, sx, ...rest } : SelectProps ,
38
+ ref ,
39
+ ) => {
135
40
return (
136
41
< TextInputWrapper
137
- sx = { {
138
- overflow : 'hidden' ,
139
- position : 'relative' ,
140
- '@media screen and (forced-colors: active)' : {
141
- svg : {
142
- fill : disabled ? 'GrayText' : 'FieldText' ,
143
- } ,
144
- } ,
145
- } }
146
42
block = { block }
147
43
contrast = { contrast }
148
44
disabled = { disabled }
149
45
size = { size }
150
46
validationStatus = { validationStatus }
47
+ className = { classes . TextInputWrapper }
48
+ sx = { sx }
151
49
>
152
- < StyledSelect
50
+ < select
153
51
ref = { ref }
154
52
required = { required }
155
53
disabled = { disabled }
156
54
aria-invalid = { validationStatus === 'error' ? 'true' : 'false' }
157
55
data-hasplaceholder = { Boolean ( placeholder ) }
158
56
defaultValue = { placeholder ?? undefined }
57
+ className = { clsx ( classes . Select , disabled && classes . Disabled ) }
159
58
{ ...rest }
160
59
>
161
60
{ placeholder && (
@@ -164,8 +63,8 @@ const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
164
63
</ option >
165
64
) }
166
65
{ children }
167
- </ StyledSelect >
168
- < ArrowIndicator />
66
+ </ select >
67
+ < ArrowIndicator className = { classes . ArrowIndicator } />
169
68
</ TextInputWrapper >
170
69
)
171
70
} ,
0 commit comments