Skip to content
This repository was archived by the owner on Jun 20, 2022. It is now read-only.

Commit 4fdfc73

Browse files
committed
feat: add variants to buttons
1 parent 4c33e13 commit 4fdfc73

File tree

9 files changed

+107
-36
lines changed

9 files changed

+107
-36
lines changed

src/Button.js

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
11
import React from 'react'
22
import PropTypes from 'prop-types'
33
import classNames from 'classnames'
4-
import styled from 'styled-components'
4+
import styled, { css } from 'styled-components'
55
import handleRef from './internal/handleRef'
66
import * as defaultTheme from './style/defaultTheme'
7-
import { th } from './utils'
7+
import { th, mixin } from './utils'
88

9-
const ButtonComponent = ({ className, size, ...props }) => (
9+
const variants = [
10+
'primary',
11+
'secondary',
12+
'success',
13+
'danger',
14+
'warning',
15+
'info',
16+
'light',
17+
'dark',
18+
]
19+
20+
const ButtonComponent = ({ className, size, theme, variant, ...props }) => (
1021
<button
1122
{...props}
1223
className={classNames(
1324
'sui-button',
1425
{
1526
[`sui-button-${size}`]: size,
27+
[`sui-button-${variant}`]: variant,
1628
},
1729
className,
1830
)}
@@ -26,21 +38,11 @@ const Button = styled(handleRef(ButtonComponent))`
2638
border-radius: ${th('borderRadius')};
2739
font-size: ${th('fontSizeBase')};
2840
line-height: ${th('lineHeightBase')};
29-
background-color: ${th('btnBackgroundColor')};
3041
color: ${th('white')};
3142
border-width: ${th('btnBorderWidth')};
3243
cursor: pointer;
3344
transition: ${th('transitionBase')};
3445
35-
&:focus {
36-
${th('controlFocus')};
37-
}
38-
39-
&:not(:disabled):hover,
40-
&:not(:disabled):active {
41-
background-color: ${th('btnHoverBackgroundColor')};
42-
}
43-
4446
&.sui-button-sm {
4547
padding: ${th('btnPaddingYSm')} ${th('btnPaddingXSm')};
4648
font-size: ${th('fontSizeSm')};
@@ -56,15 +58,25 @@ const Button = styled(handleRef(ButtonComponent))`
5658
&:disabled {
5759
opacity: ${th('btnDisabledOpacity')};
5860
}
61+
62+
${variants.map(
63+
variant => css`
64+
&.sui-button-${variant} {
65+
${mixin('btnVariant', variant)};
66+
}
67+
`,
68+
)};
5969
`
6070

6171
Button.propTypes = {
62-
size: PropTypes.oneOf(['sm', 'lg']),
6372
disabled: PropTypes.bool,
73+
size: PropTypes.oneOf(['sm', 'lg']),
74+
variant: PropTypes.oneOf(variants),
6475
theme: PropTypes.object,
6576
}
6677

6778
Button.defaultProps = {
79+
variant: 'primary',
6880
theme: defaultTheme,
6981
}
7082

src/Button.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,36 @@
1+
### Variants
2+
3+
Set sizes using `variant` prop.
4+
5+
```js
6+
<div>
7+
<span style={{ margin: '5px' }}>
8+
<Button variant="primary">Primary</Button>
9+
</span>
10+
<span style={{ margin: '5px' }}>
11+
<Button variant="secondary">Secondary</Button>
12+
</span>
13+
<span style={{ margin: '5px' }}>
14+
<Button variant="success">Success</Button>
15+
</span>
16+
<span style={{ margin: '5px' }}>
17+
<Button variant="danger">Danger</Button>
18+
</span>
19+
<span style={{ margin: '5px' }}>
20+
<Button variant="warning">Warning</Button>
21+
</span>
22+
<span style={{ margin: '5px' }}>
23+
<Button variant="info">Info</Button>
24+
</span>
25+
<span style={{ margin: '5px' }}>
26+
<Button variant="light">Light</Button>
27+
</span>
28+
<span style={{ margin: '5px' }}>
29+
<Button variant="dark">Dark</Button>
30+
</span>
31+
</div>
32+
```
33+
134
### Sizes
235

336
Set sizes using `size` prop like `"sm"` or `"lg"`.

src/Checkbox.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import styled from 'styled-components'
44
import classNames from 'classnames'
55
import InnerSwitch from './internal/InnerSwitch'
66
import * as defaultTheme from './style/defaultTheme'
7-
import { th } from './utils'
7+
import { th, mixin } from './utils'
88

99
const CheckboxComponent = ({ className, size, theme, ...props }) => (
1010
<div
@@ -69,7 +69,7 @@ const Checkbox = styled(CheckboxComponent)`
6969
}
7070
7171
&.focused {
72-
${th('controlFocus')};
72+
${mixin('controlFocus')};
7373
}
7474
7575
&.disabled {

src/Input.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
44
import styled from 'styled-components'
55
import handleRef from './internal/handleRef'
66
import * as defaultTheme from './style/defaultTheme'
7-
import { th } from './utils'
7+
import { th, mixin } from './utils'
88

99
const InputComponent = ({
1010
className,
@@ -51,7 +51,7 @@ const Input = styled(handleRef(InputComponent))`
5151
}
5252
5353
&:focus {
54-
${th('controlFocus')};
54+
${mixin('controlFocus')};
5555
}
5656
5757
&[disabled] {

src/Radio.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import styled from 'styled-components'
44
import classNames from 'classnames'
55
import * as defaultTheme from './style/defaultTheme'
66
import InnerSwitch from './internal/InnerSwitch'
7-
import { th } from './utils'
7+
import { th, mixin } from './utils'
88

99
const RadioComponent = ({ className, size, theme, ...props }) => (
1010
<div
@@ -62,7 +62,7 @@ const Radio = styled(RadioComponent)`
6262
}
6363
6464
&.focused {
65-
${th('controlFocus')};
65+
${mixin('controlFocus')};
6666
}
6767
6868
&.disabled {

src/Select.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import classNames from 'classnames'
44
import styled from 'styled-components'
55
import handleRef from './internal/handleRef'
66
import * as defaultTheme from './style/defaultTheme'
7-
import { th } from './utils'
7+
import { th, mixin } from './utils'
88

99
const renderOption = option => {
1010
const { label, value } =
@@ -84,7 +84,7 @@ const Select = styled(handleRef(SelectComponent))`
8484
padding-right: 1.6rem;
8585
8686
&:focus {
87-
${th('controlFocus')};
87+
${mixin('controlFocus')};
8888
}
8989
9090
&[disabled] {

src/Switch.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import styled from 'styled-components'
44
import classNames from 'classnames'
55
import * as defaultTheme from './style/defaultTheme'
66
import InnerSwitch from './internal/InnerSwitch'
7-
import { th } from './utils'
7+
import { th, mixin } from './utils'
88

99
const SwitchComponent = ({ className, labeled, theme, ...props }) => (
1010
<div
@@ -53,7 +53,7 @@ const Switch = styled(SwitchComponent)`
5353
transition: ${th('transitionBase')};
5454
5555
&.focused {
56-
${th('controlFocus')};
56+
${mixin('controlFocus')};
5757
}
5858
5959
&.checked {

src/style/defaultTheme.js

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
/* eslint-disable no-unused-vars */
22
import { injectGlobal, css } from 'styled-components'
3-
import { transparentize, lighten, modularScale, darken } from 'polished'
4-
import { th } from '../utils'
3+
import {
4+
transparentize,
5+
lighten,
6+
modularScale,
7+
darken,
8+
parseToRgb,
9+
} from 'polished'
10+
import { th, mixin } from '../utils'
511

612
/* eslint-disable no-unused-expressions */
713
injectGlobal`
@@ -54,6 +60,9 @@ export const dark = gray800
5460
export const primaryLight = th('primary', c => lighten(0.3, c))
5561
export const secondaryLight = th('secondary', c => lighten(0.3, c))
5662

63+
export const yikTextDark = '#111'
64+
export const yikTextLight = '#fff'
65+
5766
// Borders
5867

5968
export const borderRadius = '.25rem'
@@ -110,11 +119,6 @@ export const btnPaddingXLg = th('inputBtnPaddingXLg')
110119
export const btnLineHeightLg = th('inputBtnLineHeightLg')
111120

112121
export const btnBorderWidth = 0
113-
114-
export const btnBackgroundColor = th('primary')
115-
export const btnHoverBackgroundColor = th('btnBackgroundColor', color =>
116-
darken(0.05, color),
117-
)
118122
export const btnDisabledOpacity = 0.8
119123

120124
// Inputs
@@ -168,7 +172,27 @@ export const breakPoints = {
168172

169173
// Mixins
170174

171-
export const controlFocus = css`
175+
export const controlFocus = (baseColor = 'primary') => css`
172176
outline: 0;
173-
box-shadow: 0 0 2px ${th('primary', color => transparentize(0.1, color))};
177+
box-shadow: 0 0 2px ${th(baseColor, color => transparentize(0.1, color))};
174178
`
179+
180+
export const btnVariant = baseColor => css`
181+
color: ${props => props.theme.colorYik(th(baseColor)(props))};
182+
background-color: ${th(baseColor)};
183+
184+
&:focus {
185+
${mixin('controlFocus', baseColor)};
186+
}
187+
188+
&:not(:disabled):hover,
189+
&:not(:disabled):active {
190+
background-color: ${th(baseColor, color => darken(0.05, color))};
191+
}
192+
`
193+
194+
export const colorYik = color => {
195+
const { red: r, green: g, blue: b } = parseToRgb(color)
196+
const yik = (r * 299 + g * 587 + b * 114) / 1000
197+
return yik >= 150 ? th('yikTextDark') : th('yikTextLight')
198+
}

src/utils.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@ export const upTo = (breakPoint, code) => css`
99
${code};
1010
}
1111
`
12-
export const th = (value, modifier = x => x) => props => {
12+
export const th = (name, modifier = x => x) => props => {
1313
function run(fn) {
1414
const next = fn(props)
1515
if (typeof next === 'undefined')
16-
throw new Error(`"${value}" not found in theme`)
16+
throw new Error(`"${name}" not found in theme`)
1717
if (typeof next === 'function') return run(next)
1818
return next
1919
}
2020

21-
const result = run(p => p.theme[value])
21+
const result = run(p => p.theme[name])
2222
return modifier(result)
2323
}
24+
25+
export const mixin = (name, ...args) => props => props.theme[name](...args)

0 commit comments

Comments
 (0)