@@ -7,6 +7,7 @@ import { createDisabledTextStyles, createHatchedBackground } from '../common';
7
7
import { padding , fontSizes } from '../common/system' ;
8
8
import useControlledOrUncontrolled from '../common/hooks/useControlledOrUncontrolled' ;
9
9
import Cutout from '../Cutout/Cutout' ;
10
+ import { StyledListItem } from '../ListItem/ListItem' ;
10
11
11
12
const checkboxSize = 20 ;
12
13
@@ -22,6 +23,11 @@ const StyledLabel = styled.label`
22
23
user-select: none;
23
24
font-size: ${ fontSizes . md } ;
24
25
${ props => props . isDisabled && createDisabledTextStyles ( ) }
26
+
27
+ ${ StyledListItem } & {
28
+ margin: 0;
29
+ height: 100%;
30
+ }
25
31
` ;
26
32
27
33
const StyledInput = styled . input `
@@ -63,6 +69,21 @@ const StyledFlatCheckbox = styled.div`
63
69
background: ${ ( { theme, isDisabled } ) =>
64
70
isDisabled ? theme . flatLight : theme . canvas } ;
65
71
` ;
72
+
73
+ const StyledMenuCheckbox = styled . div `
74
+ position: relative;
75
+ box-sizing: border-box;
76
+ display: inline-block;
77
+ background: ${ ( { theme, isDisabled } ) =>
78
+ isDisabled ? theme . flatLight : theme . canvas } ;
79
+ ${ sharedCheckboxStyles }
80
+ width: ${ checkboxSize - 4 } px;
81
+ height: ${ checkboxSize - 4 } px;
82
+ background: none;
83
+ border: none;
84
+ outline: none;
85
+ ` ;
86
+
66
87
const CheckmarkIcon = styled . span . attrs ( ( ) => ( {
67
88
'data-testid' : 'checkmarkIcon'
68
89
} ) ) `
@@ -84,15 +105,46 @@ const CheckmarkIcon = styled.span.attrs(() => ({
84
105
isDisabled ? theme . checkmarkDisabled : theme . checkmark } ;
85
106
border-width: 0 3px 3px 0;
86
107
transform: translate(-50%, -50%) rotate(45deg);
108
+
109
+ ${ ( { variant, theme, isDisabled } ) =>
110
+ variant === 'menu'
111
+ ? css `
112
+ border-color: ${ isDisabled ? theme . textDisabled : theme . text } ;
113
+ filter: drop-shadow(
114
+ 1px 1px 0px
115
+ ${ isDisabled ? theme . textDisabledShadow : 'transparent' }
116
+ );
117
+ `
118
+ : css `
119
+ border-color: ${ isDisabled
120
+ ? theme . checkmarkDisabled
121
+ : theme . checkmark } ;
122
+ ` }
123
+ ${ StyledListItem } :hover & {
124
+ ${ ( { theme, isDisabled, variant } ) =>
125
+ ! isDisabled &&
126
+ variant === 'menu' &&
127
+ css `
128
+ border-color: ${ theme . textInvert } ;
129
+ ` } ;
87
130
}
88
131
` ;
89
132
const IndeterminateIcon = styled . span . attrs ( ( ) => ( {
90
133
'data-testid' : 'indeterminateIcon'
91
134
} ) ) `
92
135
display: inline-block;
93
136
position: relative;
94
- width: 100%;
95
- height: 100%;
137
+
138
+ ${ ( { variant } ) =>
139
+ variant === 'menu'
140
+ ? css `
141
+ height: calc(100% - 4px);
142
+ width: calc(100% - 4px);
143
+ `
144
+ : css `
145
+ width: 100%;
146
+ height: 100%;
147
+ ` }
96
148
&:after {
97
149
content: '';
98
150
display: block;
@@ -104,12 +156,33 @@ const IndeterminateIcon = styled.span.attrs(() => ({
104
156
createHatchedBackground ( {
105
157
mainColor : isDisabled ? theme . checkmarkDisabled : theme . checkmark
106
158
} ) }
107
- background-position: -1px -1px, 1px 1px;
108
- outline: 1px solid
109
- ${ ( { theme, isDisabled } ) => ( isDisabled ? theme . material : theme . canvas ) } ;
110
- outline-offset: -1px;
159
+ background-position: 0px 0px, 2px 2px;
160
+
161
+ ${ ( { variant, isDisabled, theme } ) =>
162
+ variant === 'menu' &&
163
+ css `
164
+ ${ StyledListItem } :hover & {
165
+ ${ createHatchedBackground ( {
166
+ mainColor : theme . textInvert
167
+ } ) }
168
+ }
169
+ filter: drop-shadow(
170
+ 1px 1px 0px ${ isDisabled ? theme . textDisabledShadow : 'transparent' }
171
+ );
172
+ ` } ;
111
173
}
112
174
` ;
175
+ const LabelText = styled . span `
176
+ display: inline-block;
177
+ line-height: 1;
178
+ ` ;
179
+
180
+ const CheckboxComponents = {
181
+ flat : StyledFlatCheckbox ,
182
+ default : StyledCheckbox ,
183
+ menu : StyledMenuCheckbox
184
+ } ;
185
+
113
186
const Checkbox = React . forwardRef ( function Checkbox ( props , ref ) {
114
187
const {
115
188
onChange,
@@ -134,8 +207,8 @@ const Checkbox = React.forwardRef(function Checkbox(props, ref) {
134
207
setState ( newState ) ;
135
208
if ( onChange ) onChange ( e ) ;
136
209
} ;
137
- const CheckboxComponent =
138
- variant === 'flat' ? StyledFlatCheckbox : StyledCheckbox ;
210
+
211
+ const CheckboxComponent = CheckboxComponents [ variant ] ;
139
212
140
213
let Icon = null ;
141
214
if ( indeterminate ) {
@@ -151,9 +224,9 @@ const Checkbox = React.forwardRef(function Checkbox(props, ref) {
151
224
isDisabled = { disabled }
152
225
role = 'presentation'
153
226
>
154
- { Icon && < Icon isDisabled = { disabled } /> }
227
+ { Icon && < Icon isDisabled = { disabled } variant = { variant } /> }
155
228
</ CheckboxComponent >
156
- { label && < span > { label } </ span > }
229
+ { label && < LabelText > { label } </ LabelText > }
157
230
< StyledInput
158
231
disabled = { disabled }
159
232
onChange = { disabled ? undefined : handleChange }
@@ -195,7 +268,7 @@ Checkbox.propTypes = {
195
268
label : propTypes . oneOfType ( [ propTypes . string , propTypes . number ] ) ,
196
269
checked : propTypes . bool ,
197
270
disabled : propTypes . bool ,
198
- variant : propTypes . oneOf ( [ 'default' , 'flat' ] ) ,
271
+ variant : propTypes . oneOf ( [ 'default' , 'flat' , 'menu' ] ) ,
199
272
style : propTypes . shape ( [ propTypes . string , propTypes . number ] ) ,
200
273
defaultChecked : propTypes . bool ,
201
274
indeterminate : propTypes . bool ,
0 commit comments