Skip to content

Commit

Permalink
Component/tri state switch (#575)
Browse files Browse the repository at this point in the history
* [components] Tri state switch

* [components] Support indeterminate state on checkboxes #47

* [components] Changes from PR
  • Loading branch information
Kristoffer J. Sivertsen committed Feb 12, 2018
1 parent 97b9256 commit f2ae92d
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 18 deletions.
16 changes: 14 additions & 2 deletions packages/@sanity/components/src/toggles/Checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ export default class Checkbox extends React.Component {
hasFocus: false
}

componentDidMount() {
if (typeof value === 'undefined' && this._input) {
this._input.indeterminate = true
}
}

handleFocus = event => {
this.setState({hasFocus: true})
if (this.props.onFocus) {
Expand Down Expand Up @@ -44,13 +50,19 @@ export default class Checkbox extends React.Component {
const {disabled, checked, label, children, ...rest} = this.props
const {hasFocus} = this.state

let checkedClass = checked ? styles.isChecked : styles.unChecked

if (typeof checked === 'undefined') {
checkedClass = styles.indeterminate
}

return (
<label
title={label}
className={`
${styles.root}
${disabled ? styles.isDisabled : styles.isEnabled}
${checked ? styles.isChecked : styles.unChecked}
${checkedClass}
${hasFocus ? styles.hasFocus : ''}
`}
onBlur={this.handleBlur}
Expand All @@ -60,7 +72,7 @@ export default class Checkbox extends React.Component {
className={styles.input}
type="checkbox"
disabled={disabled}
checked={checked}
checked={!!checked}
ref={this.setInput}
onFocus={this.handleFocus}
/>
Expand Down
18 changes: 15 additions & 3 deletions packages/@sanity/components/src/toggles/Switch.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ export default class Switch extends React.Component {
hasFocus: false
}

componentDidMount() {
if (typeof value === 'undefined' && this._input) {
this._input.indeterminate = true
}
}

handleFocus = event => {
this.setState({hasFocus: true})
this.props.onFocus(event)
Expand All @@ -39,18 +45,24 @@ export default class Switch extends React.Component {
const {disabled, checked, label, ...rest} = this.props
const {hasFocus} = this.state

let thumbClass = checked ? styles.thumbChecked : styles.thumb

if (typeof checked === 'undefined') {
thumbClass = styles.thumbIndeterminate
}

return (
<label
className={`
${styles.root}
${typeof checked === 'undefined' ? styles.indeterminate : styles.root}
${disabled ? styles.isDisabled : styles.isEnabled}
${checked ? styles.isChecked : styles.unChecked}
${hasFocus ? styles.hasFocus : ''}
`}
onBlur={this.handleBlur}
>
<div className={styles.track} />
<div className={`${checked ? styles.thumbChecked : styles.thumb}`}>
<div className={thumbClass}>
<div className={styles.focusHelper} />
</div>

Expand All @@ -59,7 +71,7 @@ export default class Switch extends React.Component {
className={styles.input}
type="checkbox"
disabled={disabled}
checked={checked}
checked={!!checked}
ref={this.setInput}
onFocus={this.handleFocus}
/>
Expand Down
6 changes: 3 additions & 3 deletions packages/@sanity/components/src/toggles/story.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import ToggleButton from 'part:@sanity/components/toggles/button'
import Switch from 'part:@sanity/components/toggles/switch'
import Checkbox from 'part:@sanity/components/toggles/checkbox'
import SanityLogoIcon from 'part:@sanity/base/sanity-logo-icon'
import {withKnobs, boolean, text} from 'part:@sanity/storybook/addons/knobs'
import {withKnobs, boolean, text, select} from 'part:@sanity/storybook/addons/knobs'
import Sanity from 'part:@sanity/storybook/addons/sanity'

storiesOf('Toggles')
Expand All @@ -16,7 +16,7 @@ storiesOf('Toggles')
return (
<Sanity part="part:@sanity/components/toggles/switch" propTables={[Switch]}>
<Switch
checked={boolean('checked (prop)', false)}
checked={boolean('undefined', false) ? undefined : boolean('checked (prop)', false)}
label={text('label (prop)', 'This is the label')}
disabled={boolean('disabled (prop)', false)}
onChange={action('change')}
Expand All @@ -34,7 +34,7 @@ storiesOf('Toggles')
<Sanity part="part:@sanity/components/toggles/checkbox" propTables={[Checkbox]}>
<Checkbox
label={text('label (prop)', 'This is the label')}
checked={boolean('checked (prop)', false)}
checked={boolean('undefined', false) ? undefined : boolean('checked (prop)', false)}
disabled={boolean('disabled (prop)', false)}
onChange={action('onChange')}
onBlur={action('onBlur')}
Expand Down
18 changes: 10 additions & 8 deletions packages/@sanity/components/src/toggles/styles/Checkbox.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
composes: root;
}

.indeterminate {
composes: root;
}

.isDisabled {
opacity: 0.2;
}
Expand Down Expand Up @@ -120,6 +124,12 @@
/* background: $checkbox-color url("#{$checkbox-image-path}/tick.svg?embed"); */
background-color: var(--checkbox-color);
}

@nest .indeterminate & {
top: calc(var(--checkbox-button-size) * 0.29);
height: calc(var(--checkbox-button-size) * 0.2);
background-color: var(--checkbox-color);
}
}

.label {
Expand All @@ -128,12 +138,4 @@
font-size: var(--checkbox-label-font-size);
line-height: var(--checkbox-label-height);
margin: 0;

/*
fieldset[disabled] .mdl-checkbox &,
.mdl-checkbox.is-disabled & {
color: $checkbox-disabled-color;
cursor: auto;
}
*/
}
9 changes: 9 additions & 0 deletions packages/@sanity/components/src/toggles/styles/Switch.css
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
position: relative;
}

.indeterminate {
composes: root;
}

.switch {
background: var(--switch-off-track-color);
position: absolute;
Expand Down Expand Up @@ -117,6 +121,11 @@
left: calc(var(--switch-track-length) - var(--switch-thumb-size));
}

.thumbIndeterminate {
composes: thumb;
left: calc(0.5 * (var(--switch-track-length) - var(--switch-thumb-size)));
}

.focusHelper {
position: absolute;
top: 50%;
Expand Down
4 changes: 2 additions & 2 deletions packages/@sanity/form-builder/src/inputs/Boolean.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default class BooleanInput extends React.Component<Props> {
<Checkbox
{...rest}
onChange={this.handleChange}
checked={!!value}
checked={value}
ref={this.setInput}
>
{type.title}
Expand All @@ -48,7 +48,7 @@ export default class BooleanInput extends React.Component<Props> {
<Switch
{...rest}
onChange={this.handleChange}
checked={!!value}
checked={value}
label={type.title}
ref={this.setInput}
/>
Expand Down

0 comments on commit f2ae92d

Please sign in to comment.