From f7320ad8d0dd7cae7622ff970389984fe9ed4956 Mon Sep 17 00:00:00 2001 From: Alexandru Munteanu <alexandru.munt@gmail.com> Date: Tue, 14 Aug 2018 14:49:26 +0300 Subject: [PATCH] feat(styleguide): add modal components --- .../component-faraday-ui/src/IconButton.js | 18 ++++- .../src/modals/MultiAction.js | 81 +++++++++++++++++++ .../src/modals/MultiAction.md | 43 ++++++++++ .../src/modals/SingleActionModal.js | 62 ++++++++++++++ .../src/modals/SingleActionModal.md | 19 +++++ packages/styleguide/styleguide.config.js | 4 + 6 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 packages/component-faraday-ui/src/modals/MultiAction.js create mode 100644 packages/component-faraday-ui/src/modals/MultiAction.md create mode 100644 packages/component-faraday-ui/src/modals/SingleActionModal.js create mode 100644 packages/component-faraday-ui/src/modals/SingleActionModal.md diff --git a/packages/component-faraday-ui/src/IconButton.js b/packages/component-faraday-ui/src/IconButton.js index a2eb570ce..b426dc6ce 100644 --- a/packages/component-faraday-ui/src/IconButton.js +++ b/packages/component-faraday-ui/src/IconButton.js @@ -1,8 +1,20 @@ import React from 'react' +import { has, get } from 'lodash' import { Icon } from '@pubsweet/ui' -import styled from 'styled-components' +import styled, { css } from 'styled-components' import { th } from '@pubsweet/ui-toolkit' +const positionHelper = css` + position: ${props => + has(props, 'top', 'bottom', 'left', 'right') ? 'absolute' : 'initial'}; + top: ${props => (has(props, 'top') ? `${get(props, 'top')}px` : 'unset')}; + bottom: ${props => + has(props, 'bottom') ? `${get(props, 'bottom')}px` : 'unset'}; + left: ${props => (has(props, 'left') ? `${get(props, 'left')}px` : 'unset')}; + right: ${props => + has(props, 'right') ? `${get(props, 'right')}px` : 'unset'}; +` + const IconButton = styled.div` align-items: center; cursor: pointer; @@ -12,10 +24,12 @@ const IconButton = styled.div` &:hover { opacity: 0.7; } + + ${positionHelper}; ` export default ({ icon, onClick, iconSize = 3, ...props }) => ( - <IconButton onClick={onClick}> + <IconButton onClick={onClick} {...props}> <Icon size={iconSize} {...props}> {icon} </Icon> diff --git a/packages/component-faraday-ui/src/modals/MultiAction.js b/packages/component-faraday-ui/src/modals/MultiAction.js new file mode 100644 index 000000000..c87877c52 --- /dev/null +++ b/packages/component-faraday-ui/src/modals/MultiAction.js @@ -0,0 +1,81 @@ +import React, { Fragment } from 'react' +import styled from 'styled-components' +import { th } from '@pubsweet/ui-toolkit' +import { H2, Button, Spinner } from '@pubsweet/ui' +import { compose, setDisplayName, withHandlers } from 'recompose' + +import Text from '../Text' +import IconButton from '../IconButton' + +const MultiAction = ({ + title, + content, + onClose, + subtitle, + onConfirm, + modalError, + isFetching, + confirmText = 'OK', + cancelText = 'Cancel', +}) => ( + <Root> + <IconButton icon="x" onClick={onClose} right={5} secondary top={5} /> + <H2>{title}</H2> + {subtitle && <Text secondary>{subtitle}</Text>} + <Text dangerouslySetInnerHTML={{ __html: content }} /> + <Buttons isFetching={isFetching}> + {isFetching ? ( + <Spinner size={3} /> + ) : ( + <Fragment> + <Button onClick={onClose}>{cancelText}</Button> + <Button onClick={onConfirm} primary> + {confirmText} + </Button> + </Fragment> + )} + </Buttons> + </Root> +) + +export default compose( + withHandlers({ + onClose: ({ onCancel, hideModal }) => () => { + if (onCancel && typeof onCancel === 'function') { + onCancel() + } else { + hideModal() + } + }, + }), + setDisplayName('MultiActionModal'), +)(MultiAction) + +// #region styles +const Root = styled.div` + align-items: center; + border: ${th('borderWidth')} ${th('borderStyle')} transparent; + border-radius: ${th('borderRadius')}; + box-shadow: ${th('boxShadow')}; + display: flex; + flex-direction: column; + position: relative; + padding: calc(${th('gridUnit')} * 5); + width: calc(${th('gridUnit')} * 60); + + ${H2} { + margin: 0 0 ${th('gridUnit')} 0; + } + + ${Text} { + margin-bottom: ${th('gridUnit')}; + } +` + +const Buttons = styled.div` + display: flex; + justify-content: ${props => (props.isFetching ? 'center' : 'space-between')}; + margin-top: calc(${th('gridUnit')} * 3); + width: 60%; +` +// #endregion diff --git a/packages/component-faraday-ui/src/modals/MultiAction.md b/packages/component-faraday-ui/src/modals/MultiAction.md new file mode 100644 index 000000000..e0b142ede --- /dev/null +++ b/packages/component-faraday-ui/src/modals/MultiAction.md @@ -0,0 +1,43 @@ +A multi action modal. + +```js +<MultiAction + title="Ready to Submit your Report?" + subtitle="Once submited, the report can’t be modified." + confirmText="SUBMIT REPORT" + cancelText="NOT YET" + onCancel={() => console.log('i am canceling')} + onConfirm={() => console.log('i am confirming')} +/> +``` + +A multi action modal with content. + +```js +const content = `<h3>What is Lorem Ipsum?</h3> +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.`; + +<MultiAction + title="Ready to Rumble?" + subtitle="Once rumbling, you can never stop." + confirmText="SUBMIT REPORT" + cancelText="NOT YET" + content={content} + onCancel={() => console.log('i am canceling')} + onConfirm={() => console.log('i am confirming')} +/> +``` + +A multi action modal with pending API request. + +```js +<MultiAction + title="Ready to Rumble?" + subtitle="Once submited, the report can’t be modified." + confirmText="SUBMIT REPORT" + cancelText="NOT YET" + isFetching + onCancel={() => console.log('i am canceling')} + onConfirm={() => console.log('i am confirming')} +/> +``` diff --git a/packages/component-faraday-ui/src/modals/SingleActionModal.js b/packages/component-faraday-ui/src/modals/SingleActionModal.js new file mode 100644 index 000000000..5a68c7963 --- /dev/null +++ b/packages/component-faraday-ui/src/modals/SingleActionModal.js @@ -0,0 +1,62 @@ +import React from 'react' +import styled from 'styled-components' +import { th } from '@pubsweet/ui-toolkit' +import { Button, Icon, H2 } from '@pubsweet/ui' +import { compose, setDisplayName, withHandlers } from 'recompose' + +import Text from '../Text' +import IconButton from '../IconButton' + +const SingleActionModal = ({ + error, + title, + content, + onClick, + subtitle, + confirmText = 'OK', +}) => ( + <Root> + <IconButton icon="x" onClick={onClick} right={5} secondary top={5} /> + <Icon error={error} primary={!error} size={6}> + {error ? 'x-circle' : 'check-circle'} + </Icon> + {title && <H2>{title}</H2>} + {subtitle && <Text secondary>{subtitle}</Text>} + <Button onClick={onClick} primary> + {confirmText} + </Button> + </Root> +) + +export default compose( + withHandlers({ + onClick: ({ onCancel, onConfirm }) => onCancel || onConfirm, + }), + setDisplayName('SingleActionModal'), +)(SingleActionModal) + +// #region styles +const Root = styled.div` + align-items: center; + border: ${th('borderWidth')} ${th('borderStyle')} transparent; + border-radius: ${th('borderRadius')}; + box-shadow: ${th('boxShadow')}; + display: flex; + flex-direction: column; + position: relative; + padding: calc(${th('gridUnit')} * 5); + width: calc(${th('gridUnit')} * 40); + + ${H2} { + margin: calc(${th('gridUnit')} * 2) 0; + } + + ${Text} { + margin-bottom: ${th('gridUnit')}; + } + + ${Button} { + margin-top: ${th('gridUnit')}; + } +` +// #endregion diff --git a/packages/component-faraday-ui/src/modals/SingleActionModal.md b/packages/component-faraday-ui/src/modals/SingleActionModal.md new file mode 100644 index 000000000..62123d1e6 --- /dev/null +++ b/packages/component-faraday-ui/src/modals/SingleActionModal.md @@ -0,0 +1,19 @@ +A success modal. + +```js +<SingleActionModal + title="Report submitted" + onConfirm={() => console.log('confirma')} +/> +``` + +An error modal. + +```js +<SingleActionModal + error + title="Error submitting report" + subtitle="Please try again later." + onConfirm={() => console.log('confirma')} +/> +``` diff --git a/packages/styleguide/styleguide.config.js b/packages/styleguide/styleguide.config.js index db2e28491..9d38e49c4 100644 --- a/packages/styleguide/styleguide.config.js +++ b/packages/styleguide/styleguide.config.js @@ -6,6 +6,10 @@ module.exports = { name: 'Hinadwi UI', components: ['../component-faraday-ui/src/*.js'], }, + { + name: 'Modals', + components: ['../component-faraday-ui/src/modals/*.js'], + }, { name: 'Grid Items', components: ['../component-faraday-ui/src/gridItems/*.js'], -- GitLab