@@ -7,6 +7,7 @@ import { createDisabledTextStyles, createHatchedBackground } from '../common';
77import { padding , fontSizes } from '../common/system' ;
88import useControlledOrUncontrolled from '../common/hooks/useControlledOrUncontrolled' ;
99import Cutout from '../Cutout/Cutout' ;
10+ import { StyledListItem } from '../ListItem/ListItem' ;
1011
1112const checkboxSize = 20 ;
1213
@@ -22,6 +23,11 @@ const StyledLabel = styled.label`
2223 user-select: none;
2324 font-size: ${ fontSizes . md } ;
2425 ${ props => props . isDisabled && createDisabledTextStyles ( ) }
26+
27+ ${ StyledListItem } & {
28+ margin: 0;
29+ height: 100%;
30+ }
2531` ;
2632
2733const StyledInput = styled . input `
@@ -63,6 +69,21 @@ const StyledFlatCheckbox = styled.div`
6369 background: ${ ( { theme, isDisabled } ) =>
6470 isDisabled ? theme . flatLight : theme . canvas } ;
6571` ;
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+
6687const CheckmarkIcon = styled . span . attrs ( ( ) => ( {
6788 'data-testid' : 'checkmarkIcon'
6889} ) ) `
@@ -84,15 +105,46 @@ const CheckmarkIcon = styled.span.attrs(() => ({
84105 isDisabled ? theme . checkmarkDisabled : theme . checkmark } ;
85106 border-width: 0 3px 3px 0;
86107 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+ ` } ;
87130 }
88131` ;
89132const IndeterminateIcon = styled . span . attrs ( ( ) => ( {
90133 'data-testid' : 'indeterminateIcon'
91134} ) ) `
92135 display: inline-block;
93136 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+ ` }
96148 &:after {
97149 content: '';
98150 display: block;
@@ -104,12 +156,33 @@ const IndeterminateIcon = styled.span.attrs(() => ({
104156 createHatchedBackground ( {
105157 mainColor : isDisabled ? theme . checkmarkDisabled : theme . checkmark
106158 } ) }
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+ ` } ;
111173 }
112174` ;
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+
113186const Checkbox = React . forwardRef ( function Checkbox ( props , ref ) {
114187 const {
115188 onChange,
@@ -134,8 +207,8 @@ const Checkbox = React.forwardRef(function Checkbox(props, ref) {
134207 setState ( newState ) ;
135208 if ( onChange ) onChange ( e ) ;
136209 } ;
137- const CheckboxComponent =
138- variant === 'flat' ? StyledFlatCheckbox : StyledCheckbox ;
210+
211+ const CheckboxComponent = CheckboxComponents [ variant ] ;
139212
140213 let Icon = null ;
141214 if ( indeterminate ) {
@@ -151,9 +224,9 @@ const Checkbox = React.forwardRef(function Checkbox(props, ref) {
151224 isDisabled = { disabled }
152225 role = 'presentation'
153226 >
154- { Icon && < Icon isDisabled = { disabled } /> }
227+ { Icon && < Icon isDisabled = { disabled } variant = { variant } /> }
155228 </ CheckboxComponent >
156- { label && < span > { label } </ span > }
229+ { label && < LabelText > { label } </ LabelText > }
157230 < StyledInput
158231 disabled = { disabled }
159232 onChange = { disabled ? undefined : handleChange }
@@ -195,7 +268,7 @@ Checkbox.propTypes = {
195268 label : propTypes . oneOfType ( [ propTypes . string , propTypes . number ] ) ,
196269 checked : propTypes . bool ,
197270 disabled : propTypes . bool ,
198- variant : propTypes . oneOf ( [ 'default' , 'flat' ] ) ,
271+ variant : propTypes . oneOf ( [ 'default' , 'flat' , 'menu' ] ) ,
199272 style : propTypes . shape ( [ propTypes . string , propTypes . number ] ) ,
200273 defaultChecked : propTypes . bool ,
201274 indeterminate : propTypes . bool ,
0 commit comments