Browse Source
feat(ui): add Button component
renovate/lint-staged-8.x
Tom Kirkpatrick
6 years ago
No known key found for this signature in database
GPG Key ID: 72203A8EC5967EA8
4 changed files with
208 additions and
0 deletions
-
app/components/UI/Button.js
-
stories/components/button.stories.js
-
test/unit/components/UI/Button.spec.js
-
test/unit/components/UI/__snapshots__/Button.spec.js.snap
|
|
@ -0,0 +1,83 @@ |
|
|
|
import React from 'react' |
|
|
|
import PropTypes from 'prop-types' |
|
|
|
import styled from 'styled-components' |
|
|
|
import { Button as BaseButton, Flex, Text } from 'rebass' |
|
|
|
import Spinner from './Spinner' |
|
|
|
|
|
|
|
const Wrapper = styled(BaseButton)` |
|
|
|
transition: all 0.25s; |
|
|
|
outline: none; |
|
|
|
border-radius: 5; |
|
|
|
font-weight: normal; |
|
|
|
line-height: '18px'; |
|
|
|
&:focus { |
|
|
|
box-shadow: 0 0 3px ${props => props.theme.lightningOrange}; |
|
|
|
} |
|
|
|
&:disabled { |
|
|
|
opacity: 0.5; |
|
|
|
} |
|
|
|
&:hover:enabled { |
|
|
|
cursor: pointer; |
|
|
|
} |
|
|
|
` |
|
|
|
Wrapper.displayName = 'Button' |
|
|
|
|
|
|
|
/** |
|
|
|
* @render react |
|
|
|
* @name Button |
|
|
|
* @example |
|
|
|
* <Button><Basic button</Button> |
|
|
|
*/ |
|
|
|
class Button extends React.PureComponent { |
|
|
|
static displayName = 'Button' |
|
|
|
static defaultProps = { |
|
|
|
processing: false, |
|
|
|
size: 'medium', |
|
|
|
variant: 'normal' |
|
|
|
} |
|
|
|
static propTypes = { |
|
|
|
processing: PropTypes.bool, |
|
|
|
size: PropTypes.oneOf(['small', 'medium', 'large']), |
|
|
|
variant: PropTypes.string |
|
|
|
} |
|
|
|
|
|
|
|
render() { |
|
|
|
const { children, processing, size, ...rest } = this.props |
|
|
|
const sizes = { |
|
|
|
small: { |
|
|
|
x: 3, |
|
|
|
y: 2, |
|
|
|
fontSize: 's' |
|
|
|
}, |
|
|
|
medium: { |
|
|
|
x: 3, |
|
|
|
y: 2, |
|
|
|
fontSize: 'm' |
|
|
|
}, |
|
|
|
large: { |
|
|
|
x: 5, |
|
|
|
y: 3, |
|
|
|
fontSize: 'l' |
|
|
|
} |
|
|
|
} |
|
|
|
return ( |
|
|
|
<Wrapper |
|
|
|
px={sizes[size]['x']} |
|
|
|
py={sizes[size]['y']} |
|
|
|
fontSize={sizes[size]['fontSize']} |
|
|
|
{...rest} |
|
|
|
> |
|
|
|
{processing ? ( |
|
|
|
<Flex> |
|
|
|
{processing && <Spinner size="2em" mr="0.5em" />} |
|
|
|
<Text fontFamily="sans">{children}</Text> |
|
|
|
</Flex> |
|
|
|
) : ( |
|
|
|
<Text fontFamily="sans">{children}</Text> |
|
|
|
)} |
|
|
|
</Wrapper> |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
export default Button |
|
|
@ -0,0 +1,56 @@ |
|
|
|
import React from 'react' |
|
|
|
import { storiesOf } from '@storybook/react' |
|
|
|
import { action } from '@storybook/addon-actions' |
|
|
|
import Button from 'components/UI/Button' |
|
|
|
import SystemNavPrevious from 'components/Icon/SystemNavPrevious' |
|
|
|
import SystemNavNext from 'components/Icon/SystemNavNext' |
|
|
|
|
|
|
|
storiesOf('Components.Button', module) |
|
|
|
.add('Basic', () => <Button onClick={action('clicked')}>Basic button</Button>) |
|
|
|
.add('With Icon', () => ( |
|
|
|
<section> |
|
|
|
<Button onClick={action('clicked')}> |
|
|
|
<SystemNavPrevious /> |
|
|
|
Previous |
|
|
|
</Button>{' '} |
|
|
|
<Button onClick={action('clicked')}> |
|
|
|
Next |
|
|
|
<SystemNavNext /> |
|
|
|
</Button> |
|
|
|
</section> |
|
|
|
)) |
|
|
|
.add('Processing', () => ( |
|
|
|
<Button processing onClick={action('clicked')}> |
|
|
|
Processing |
|
|
|
</Button> |
|
|
|
)) |
|
|
|
.add('Disabled', () => ( |
|
|
|
<Button disabled onClick={action('clicked')}> |
|
|
|
Disabled button |
|
|
|
</Button> |
|
|
|
)) |
|
|
|
.add('Primary', () => ( |
|
|
|
<Button onClick={action('clicked')} variant="primary"> |
|
|
|
Primary button |
|
|
|
</Button> |
|
|
|
)) |
|
|
|
.add('Secondary', () => ( |
|
|
|
<Button onClick={action('clicked')} variant="secondary"> |
|
|
|
Secondary button |
|
|
|
</Button> |
|
|
|
)) |
|
|
|
.add('Small', () => ( |
|
|
|
<Button onClick={action('clicked')} size="small"> |
|
|
|
Small button |
|
|
|
</Button> |
|
|
|
)) |
|
|
|
.add('Medium', () => ( |
|
|
|
<Button onClick={action('clicked')} size="medium"> |
|
|
|
Medium button |
|
|
|
</Button> |
|
|
|
)) |
|
|
|
.add('Large', () => ( |
|
|
|
<Button onClick={action('clicked')} size="large"> |
|
|
|
Large button |
|
|
|
</Button> |
|
|
|
)) |
|
|
@ -0,0 +1,10 @@ |
|
|
|
import React from 'react' |
|
|
|
import Button from 'components/UI/Button' |
|
|
|
import renderer from 'react-test-renderer' |
|
|
|
|
|
|
|
describe('component.UI.Button', () => { |
|
|
|
it('should render correctly', () => { |
|
|
|
const tree = renderer.create(<Button />).toJSON() |
|
|
|
expect(tree).toMatchSnapshot() |
|
|
|
}) |
|
|
|
}) |
|
|
@ -0,0 +1,59 @@ |
|
|
|
// Jest Snapshot v1, https://goo.gl/fbAQLP |
|
|
|
|
|
|
|
exports[`component.UI.Button should render correctly 1`] = ` |
|
|
|
.c1 { |
|
|
|
font-family: sans; |
|
|
|
} |
|
|
|
|
|
|
|
.c0 { |
|
|
|
margin: 0px; |
|
|
|
padding-left: 16px; |
|
|
|
padding-right: 16px; |
|
|
|
padding-top: 8px; |
|
|
|
padding-bottom: 8px; |
|
|
|
font-size: m; |
|
|
|
color: white; |
|
|
|
background-color: blue; |
|
|
|
-webkit-appearance: none; |
|
|
|
-moz-appearance: none; |
|
|
|
appearance: none; |
|
|
|
display: inline-block; |
|
|
|
text-align: center; |
|
|
|
line-height: inherit; |
|
|
|
-webkit-text-decoration: none; |
|
|
|
text-decoration: none; |
|
|
|
font-weight: bold; |
|
|
|
border: 0; |
|
|
|
border-radius: 4px; |
|
|
|
-webkit-transition: all 0.25s; |
|
|
|
transition: all 0.25s; |
|
|
|
outline: none; |
|
|
|
border-radius: 5; |
|
|
|
font-weight: normal; |
|
|
|
line-height: '18px'; |
|
|
|
} |
|
|
|
|
|
|
|
.c0:focus { |
|
|
|
box-shadow: 0 0 3px; |
|
|
|
} |
|
|
|
|
|
|
|
.c0:disabled { |
|
|
|
opacity: 0.5; |
|
|
|
} |
|
|
|
|
|
|
|
.c0:hover:enabled { |
|
|
|
cursor: pointer; |
|
|
|
} |
|
|
|
|
|
|
|
<button |
|
|
|
className="c0" |
|
|
|
color="white" |
|
|
|
fontSize="m" |
|
|
|
fontWeight="bold" |
|
|
|
> |
|
|
|
<div |
|
|
|
className="c1" |
|
|
|
fontFamily="sans" |
|
|
|
/> |
|
|
|
</button> |
|
|
|
`; |