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

Commit ec57ee4

Browse files
committed
feat(Alert): add alerts
BREAKING CHANGE: Mixins are now a function that takes props and return another function.
1 parent 2e7daf8 commit ec57ee4

File tree

7 files changed

+154
-6
lines changed

7 files changed

+154
-6
lines changed

β€Ž.eslintrc.jsβ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,7 @@ module.exports = {
1414
'import/prefer-default-export': 'off',
1515

1616
'no-return-assign': 'off',
17+
'no-param-reassign': 'off',
18+
'no-shadow': 'off',
1719
},
1820
}

β€Žsrc/Alert.jsβ€Ž

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import React from 'react'
2+
import PropTypes from 'prop-types'
3+
import classNames from 'classnames'
4+
import styled, { css } from 'styled-components'
5+
import handleRef from './internal/handleRef'
6+
import setWithComponent from './internal/setWithComponent'
7+
import * as defaultTheme from './style/defaultTheme'
8+
import { th, mixin } from './utils'
9+
10+
const variants = [
11+
'primary',
12+
'secondary',
13+
'success',
14+
'danger',
15+
'warning',
16+
'info',
17+
'light',
18+
'dark',
19+
]
20+
21+
const AlertComponent = ({
22+
className,
23+
component: Component = 'div',
24+
theme,
25+
variant,
26+
...props
27+
}) => (
28+
<Component
29+
{...props}
30+
className={classNames(
31+
'sui-alert',
32+
{
33+
[`sui-alert-${variant}`]: variant,
34+
},
35+
className,
36+
)}
37+
/>
38+
)
39+
40+
const Alert = styled(handleRef(AlertComponent))`
41+
position: relative;
42+
padding: ${th('alertPaddingY')} ${th('alertPaddingX')};
43+
margin-bottom: ${th('alertMarginBottom')};
44+
border: 1px solid transparent;
45+
border-radius: ${th('borderRadius')};
46+
47+
${variants.map(
48+
variant => css`
49+
&.sui-alert-${variant} {
50+
${mixin('alertVariant', variant)};
51+
}
52+
`,
53+
)};
54+
`
55+
56+
Alert.propTypes = {
57+
variant: PropTypes.oneOf(variants),
58+
theme: PropTypes.object,
59+
}
60+
61+
Alert.defaultProps = {
62+
variant: 'primary',
63+
theme: defaultTheme,
64+
}
65+
66+
setWithComponent(Alert, AlertComponent)
67+
68+
/** @component */
69+
export default Alert

β€Žsrc/Alert.mdβ€Ž

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

β€Žsrc/index.jsβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as defaultTheme from './style/defaultTheme'
22

3+
export { default as Alert } from './Alert'
34
export { default as Box } from './Box'
45
export { default as Button } from './Button'
56
export { default as Checkbox } from './Checkbox'

β€Žsrc/style/defaultTheme.jsβ€Ž

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
modularScale,
77
darken,
88
parseToRgb,
9+
mix,
910
} from 'polished'
1011
import { th, mixin } from '../utils'
1112

@@ -151,6 +152,16 @@ export const controlFocusBorderColor = th('primary', color =>
151152
export const controlFocusBoxShadow = color =>
152153
css`0 0 0 0.2rem ${th(color, c => transparentize(0.75, c))}`
153154

155+
// Alerts
156+
157+
export const alertPaddingY = '.75rem'
158+
export const alertPaddingX = '1.25rem'
159+
export const alertMarginBottom = '1rem'
160+
161+
export const alertBgLevel = -10
162+
export const alertBorderLevel = -9
163+
export const alertColorLevel = 6
164+
154165
// Z-indexes
155166

156167
export const zIndexControl = 1
@@ -170,15 +181,20 @@ export const breakPoints = {
170181
xl: 1200,
171182
}
172183

184+
// Color levels
185+
186+
export const yiqContrastedThreshold = 150
187+
export const colorInterval = 0.08
188+
173189
// Mixins
174190

175-
export const controlFocus = (baseColor = 'primary') => css`
191+
export const controlFocus = props => (baseColor = 'primary') => css`
176192
outline: 0;
177193
box-shadow: 0 0 2px ${th(baseColor, color => transparentize(0.1, color))};
178194
`
179195

180-
export const btnVariant = baseColor => css`
181-
color: ${props => props.theme.colorYik(th(baseColor)(props))};
196+
export const btnVariant = props => baseColor => css`
197+
color: ${mixin('colorYik', th(baseColor))};
182198
background-color: ${th(baseColor)};
183199
184200
&:focus {
@@ -191,8 +207,34 @@ export const btnVariant = baseColor => css`
191207
}
192208
`
193209

194-
export const colorYik = color => {
210+
export const alertVariant = props => baseColor =>
211+
css`
212+
color: ${mixin('colorLevel', th(baseColor), th('alertColorLevel'))};
213+
background-color: ${mixin('colorLevel', th(baseColor), th('alertBgLevel'))};
214+
border-color: ${mixin('colorLevel', th(baseColor), th('alertBorderLevel'))};
215+
216+
hr {
217+
border-top-color: ${props =>
218+
darken(
219+
0.05,
220+
mixin('colorLevel', th(baseColor), th('alertColorLevel'))(props),
221+
)};
222+
}
223+
`
224+
225+
export const colorLevel = props => (color, level) => {
226+
color = typeof color === 'function' ? color(props) : color
227+
level = typeof level === 'function' ? level(props) : level
228+
const baseColor = level > 0 ? th('black')(props) : th('white')(props)
229+
const absLevel = Math.abs(level)
230+
return mix(absLevel * colorInterval, baseColor, color)
231+
}
232+
233+
export const colorYik = props => color => {
234+
color = typeof color === 'function' ? color(props) : color
195235
const { red: r, green: g, blue: b } = parseToRgb(color)
196236
const yik = (r * 299 + g * 587 + b * 114) / 1000
197-
return yik >= 150 ? th('yikTextDark') : th('yikTextLight')
237+
return yik >= th('yiqContrastedThreshold')(props)
238+
? th('yikTextDark')(props)
239+
: th('yikTextLight')(props)
198240
}

β€Žsrc/utils.jsβ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@ export const th = (name, modifier = x => x) => props => {
2222
return modifier(result)
2323
}
2424

25-
export const mixin = (name, ...args) => props => props.theme[name](...args)
25+
export const mixin = (name, ...args) => props =>
26+
props.theme[name](props)(...args)

β€Žstyleguide.config.jsβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ module.exports = {
3737
{
3838
name: 'Components',
3939
components: () => [
40+
path.resolve(__dirname, 'src/Alert.js'),
4041
path.resolve(__dirname, 'src/Box.js'),
4142
path.resolve(__dirname, 'src/Button.js'),
4243
path.resolve(__dirname, 'src/Checkbox.js'),

0 commit comments

Comments
Β (0)