Skip to content
18 changes: 16 additions & 2 deletions docs/content/Flash.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,21 @@ The Flash component informs users of successful or pending actions.
## Default example

```jsx live
<Flash m={4} scheme="green"> Flash green </Flash>
<Flash>Default Flash</Flash>
<Flash variant="success">Success Flash</Flash>
<Flash variant="warning">Warning Flash</Flash>
<Flash variant="danger">Danger Flash</Flash>
```

## With an icon

Flash components with icons inside of them will automatically set the correct color for the icon depending on the type of Flash, as well as applying the correct right margin.

```jsx live
<Flash variant="success">
<StyledOcticon icon={Check}/>
Success!
</Flash>
```

## System props
Expand All @@ -19,4 +33,4 @@ Flash components get `COMMON` system props. Read our [System Props](/system-prop
| Name | Type | Default | Description |
| :- | :- | :-: | :- |
| full | Boolean | | Creates a full width Flash component|
| scheme | String | blue | Can be one of `green`, `yellow`, or `red` - sets the background color, border, and text color of the Flash component
| variant | String | default | Can be one of `default`, `success`, `warning`, or `danger` - sets the background color and border of the Flash component |
4 changes: 4 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ declare module '@primer/components' {

export interface FlashProps extends CommonProps, Omit<React.HTMLAttributes<HTMLDivElement>, 'color'> {
full?: boolean
variant?: 'success' | 'default' | 'warning' | 'danger'
/**
* @deprecated since version 19.0.0
*/
scheme?: string
}

Expand Down
50 changes: 38 additions & 12 deletions src/Flash.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,70 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import {variant} from 'styled-system'
import {COMMON, get} from './constants'
import theme from './theme'
import sx from './sx'
import deprecate from './utils/deprecate'

const schemeMap = {
green: {color: 'colors.green.8', bg: 'colors.green.1'},
red: {color: 'colors.red.9', bg: 'colors.red.1'},
yellow: {color: 'colors.yellow.9', bg: 'colors.yellow.1'},
base: {color: 'colors.blue.8', bg: 'colors.blue.1'}
red: 'danger',
blue: 'default',
yellow: 'warning',
green: 'success'
}

const Flash = styled.div`
const variants = variant({
scale: 'flash'
})

const getIconColor = (variant, theme) => get(`flashIcon.${variant}`)(theme)

const StyledFlash = styled.div`
position: relative;
color: ${get('colors.text.grayDark')};
padding: ${get('space.3')};
color: ${props => get(schemeMap[props.scheme] ? schemeMap[props.scheme].color : '')};
background-color: ${props => get(schemeMap[props.scheme] ? schemeMap[props.scheme].bg : '')};
border-color: ${get('colors.blackfade15')};
border-style: solid;
border-width: ${props => (props.full ? '1px 0px' : '1px')};
border-radius: ${props => (props.full ? '0' : '3px')};
border-radius: ${props => (props.full ? '0' : get('radii.2'))};
margin-top: ${props => (props.full ? '-1px' : '0')};

p:last-child {
margin-bottom: 0;
}

svg {
color: ${props => getIconColor(props.variant, props.theme)};
margin-right: ${get('space.2')};
}

${COMMON};
${variants}
${sx};
`

const Flash = ({variant, scheme, ...props}) => {
if (scheme) {
deprecate({
name: 'The scheme prop',
version: '20.0.0',
message: 'Use the variant prop instead. See https://primer.style/components/Flash for more details.'
})
variant = schemeMap[scheme]
} // deprecate 20.0.0
return <StyledFlash variant={variant} {...props} />
}

Flash.defaultProps = {
theme,
scheme: 'base'
variant: 'default'
}

Flash.propTypes = {
children: PropTypes.node,
full: PropTypes.bool,
scheme: PropTypes.oneOf(Object.keys(schemeMap)),
theme: PropTypes.object,
scheme: PropTypes.oneOf(Object.keys(schemeMap)), // deprecate 20.0.0
variant: PropTypes.oneOf(['default', 'warning', 'success', 'danger']),
...COMMON.propTypes,
...sx.propTypes
}
Expand Down
11 changes: 6 additions & 5 deletions src/__tests__/Flash.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('Flash', () => {
behavesAsComponent(Flash, [COMMON])

it('should have no axe violations', async () => {
const {container} = HTMLRender(<Flash scheme="yellow" theme={theme} />)
const {container} = HTMLRender(<Flash variant="warning" theme={theme} />)
const results = await axe(container)
expect(results).toHaveNoViolations()
cleanup()
Expand All @@ -24,9 +24,10 @@ describe('Flash', () => {
expect(render(<Flash full />)).toHaveStyleRule('border-width', '1px 0px')
})

it('respects the "scheme" prop', () => {
expect(render(<Flash scheme="yellow" theme={theme} />)).toHaveStyleRule('color', colors.yellow[9])
expect(render(<Flash scheme="red" theme={theme} />)).toHaveStyleRule('color', colors.red[9])
expect(render(<Flash scheme="green" theme={theme} />)).toHaveStyleRule('color', colors.green[8])
it('respects the "variant" prop', () => {
expect(render(<Flash variant="warning" theme={theme} />)).toHaveStyleRule('background-color', colors.yellow[1])
expect(render(<Flash variant="danger" theme={theme} />)).toHaveStyleRule('background-color', '#FFE3E6')
expect(render(<Flash variant="success" theme={theme} />)).toHaveStyleRule('background-color', colors.green[1])
expect(render(<Flash theme={theme} />)).toHaveStyleRule('background-color', colors.blue[1])
})
})
13 changes: 9 additions & 4 deletions src/__tests__/__snapshots__/Flash.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@
exports[`Flash renders consistently 1`] = `
.c0 {
position: relative;
color: #24292e;
padding: 16px;
color: #032f62;
background-color: #dbedff;
border-color: rgba(27,31,35,0.15);
border-style: solid;
border-width: 1px;
border-radius: 3px;
border-radius: 6px;
margin-top: 0;
background-color: #dbedff;
border-color: rgba(4,66,137,0.2);
}

.c0 p:last-child {
margin-bottom: 0;
}

.c0 svg {
color: rgba(4,66,137,0.6);
margin-right: 8px;
}

<div
className="c0"
/>
Expand Down
31 changes: 30 additions & 1 deletion src/theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,33 @@ const buttons = {
}
}

const flash = {
default: {
backgroundColor: blue[1],
borderColor: 'rgba(4, 66, 137, 0.2)'
},
success: {
backgroundColor: green[1],
borderColor: 'rgba(23, 111, 44, 0.2)'
},
danger: {
backgroundColor: '#FFE3E6',
borderColor: 'rgba(158, 28, 35, 0.2)'
},
warning: {
backgroundColor: yellow[1],
borderColor: 'rgba(176, 136, 0, 0.2)'
}
}

// this has to be separated from the flash object since we have to use an svg selector to style the icon color
const flashIcon = {
default: 'rgba(4, 66, 137, 0.6)',
success: 'rgba(23, 111, 44, 0.8)',
danger: 'rgba(158, 28, 35, 0.6)',
warning: yellow[8]
}

const popovers = {
colors: {
caret: 'rgba(27, 31, 35, 0.15)'
Expand Down Expand Up @@ -293,7 +320,9 @@ const theme = {
// Components
buttons,
pagination,
popovers
popovers,
flash,
flashIcon
}

export default theme
Expand Down
5 changes: 5 additions & 0 deletions src/utils/deprecate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* eslint-disable no-console */

export default function deprecate({name, message, version}) {
console.warn(`WARNING! ${name} is deprecated and will be removed in version ${version}. ${message}`)
}