Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alerts + Icons + Badges #105

Merged
merged 9 commits into from
Apr 10, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion client/.babelrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
{
"presets": ["next/babel"],
"plugins": [
"inline-react-svg",
[
"inline-react-svg",
{
"svgo": {
"plugins": [
{
"cleanupIDs": {
"minify": false
}
}
]
}
}
],
[
"styled-components",
{
Expand Down
177 changes: 177 additions & 0 deletions client/src/components/Alert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import React from 'react'
import { Box, Button, Text } from 'grommet'
import styled from 'styled-components'

import Info from '../images/info-white.svg'
import Warning from '../images/warning-white.svg'
import Check from '../images/check-white.svg'
import Cross from '../images/cross-white.svg'

const types = {
info: {
Icon: Info,
background: 'brand',
multipleBackground: 'turteal-shade-20',
color: 'white'
},
error: {
Icon: Warning,
background: 'error',
multipleBackground: 'error-shade-20',
color: 'white'
},
success: {
Icon: Check,
background: 'success',
multipleBackground: 'success-shade-20',
color: 'white'
}
}

const AlertsContext = React.createContext({ alerts: {} })
Copy link
Contributor

@arielsvn arielsvn Apr 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't necessary to use AlertsContext.Provider?


export const useAlerts = (queue = 'main') => {
const context = React.useContext(AlertsContext)

const [alerts, setAlerts] = React.useState(context.alerts)

if (!alerts[queue]) alerts[queue] = []

const addAlert = (message, type = 'info') => {
context.alerts[queue].push({
time: Date.now(),
message,
type
})
setAlerts({ ...context.alerts })
}

const removeAlert = (alertToRemove) => {
const newAlerts = context.alerts[queue].filter((a) => {
return a.time !== alertToRemove.time
})
context.alerts[queue] = newAlerts
setAlerts({ ...context.alerts })
}

const clearAlerts = () => {
context.alerts[queue] = []
setAlerts({ ...context.alerts })
}

const AlertsQueue = ({ lifo = true }) => (
<Alerts
lifo={lifo}
alerts={context.alerts[queue]}
clearAlerts={clearAlerts}
removeAlert={removeAlert}
/>
)

return {
alerts: context.alerts,
addAlert,
clearAlerts,
removeAlert,
Alerts: AlertsQueue
}
}

const CloseButton = styled(Button)`
text-align: right;
padding-right: 16px;
`

export const Alert = ({
type = 'info',
message = '',
height = '56px',
onRemove
}) => {
const { background, color, Icon } = types[type]

return (
<Box direction="row">
<Box
direction="row"
width="full"
height={height}
background={background}
justify="center"
pad={{ left: height }}
>
<Box direction="row" align="center">
{Icon && (
<Box alignContents="center" margin={{ right: '8px' }}>
<Icon />
</Box>
)}
<Box>
<Text color={color}>{message}</Text>
</Box>
</Box>
</Box>
<Box background={background} width={{ min: height }} height={height}>
<CloseButton fill plain icon={<Cross />} onClick={onRemove} />
</Box>
</Box>
)
}

const MultipleAlerts = ({ alert, alerts, clearAlerts }) => {
const { multipleBackground, color } = types[alert.type]
return (
<Box direction="row">
<Box
direction="row"
width="full"
height="40px"
background={multipleBackground}
justify="center"
>
<Box direction="row" align="center" pad={{ left: '80px' }}>
<Text color={color}>{alerts.length} Alerts</Text>
</Box>
</Box>
<Box
direction="row"
background={multipleBackground}
width={{ min: '80px' }}
pad={{ right: '16px' }}
height="40px"
justify="end"
>
<Button plain label="clear all" onClick={clearAlerts} />
</Box>
</Box>
)
}

export const Alerts = ({ lifo = true, alerts, removeAlert, clearAlerts }) => {
if (alerts.length === 0) return <></>

const alert = lifo ? alerts[alerts.length - 1] : alerts[0]

return (
<>
{alerts.length > 1 && (
<MultipleAlerts
alert={alert}
alerts={alerts}
clearAlerts={clearAlerts}
/>
)}
{alerts.length > 0 && (
<Alert
type={alert.type}
message={alert.message}
onRemove={() => {
removeAlert(alert)
}}
/>
)}
</>
)
}

export default Alert
61 changes: 61 additions & 0 deletions client/src/components/Alert.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import * as React from 'react'
import { Grommet, Box, Button } from 'grommet'
import { storiesOf } from '@storybook/react'
import { Alert, useAlerts } from './Alert'
import theme from '../theme'

storiesOf('Alert', module).add('default', () => {
return (
<Grommet theme={theme}>
<Box pad="medium">
<Alert type="info" message="This is information." />
</Box>
<Box pad="medium">
<Alert type="success" message="This worked out well!" />
</Box>
<Box pad="medium">
<Alert type="error" message="This is an error!" />
</Box>
</Grommet>
)
})

storiesOf('Alert', module).add('Alerts', () => {
const { addAlert, Alerts } = useAlerts('demo1')

// This is to demonstate how you can use queues and context
const { addAlert: addAnotherAlert } = useAlerts('demo1')
return (
<Grommet theme={theme}>
<Alerts />
<Box pad="medium" direction="row">
<Button
label="Add Success Alert"
width="50px"
onClick={() => {
addAlert('New Alert!', 'success')
}}
/>
</Box>
<Box pad="medium" direction="row">
<Button
label="Add Error Alert"
width="50px"
onClick={() => {
addAnotherAlert('New Error Alert!', 'error')
}}
/>
</Box>
<Box pad="medium" direction="row">
<Button
label="Add Info Alert"
width="50px"
onClick={() => {
addAnotherAlert('New Info Alert!', 'info')
// or addAnotherAlert('New Info Alert!')
}}
/>
</Box>
</Grommet>
)
})
24 changes: 24 additions & 0 deletions client/src/images/check-green.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions client/src/images/check-white.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions client/src/images/cite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions client/src/images/cross-black-tint-30.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions client/src/images/cross-white.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading