-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Pill, DeletablePill, EasyPill (#81)
Bumped to alpha 12 * Add Pill, DeletablePill, EasyPill * Rename clear to times-circled, limited onDelete click to the icon
- Loading branch information
1 parent
defd0b6
commit f53fbf9
Showing
27 changed files
with
795 additions
and
28 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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,5 @@ | ||
# DeletablePill | ||
|
||
When checked, the pill has a small delete icon (⊗). Clicking it fires an `onDelete` function. | ||
|
||
When unchecked, it behaves just like a regular pill. |
This file contains 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,37 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
import Icon from '../Icon'; | ||
import Pill from '../Pill'; | ||
|
||
export const DeletablePill = ({ children, onDelete, ...passedProps }) => { | ||
return ( | ||
<Pill {...passedProps}> | ||
{children} | ||
{passedProps.checked && ( | ||
<Pill.Addon | ||
onClick={e => { | ||
e.stopPropagation(); | ||
onDelete(e); | ||
}} | ||
role="button" | ||
tabIndex={0} | ||
> | ||
<Icon name="times-circle" style={{ display: 'block' }} /> | ||
</Pill.Addon> | ||
)} | ||
</Pill> | ||
); | ||
}; | ||
|
||
DeletablePill.propTypes = { | ||
checked: PropTypes.bool, | ||
children: PropTypes.node.isRequired, | ||
onDelete: PropTypes.func.isRequired, | ||
}; | ||
|
||
DeletablePill.defaultProps = { | ||
checked: false, | ||
}; | ||
|
||
export default DeletablePill; |
This file contains 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,32 @@ | ||
import React from 'react'; | ||
import { storiesOf } from '@storybook/react'; | ||
import { action } from '@storybook/addon-actions'; | ||
import { boolean } from '@storybook/addon-knobs'; | ||
|
||
import DeletablePill from './'; | ||
import Readme from './README.md'; | ||
|
||
storiesOf('Star Systems/DeletablePill', module) | ||
.addParameters({ | ||
readme: { | ||
sidebar: Readme, | ||
}, | ||
}) | ||
.add( | ||
'Overview', | ||
() => ( | ||
<DeletablePill | ||
checked={boolean('checked', false)} | ||
onClick={action('onClick')} | ||
onDelete={action('onDelete')} | ||
> | ||
DeletablePill 1 | ||
</DeletablePill> | ||
), | ||
{ | ||
info: { | ||
inline: true, | ||
source: true, | ||
}, | ||
} | ||
); |
This file contains 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,48 @@ | ||
import React from 'react'; | ||
import { mount, shallow } from 'enzyme'; | ||
|
||
import Icon from '../Icon'; | ||
import DeletablePill from './'; | ||
|
||
describe('DeletablePill', () => { | ||
it('renders', () => { | ||
shallow(<DeletablePill onDelete={() => {}}>DeletablePill</DeletablePill>); | ||
}); | ||
|
||
describe('with children', () => { | ||
it('renders its children', () => { | ||
const wrapper = mount( | ||
<DeletablePill onDelete={() => {}}>DeletablePill 1</DeletablePill> | ||
); | ||
|
||
expect(wrapper.children()).toHaveLength(1); | ||
expect(wrapper.text()).toEqual('DeletablePill 1'); | ||
}); | ||
}); | ||
|
||
describe('when unchecked', () => { | ||
it("doesn't show clear action", () => { | ||
const wrapper = mount( | ||
<DeletablePill onDelete={() => {}}>DeletablePill 1</DeletablePill> | ||
); | ||
|
||
const clear = wrapper.find(Icon); | ||
|
||
expect(clear).toHaveLength(0); | ||
}); | ||
}); | ||
|
||
describe('when checked', () => { | ||
it('shows clear action', () => { | ||
const wrapper = mount( | ||
<DeletablePill checked onDelete={() => {}}> | ||
DeletablePill 1 | ||
</DeletablePill> | ||
); | ||
|
||
const clear = wrapper.find(Icon); | ||
|
||
expect(clear).toHaveLength(1); | ||
}); | ||
}); | ||
}); |
This file contains 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,12 @@ | ||
# EasyPill | ||
|
||
Easy pills are more opinionated than basic pills, to make it easy to get started on the most common use cases. | ||
They take an `actions` prop that's an array of objects. | ||
Each object has, at least, a callback function (`onClick`) and a text label (`label`). | ||
|
||
Easy pills show those action labels in a list. Each one fires its callback function when clicked. | ||
Easy pill actions may also have `children` props, in which case they'll render the `children` as a React node instead of the label. You still need to provide a unique text label, though, for use as an identifying key. | ||
|
||
Easy pills come with a delete action by default. If you provide an `onDelete` function as a prop, it will show up automatically. | ||
|
||
**TODO**: The easy pill's actions should be in a small dropdown with an ellipsis icon that triggers it. |
This file contains 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,57 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
import Icon from '../Icon'; | ||
import Pill from '../Pill'; | ||
|
||
export const EasyPill = ({ actions, children, onDelete, ...passedProps }) => { | ||
return ( | ||
<Pill {...passedProps}> | ||
{children} | ||
{passedProps.checked && | ||
!!actions.length && | ||
actions.map(action => ( | ||
<Pill.Addon | ||
key={action.label} | ||
onClick={e => { | ||
e.stopPropagation(); | ||
action.onClick(e); | ||
}} | ||
> | ||
{action.children || action.label} | ||
</Pill.Addon> | ||
))} | ||
{passedProps.checked && onDelete && ( | ||
<Pill.Addon | ||
onClick={e => { | ||
e.stopPropagation(); | ||
onDelete(e); | ||
}} | ||
> | ||
<Icon name="times-circle" /> | ||
</Pill.Addon> | ||
)} | ||
</Pill> | ||
); | ||
}; | ||
|
||
EasyPill.propTypes = { | ||
actions: PropTypes.arrayOf( | ||
PropTypes.shape({ | ||
children: PropTypes.string, | ||
label: PropTypes.string.isRequired, | ||
onClick: PropTypes.func.isRequired, | ||
}) | ||
), | ||
checked: PropTypes.bool, | ||
children: PropTypes.node.isRequired, | ||
onDelete: PropTypes.func, | ||
}; | ||
|
||
EasyPill.defaultProps = { | ||
actions: [], | ||
checked: false, | ||
onDelete: null, | ||
}; | ||
|
||
export default EasyPill; |
This file contains 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,42 @@ | ||
import React from 'react'; | ||
import { storiesOf } from '@storybook/react'; | ||
import { action } from '@storybook/addon-actions'; | ||
import { boolean } from '@storybook/addon-knobs'; | ||
|
||
import EasyPill from './'; | ||
import Readme from './README.md'; | ||
|
||
storiesOf('Star Systems/EasyPill', module) | ||
.addParameters({ | ||
readme: { | ||
sidebar: Readme, | ||
}, | ||
}) | ||
.add( | ||
'Overview', | ||
() => ( | ||
<EasyPill | ||
actions={[ | ||
{ | ||
label: 'Boom', | ||
onClick: action('Boom'), | ||
}, | ||
{ | ||
label: 'Bang', | ||
onClick: action('Bang'), | ||
}, | ||
]} | ||
checked={boolean('checked', false)} | ||
onClick={action('onClick')} | ||
onDelete={action('onDelete')} | ||
> | ||
EasyPill 1 | ||
</EasyPill> | ||
), | ||
{ | ||
info: { | ||
inline: true, | ||
source: true, | ||
}, | ||
} | ||
); |
This file contains 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,81 @@ | ||
import React from 'react'; | ||
import { mount, shallow } from 'enzyme'; | ||
|
||
import Pill from '../Pill'; | ||
import EasyPill from './'; | ||
|
||
describe('EasyPill', () => { | ||
it('renders', () => { | ||
shallow(<EasyPill onDelete={() => {}}>EasyPill</EasyPill>); | ||
}); | ||
|
||
describe('with children', () => { | ||
it('renders its children', () => { | ||
const wrapper = mount( | ||
<EasyPill onDelete={() => {}}>EasyPill 1</EasyPill> | ||
); | ||
|
||
expect(wrapper.children()).toHaveLength(1); | ||
expect(wrapper.text()).toEqual('EasyPill 1'); | ||
}); | ||
}); | ||
|
||
describe('with props.actions', () => { | ||
describe('when unchecked', () => { | ||
it("doesn't render actions", () => { | ||
const wrapper = mount( | ||
<EasyPill | ||
actions={[ | ||
{ | ||
label: 'Boom', | ||
onClick: () => {}, | ||
}, | ||
{ | ||
label: 'Bang', | ||
onClick: () => {}, | ||
}, | ||
]} | ||
onClick={() => {}} | ||
> | ||
EasyPill 1 | ||
</EasyPill> | ||
); | ||
|
||
// Should use css modules selector, but our version of react-scripts doesn't support it. | ||
const addons = wrapper.find(Pill.Addon); | ||
|
||
expect(addons.children()).toHaveLength(0); | ||
}); | ||
}); | ||
|
||
describe('when checked', () => { | ||
it('does render actions', () => { | ||
const wrapper = mount( | ||
<EasyPill | ||
actions={[ | ||
{ | ||
label: 'Boom', | ||
onClick: () => {}, | ||
}, | ||
{ | ||
label: 'Bang', | ||
onClick: () => {}, | ||
}, | ||
]} | ||
checked | ||
onClick={() => {}} | ||
> | ||
EasyPill 1 | ||
</EasyPill> | ||
); | ||
|
||
// Should use css modules selector, but our version of react-scripts doesn't support it. | ||
const addons = wrapper.find(Pill.Addon); | ||
|
||
expect(addons).toHaveLength(2); | ||
expect(addons.at(0).text()).toEqual('Boom'); | ||
expect(addons.at(1).text()).toEqual('Bang'); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.