diff --git a/packages/component-faraday-ui/src/IconButton.js b/packages/component-faraday-ui/src/IconButton.js index a2eb570ceeda1fcc72f37aae78142fc946630505..b426dc6ce44b81f0c46a6b7dc170cc7c3b01d704 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 0000000000000000000000000000000000000000..c87877c520b2a95b911b9744a9d6334873f275ea --- /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 0000000000000000000000000000000000000000..e0b142ede25948175a77a421142917dfb6893dfd --- /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 0000000000000000000000000000000000000000..5a68c79632b4548b78e00aecdd95f4ab43e6418f --- /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 0000000000000000000000000000000000000000..62123d1e6ad72396fbcbcb99664264576238a9b7 --- /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 db2e284914e457c3b79a63c958c409c3b819e9de..9d38e49c48d10b34138250998e70f8d2f0d7756b 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'],