diff --git a/.storybook/main.js b/.storybook/main.js index 86e57839..be0855ad 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -5,6 +5,7 @@ module.exports = { addons: ['@storybook/addon-links', '@storybook/addon-essentials'], typescript: { check: false, // type-check stories during Storybook build + reactDocgen: false, }, webpackFinal: async (config) => { // allow __DEV__ macro to be used diff --git a/src/Alert/Alert.stories.tsx b/src/Alert/Alert.stories.tsx index 0f0bf9c9..ffaa3df6 100644 --- a/src/Alert/Alert.stories.tsx +++ b/src/Alert/Alert.stories.tsx @@ -1,11 +1,42 @@ import React from 'react'; -import { Alert } from '../Alert'; +import { Alert, AlertActions, AlertProps } from '../Alert'; import Button from '../Button'; -import { Close } from '../Icon/baseIcons'; import { defaultIcons, defaultTheme, ThemeProvider } from '..'; import { filteredArgs } from '../utils'; +const ALERT_BUTTONS_EXAMPLE: AlertActions = [ + { + buttonText: 'View Status', + }, + { + buttonText: 'Dismiss', + }, +]; + +const ALERT_EXAMPLE: Array = [ + { + status: 'error', + title: 'Error', + children: 'Something not great is happening.', + }, + { + status: 'success', + title: 'Success', + children: 'Something great is happening!', + }, + { + status: 'warning', + title: 'Warning', + children: `Something is happening that isn't bad yet, but might be soon.`, + }, + { + status: 'info', + title: 'Info', + children: 'Something is happening and you should know about it.', + }, +]; + export default { title: 'Alert', component: Alert, @@ -21,21 +52,25 @@ const Provider = props => ( export const Statuses = () => { return ( - - Something not great is happening. - -
- - Something great is happening! - -
- - Something is happening that isn't bad yet, but might be soon. - -
- - Something is happening and you should know about it. - + {ALERT_EXAMPLE.map((alert, index, array) => ( + <> + + {index + 1 < array.length &&
} + + ))} +
+ ); +}; + +export const WithActionButtons = () => { + return ( + + ); }; @@ -47,19 +82,33 @@ export const Hidden = () => { {open && ( - - Something not great is happening! - - + setOpen(false)} + /> + )} + + ); +}; + +export const HiddenWithTextButton = () => { + const [open, setOpen] = React.useState(false); + + return ( + + + {open && ( + setOpen(false)} + buttonText="Dismiss" + /> )} ); @@ -69,6 +118,9 @@ export const Custom = () => (
- Here is some information. +
); diff --git a/src/Alert/index.tsx b/src/Alert/index.tsx index ce09dfa1..a91b1ab7 100644 --- a/src/Alert/index.tsx +++ b/src/Alert/index.tsx @@ -1,45 +1,111 @@ -import React from 'react'; +import React, { useCallback, useMemo } from 'react'; import styled from 'styled-components'; -import { MinervaProps, systemProps, Flex } from '../layout'; + import Icon from '../Icon'; -// import Button from '../Button'; import Text from '../Text'; +import Button from '../Button'; import { forwardRefWithAs } from '../type-utilities'; +import { MinervaProps, systemProps, Flex } from '../layout'; + +const CloseIcon = () => ( + + + +); export const StyledAlert = styled(Flex)( { - padding: '16px', + padding: '20px', borderRadius: '5px', alignItems: 'center', - // justifyContent: 'space-between', + justifyContent: 'space-between', + flexDirection: 'row', }, systemProps ); +export const StyledAlertInnerContainer = styled(Flex)` + display: flex; + flex-direction: column; + margin-bottom: -12px; +`; + +export const StyledAlertTitleContainer = styled(Flex)` + margin-bottom: 12px; +`; + export const StyledAlertTitle = styled(Text)( { - fontWeight: 'bold', - marginRight: '5px', + fontWeight: '700', + lineHeight: '17.5px', }, systemProps ); -export const StyledAlertDescription = styled(Text)``; +export const StyledAlertContentContainer = styled(Flex)` + display: flex; + flex-direction: column; + justify-content: 'flex-start'; + font-weigth: 400; + font-size: 10px; + line-height: 12.5px; + margin-bottom: 12px; +`; + +export const StyledAlertActionsContainer = styled(Flex)` + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-content: center; + justify-content: 'flex-start'; + margin: 0px -10px; + margin-bottom: 12px; +`; + +export const StyledAlertButton = styled(Flex)` + margin: 0 10px; +`; + +export const StyledAlertContent = styled(Flex)` + margin-bottom: 12px; +`; export const StyledCloseText = styled(Text)` text-decoration: underline; `; -export const StyledAlertInner = styled(Flex)``; - export const StyledAlertIconSection = styled(Flex)` justify-content: flex-start; `; -export interface AlertProps extends MinervaProps { +type Status = 'error' | 'success' | 'warning' | 'info'; + +export interface AlertButton { + buttonAction?: Function; + buttonText?: string; + children?: React.ReactNode; +} + +export interface StatusInfo { + statusColor: string; + statusIcon: string | null; +} + +export interface AlertProps extends MinervaProps, AlertButton { children?: React.ReactNode; - status?: 'error' | 'success' | 'warning' | 'info'; + status?: Status; title?: string; + actions?: Array; + close?: boolean; bg?: string; icon?: string; // isOpen?: boolean; @@ -50,28 +116,66 @@ export interface AlertProps extends MinervaProps { props?: any; } +export type AlertActions = [AlertButton, AlertButton]; // @TODO: Move these to the theme so they can be customized -const alertTypes = { + +const alertTypes: Record = { error: { - statusColor: '#f8b4b4', + statusColor: 'rgba(255, 205, 210, 0.25)', statusIcon: null, }, success: { - statusColor: '#bcf0da', + statusColor: 'rgba(200, 230, 201, 0.25)', statusIcon: null, }, warning: { - statusColor: '#fdf6b2', + statusColor: 'rgba(255, 236, 179, 0.25)', statusIcon: null, }, info: { - statusColor: '#c3ddfd', + statusColor: 'rgba(187, 222, 251, 0.25)', statusIcon: null, }, }; +const AlertButtonComponent = ({ + buttonAction = () => null, + buttonText, + children, +}: AlertButton) => { + const onClickButton = useCallback((event: any) => buttonAction(event), [ + buttonAction, + ]); + + return useMemo( + () => ( + + ), + [buttonText, onClickButton, children] + ); +}; + export const Alert = forwardRefWithAs(function Alert( - { title, children, status, icon, ...props }: AlertProps, + { + title, + children, + actions, + buttonText, + buttonAction, + close = false, + status, + icon, + ...props + }: AlertProps, ref ) { const { statusColor, statusIcon } = @@ -84,7 +188,6 @@ export const Alert = forwardRefWithAs(function Alert( }; const alertIcon = icon || statusIcon; - return ( (function Alert( fontFamily="body" {...props} > - {alertIcon && } - {title} - {children} + {alertIcon && } + + {title && ( + + {title} + + )} + {children && ( + {children} + )} + {actions && ( + + {actions.map( + ({ buttonAction, buttonText }: AlertButton, index: number) => ( + + + + ) + )} + + )} + + {close && ( + + + + )} ); });