Skip to content

Commit

Permalink
feat(toggle): add 'size' attribute
Browse files Browse the repository at this point in the history
Note: this removes 3 toggle related variables from pui-variables.scss

[Finishes #134017213]
  • Loading branch information
jeanbza committed Nov 13, 2016
1 parent 4d79c94 commit 440884c
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 58 deletions.
31 changes: 31 additions & 0 deletions library/spec/pivotal-ui-react/toggle/toggle_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,35 @@ describe('Toggle', () => {
expect('.toggle-switch').toBeChecked();
});
});

describe('size attribute', function() {
beforeEach(function() {
ReactDOM.unmountComponentAtNode(root);
});

it('renders with size=medium by default', function() {
ReactDOM.render(<Toggle id='boggle' />, root);
expect($('label').attr('class')).toContain('medium');
});

it('uses size=small class on label', function() {
ReactDOM.render(<Toggle id='boggle' size='small' />, root);
expect($('label').attr('class')).toContain('small');
});

it('uses size=medium class on label', function() {
ReactDOM.render(<Toggle id='boggle' size='medium' />, root);
expect($('label').attr('class')).toContain('medium');
});

it('uses size=large class on label', function() {
ReactDOM.render(<Toggle id='boggle' size='large' />, root);
expect($('label').attr('class')).toContain('large');
});

it('defaults to medium when size=some-random-string', function() {
ReactDOM.render(<Toggle id='boggle' size='some-random-string' />, root);
expect($('label').attr('class')).toContain('medium');
});
});
});
16 changes: 11 additions & 5 deletions library/src/pivotal-ui-react/toggle/toggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ const types = React.PropTypes;
class Toggle extends React.Component {
static propTypes = {
id: types.string,
onChange: types.func
onChange: types.func,
size: types.string
};

render() {
const {onChange, children, id, ...others} = this.props;
const {onChange, children, id, size, ...others} = this.props;
const toggleId = id || uniqueid('toggle');
const toggleSize = size && this.validSize(size) ? size : 'medium';

const props = mergeProps(others,
const inputProps = mergeProps(others,
{
className: 'toggle-switch',
id: toggleId,
Expand All @@ -25,11 +27,15 @@ class Toggle extends React.Component {

return (
<div className='form-group'>
<input {...props}/>
<label htmlFor={toggleId}>{children}</label>
<input {...inputProps}/>
<label htmlFor={toggleId} className={toggleSize}>{children}</label>
</div>
)
}

validSize(size) {
return ['small', 'medium', 'large'].includes(size)
}
}

module.exports = {Toggle};
101 changes: 52 additions & 49 deletions library/src/pivotal-ui/components/forms/forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,48 @@ This form looks and behaves mostly like a content editable field
cursor: pointer;
outline: none;
text-indent: -99999px;
width: $toggle-bg-width;
height: $toggle-bg-height;
border-radius: $toggle-bg-height;

&.small {
height: 14px;
width: 26px;
border-radius: 14px;

&:after {
height: 12px;
width: 12px;

top: 1px;
left: 1px;
}
}

&.medium {
height: 18px;
width: 33px;
border-radius: 18px;

&:after {
height: 14px;
width: 14px;

top: 2px;
left: 2px;
}
}

&.large {
height: 24px;
width: 43px;
border-radius: 24px;

&:after {
height: 18px;
width: 18px;

top: 3px;
left: 3px;
}
}

&:after {
position: absolute;
Expand All @@ -298,63 +337,27 @@ This form looks and behaves mostly like a content editable field
background-color: $neutral-11;
transition: margin 0.4s, background 0.4s;
content: "";
width: $toggle-diameter;
height: $toggle-diameter;
border-radius: $toggle-diameter / 2;
border-radius: 50%;
}
}

&:checked + label {
background-color: $blue-2;
}

&[disabled] + label {
@include opacity(.5);
&:checked + label.small:after {
margin-left: 12px;
}

&:checked + label:after {
margin-left: $toggle-bg-width - $toggle-diameter - 2;
&:checked + label.medium:after {
margin-left: 15px;
}

&.toggle-switch-lg {
+ label {
width: 80px;
height: 40px;
border-radius: 40px;

&:after {
top: 5px;
left: 5px;
width: 30px;
height: 30px;
border-radius: 15px;
}
}
&:checked + label.large:after {
margin-left: 19px;
}

&:checked + label:after {
margin-left: 40px;
}
&[disabled] + label {
@include opacity(.5);
}
}

/*pending
---
title: Focus Inputs
name: form_focus_input
categories:
- Forms
- All
---
Add the focus-input directive to an element that should be focused if the focus-input expression changes such that it evalutes as true.
```html_example
<a ng-click="focus_input1=true; focus_input2=false;">Focus input 1</a>
<br/>
<a ng-click="focus_input2=true; focus_input1=false;">Focus input 2</a>
<br/>
<input focus-input="focus_input1"></input>
<input focus-input="focus_input2"></input>
```
*/

4 changes: 0 additions & 4 deletions library/src/pivotal-ui/components/pui-variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -504,10 +504,6 @@ $input-group-addon-bg: $gray-lighter !default;
$input-group-addon-border-color: $input-border !default;
$cursor-disabled: not-allowed !default;

$toggle-bg-width: 22px;
$toggle-bg-height: 12px;
$toggle-diameter: 10px;

// Dropdowns
// -------------------------

Expand Down
11 changes: 11 additions & 0 deletions styleguide/docs/react/toggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,15 @@ Note that you must handle the addition and removal of the `checked` property you
<Toggle checked onChange={() => console.log('I should handle check changes!')}/>
```
Toggle has a `size` attribute that takes three options; small, medium (default), and large.
```react_example
<div>
<Toggle size='small'/>
<Toggle size='medium'/>
<Toggle/>
<Toggle size='large'/>
</div>
```
*/

0 comments on commit 440884c

Please sign in to comment.