-
Notifications
You must be signed in to change notification settings - Fork 376
feat(component): introduce the pf4 switch component #761
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
16 changes: 16 additions & 0 deletions
16
packages/patternfly-4/react-core/src/components/Switch/Switch.d.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import { HTMLProps, FormEvent, ReactNode } from 'react'; | ||
| import { Omit } from '../../typeUtils'; | ||
|
|
||
| export interface SwitchProps extends Omit<HTMLProps<HTMLInputElement>, 'type' | 'onChange' | 'disabled' | 'label'> { | ||
| isDisabled?: boolean; | ||
| isChecked?: boolean; | ||
| onChange?(checked: boolean, event: FormEvent<HTMLInputElement>): void; | ||
| id?: string; | ||
| 'aria-label': string; | ||
| label?: string; | ||
| className?: string; | ||
| } | ||
|
|
||
| declare const Switch: React.SFC<SwitchProps>; | ||
|
|
||
| export default Switch; | ||
18 changes: 18 additions & 0 deletions
18
packages/patternfly-4/react-core/src/components/Switch/Switch.docs.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import { Switch } from '@patternfly/react-core'; | ||
| import SimpleSwitch from './examples/SimpleSwitch'; | ||
| import NoLabelSwitch from './examples/NoLabelSwitch'; | ||
| import DisabledSwitch from './examples/DisabledSwitch'; | ||
| import UncontrolledSwitch from './examples/UncontrolledSwitch'; | ||
|
|
||
| export default { | ||
| title: 'Switch', | ||
| components: { | ||
| Switch | ||
| }, | ||
| examples: [ | ||
| { component: SimpleSwitch, title: 'Simple Switch' }, | ||
| { component: NoLabelSwitch, title: 'Switch with no labels' }, | ||
| { component: DisabledSwitch, title: 'Disabled Switch' }, | ||
| { component: UncontrolledSwitch, title: 'Uncontrolled Switch' } | ||
| ] | ||
| }; |
68 changes: 68 additions & 0 deletions
68
packages/patternfly-4/react-core/src/components/Switch/Switch.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| import React from 'react'; | ||
| import styles from '@patternfly/patternfly-next/components/Switch/switch.css'; | ||
| import { css } from '@patternfly/react-styles'; | ||
| import PropTypes from 'prop-types'; | ||
| import { getUniqueId } from '../../internal/util'; | ||
|
|
||
| const propTypes = { | ||
| /** id for the label. */ | ||
| id: PropTypes.string, | ||
| /** Additional classes added to the Switch */ | ||
| className: PropTypes.string, | ||
| /** Text value for the label */ | ||
| label: PropTypes.string, | ||
| /** Flag to show if the Switch is checked. */ | ||
| isChecked: PropTypes.bool, | ||
| /** Flag to show if the Switch is disabled. */ | ||
| isDisabled: PropTypes.bool, | ||
| /** A callback for when the Switch selection changes. (isChecked, event) => {} */ | ||
| onChange: PropTypes.func, | ||
| /** Adds accessible text to the Switch. */ | ||
| 'aria-label': props => { | ||
| if (!props.id && !props['aria-label']) { | ||
| return new Error('Switch requires either an id or aria-label to be specified'); | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| const defaultProps = { | ||
| id: '', | ||
| className: '', | ||
| label: '', | ||
| isChecked: true, | ||
| isDisabled: false, | ||
| onChange: () => undefined, | ||
| 'aria-label': '' | ||
| }; | ||
|
|
||
| class Switch extends React.Component { | ||
| id = this.props.id || getUniqueId(); | ||
|
|
||
| render() { | ||
| const { id, className, label, isChecked, isDisabled, onChange, ...props } = this.props; | ||
| return ( | ||
| <label className={css(styles.switch, className)} htmlFor={this.id}> | ||
| <input | ||
| {...props} | ||
| id={this.id} | ||
| className={css(styles.switchInput)} | ||
| type="checkbox" | ||
| onChange={event => onChange(event.currentTarget.checked, event)} | ||
| checked={isChecked} | ||
| disabled={isDisabled} | ||
| /> | ||
| <span className={css(styles.switchToggle)} /> | ||
| {label && ( | ||
| <span className={css(styles.switchLabel)} aria-hidden="true"> | ||
| {label} | ||
| </span> | ||
| )} | ||
| </label> | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| Switch.propTypes = propTypes; | ||
| Switch.defaultProps = defaultProps; | ||
|
|
||
| export default Switch; |
59 changes: 59 additions & 0 deletions
59
packages/patternfly-4/react-core/src/components/Switch/Switch.test.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| import React from 'react'; | ||
| import { shallow } from 'enzyme'; | ||
| import Switch from './Switch'; | ||
|
|
||
| const props = { | ||
| onChange: jest.fn(), | ||
| checked: false | ||
| }; | ||
|
|
||
| test('switch label for attribute equals input id attribute', () => { | ||
| const view = shallow(<Switch id="foo" />); | ||
| expect(view.find('input').prop('id')).toBe('foo'); | ||
| expect(view.find('label').prop('htmlFor')).toBe('foo'); | ||
| }); | ||
|
|
||
| test('switch label id is auto generated', () => { | ||
| const view = shallow(<Switch aria-label="..." />); | ||
| expect(view.find('input').prop('id')).toBeDefined(); | ||
| }); | ||
|
|
||
| test('switch is checked', () => { | ||
| const view = shallow(<Switch id="switch-is-checked" label="On" isChecked />); | ||
| expect(view).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| test('switch is not checked', () => { | ||
| const view = shallow(<Switch id="switch-is-not-checked" label="Off" isChecked={false} />); | ||
| expect(view).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| test('no label switch is checked', () => { | ||
| const view = shallow(<Switch id="no-label-switch-is-checked" isChecked />); | ||
| expect(view).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| test('no label switch is not checked', () => { | ||
| const view = shallow(<Switch id="no-label-switch-is-not-checked" isChecked={false} />); | ||
| expect(view).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| test('switch is checked and disabled', () => { | ||
| const view = shallow(<Switch id="switch-is-checked-and-disabled" isChecked isDisabled />); | ||
| expect(view).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| test('switch is not checked and disabled', () => { | ||
| const view = shallow(<Switch id="switch-is-not-checked-and-disabled" isChecked={false} isDisabled />); | ||
| expect(view).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| test('switch passes value and event to onChange handler', () => { | ||
| const newValue = true; | ||
| const event = { | ||
| currentTarget: { checked: newValue } | ||
| }; | ||
| const view = shallow(<Switch id="onChange-switch" {...props} />); | ||
| view.find('input').simulate('change', event); | ||
| expect(props.onChange).toBeCalledWith(newValue, event); | ||
| }); |
223 changes: 223 additions & 0 deletions
223
packages/patternfly-4/react-core/src/components/Switch/__snapshots__/Switch.test.js.snap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,223 @@ | ||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
|
||
| exports[`no label switch is checked 1`] = ` | ||
| .pf-c-switch__input { | ||
| display: block; | ||
| } | ||
| .pf-c-switch__toggle { | ||
| display: block; | ||
| } | ||
| .pf-c-switch { | ||
| display: inline-block; | ||
| position: relative; | ||
| line-height: 1.5; | ||
| vertical-align: middle; | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| <label | ||
| className="pf-c-switch" | ||
| htmlFor="no-label-switch-is-checked" | ||
| > | ||
| <input | ||
| aria-label="" | ||
| checked={true} | ||
| className="pf-c-switch__input" | ||
| disabled={false} | ||
| id="no-label-switch-is-checked" | ||
| onChange={[Function]} | ||
| type="checkbox" | ||
| /> | ||
| <span | ||
| className="pf-c-switch__toggle" | ||
| /> | ||
| </label> | ||
| `; | ||
|
|
||
| exports[`no label switch is not checked 1`] = ` | ||
| .pf-c-switch__input { | ||
| display: block; | ||
| } | ||
| .pf-c-switch__toggle { | ||
| display: block; | ||
| } | ||
| .pf-c-switch { | ||
| display: inline-block; | ||
| position: relative; | ||
| line-height: 1.5; | ||
| vertical-align: middle; | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| <label | ||
| className="pf-c-switch" | ||
| htmlFor="no-label-switch-is-not-checked" | ||
| > | ||
| <input | ||
| aria-label="" | ||
| checked={false} | ||
| className="pf-c-switch__input" | ||
| disabled={false} | ||
| id="no-label-switch-is-not-checked" | ||
| onChange={[Function]} | ||
| type="checkbox" | ||
| /> | ||
| <span | ||
| className="pf-c-switch__toggle" | ||
| /> | ||
| </label> | ||
| `; | ||
|
|
||
| exports[`switch is checked 1`] = ` | ||
| .pf-c-switch__input { | ||
| display: block; | ||
| } | ||
| .pf-c-switch__toggle { | ||
| display: block; | ||
| } | ||
| .pf-c-switch__label { | ||
| display: block; | ||
| } | ||
| .pf-c-switch { | ||
| display: inline-block; | ||
| position: relative; | ||
| line-height: 1.5; | ||
| vertical-align: middle; | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| <label | ||
| className="pf-c-switch" | ||
| htmlFor="switch-is-checked" | ||
| > | ||
| <input | ||
| aria-label="" | ||
| checked={true} | ||
| className="pf-c-switch__input" | ||
| disabled={false} | ||
| id="switch-is-checked" | ||
| onChange={[Function]} | ||
| type="checkbox" | ||
| /> | ||
| <span | ||
| className="pf-c-switch__toggle" | ||
| /> | ||
| <span | ||
| aria-hidden="true" | ||
| className="pf-c-switch__label" | ||
| > | ||
| On | ||
| </span> | ||
| </label> | ||
| `; | ||
|
|
||
| exports[`switch is checked and disabled 1`] = ` | ||
| .pf-c-switch__input { | ||
| display: block; | ||
| } | ||
| .pf-c-switch__toggle { | ||
| display: block; | ||
| } | ||
| .pf-c-switch { | ||
| display: inline-block; | ||
| position: relative; | ||
| line-height: 1.5; | ||
| vertical-align: middle; | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| <label | ||
| className="pf-c-switch" | ||
| htmlFor="switch-is-checked-and-disabled" | ||
| > | ||
| <input | ||
| aria-label="" | ||
| checked={true} | ||
| className="pf-c-switch__input" | ||
| disabled={true} | ||
| id="switch-is-checked-and-disabled" | ||
| onChange={[Function]} | ||
| type="checkbox" | ||
| /> | ||
| <span | ||
| className="pf-c-switch__toggle" | ||
| /> | ||
| </label> | ||
| `; | ||
|
|
||
| exports[`switch is not checked 1`] = ` | ||
| .pf-c-switch__input { | ||
| display: block; | ||
| } | ||
| .pf-c-switch__toggle { | ||
| display: block; | ||
| } | ||
| .pf-c-switch__label { | ||
| display: block; | ||
| } | ||
| .pf-c-switch { | ||
| display: inline-block; | ||
| position: relative; | ||
| line-height: 1.5; | ||
| vertical-align: middle; | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| <label | ||
| className="pf-c-switch" | ||
| htmlFor="switch-is-not-checked" | ||
| > | ||
| <input | ||
| aria-label="" | ||
| checked={false} | ||
| className="pf-c-switch__input" | ||
| disabled={false} | ||
| id="switch-is-not-checked" | ||
| onChange={[Function]} | ||
| type="checkbox" | ||
| /> | ||
| <span | ||
| className="pf-c-switch__toggle" | ||
| /> | ||
| <span | ||
| aria-hidden="true" | ||
| className="pf-c-switch__label" | ||
| > | ||
| Off | ||
| </span> | ||
| </label> | ||
| `; | ||
|
|
||
| exports[`switch is not checked and disabled 1`] = ` | ||
| .pf-c-switch__input { | ||
| display: block; | ||
| } | ||
| .pf-c-switch__toggle { | ||
| display: block; | ||
| } | ||
| .pf-c-switch { | ||
| display: inline-block; | ||
| position: relative; | ||
| line-height: 1.5; | ||
| vertical-align: middle; | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| <label | ||
| className="pf-c-switch" | ||
| htmlFor="switch-is-not-checked-and-disabled" | ||
| > | ||
| <input | ||
| aria-label="" | ||
| checked={false} | ||
| className="pf-c-switch__input" | ||
| disabled={true} | ||
| id="switch-is-not-checked-and-disabled" | ||
| onChange={[Function]} | ||
| type="checkbox" | ||
| /> | ||
| <span | ||
| className="pf-c-switch__toggle" | ||
| /> | ||
| </label> | ||
| `; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.