diff --git a/package.json b/package.json index 0685b5d99..cf3695278 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fannypack", - "version": "2.18.0", + "version": "2.18.2", "description": "An accessible, composable, and friendly React UI Kit", "main": "lib/index.js", "module": "es/index.js", diff --git a/src/Dialog/Dialog.js b/src/Dialog/Dialog.js index 734f15aed..94f787be2 100644 --- a/src/Dialog/Dialog.js +++ b/src/Dialog/Dialog.js @@ -1,43 +1,62 @@ // @flow import React, { type Element, type Node } from 'react'; -import Heading from '../Heading'; import _Dialog from './styled'; import DialogContent from './DialogContent'; import DialogHeader from './DialogHeader'; import DialogFooter from './DialogFooter'; +import DialogTitle from './DialogTitle'; +import DialogClose from './DialogClose'; type Props = { - border: true | 'shadow', + a11yDescriptionId?: string, + a11yTitleId?: string, + border?: true | 'shadow', children: Node, className?: string, footer?: string | Element, + onClickClose?: Function, + showCloseButton?: boolean, title?: string | Element }; -const Dialog = ({ border, children, footer, title, ...props }: Props) => ( - <_Dialog border={border} {...props}> - {typeof title === 'string' ? ( +const Dialog = ({ + a11yDescriptionId, + a11yTitleId, + border, + children, + footer, + onClickClose, + showCloseButton, + title, + ...props +}: Props) => ( + <_Dialog aria-describedby={a11yDescriptionId} aria-labelledby={a11yTitleId} role="dialog" border={border} {...props}> + {title && ( - - {title} - + {typeof title === 'string' ? {title} : title} + {showCloseButton && } - ) : ( - title )} - {children} + {children} {footer && {footer}} ); -Dialog.Content = DialogContent; Dialog.Header = DialogHeader; +Dialog.Content = DialogContent; +Dialog.Footer = DialogFooter; +Dialog.Title = DialogTitle; +Dialog.Close = DialogClose; Dialog.defaultProps = { + a11yDescriptionId: undefined, + a11yTitleId: undefined, border: true, className: undefined, footer: undefined, + onClickClose: undefined, + showCloseButton: false, title: undefined }; diff --git a/src/Dialog/Dialog.mdx b/src/Dialog/Dialog.mdx index f341e4679..5486686cd 100644 --- a/src/Dialog/Dialog.mdx +++ b/src/Dialog/Dialog.mdx @@ -21,19 +21,48 @@ import Dialog from './index'; ## Basic Usage - + + + This is a title + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue, + ultrices eget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum consectetur + lectus augue sit amet justo. + + + + +## Footer + +You can render a footer for the dialog using the `footer` prop. + + + }> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue, ultrices eget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum consectetur lectus augue sit amet justo. -## Footer +## Close button -You can render a footer for the dialog using the `footer` prop. +To render a close icon on a dialog, use the `showCloseButton` prop. + + + console.log('close')} showCloseButton title="This is a title" footer={}> + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue, ultrices + eget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum consectetur lectus + augue sit amet justo. + + + +## Accessibility + +It is recommended to add an `a11yTitleId` and `a11yDescriptionId` so that screen readers can read the dialog effectively. - }> + }> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue, ultrices eget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum consectetur lectus augue sit amet justo. @@ -59,6 +88,13 @@ You can render a footer for the dialog using the `footer` prop. }, Footer: { base: string | Object + }, + Title: { + base: string | Object + }, + Close: { + base: string | Object, + hover: string | Object } } ``` diff --git a/src/Dialog/DialogClose.js b/src/Dialog/DialogClose.js new file mode 100644 index 000000000..5ec737e13 --- /dev/null +++ b/src/Dialog/DialogClose.js @@ -0,0 +1,21 @@ +// @flow +import React from 'react'; + +import Icon from '../Icon'; +import { DialogClose as _DialogClose } from './styled'; + +type Props = { + className?: string +}; + +const DialogClose = ({ children, ...props }: Props) => ( + <_DialogClose kind="link" {...props}> + + +); + +DialogClose.defaultProps = { + className: undefined +}; + +export default DialogClose; diff --git a/src/Dialog/DialogTitle.js b/src/Dialog/DialogTitle.js new file mode 100644 index 000000000..baf24cd2d --- /dev/null +++ b/src/Dialog/DialogTitle.js @@ -0,0 +1,21 @@ +// @flow +import React, { type Node } from 'react'; + +import { DialogTitle as _DialogTitle } from './styled'; + +type Props = { + children: Node, + className?: string +}; + +const DialogTitle = ({ children, ...props }: Props) => ( + <_DialogTitle as="h5" isSubHeading {...props}> + {children} + +); + +DialogTitle.defaultProps = { + className: undefined +}; + +export default DialogTitle; diff --git a/src/Dialog/__tests__/Dialog.test.js b/src/Dialog/__tests__/Dialog.test.js index 04a639070..9e99db0c7 100644 --- a/src/Dialog/__tests__/Dialog.test.js +++ b/src/Dialog/__tests__/Dialog.test.js @@ -5,10 +5,15 @@ import 'jest-styled-components'; it('renders correctly for a default dialog', () => { const { container } = render( - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue, - ultrices eget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum consectetur - lectus augue sit amet justo. + + + This is a title + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue, + ultrices eget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum + consectetur lectus augue sit amet justo. + ); expect(container.firstChild).toMatchSnapshot(); @@ -16,7 +21,24 @@ it('renders correctly for a default dialog', () => { it('renders correctly for a dialog with a footer', () => { const { container } = render( - test}> + + + This is a title + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue, + ultrices eget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum + consectetur lectus augue sit amet justo. + + test + + ); + expect(container.firstChild).toMatchSnapshot(); +}); + +it('renders correctly for a dialog with a close button', () => { + const { container } = render( + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse diam ipsum, cursus id placerat congue, ultrices eget lectus. Duis posuere, lacus sed tristique commodo, sapien turpis mollis nunc, vestibulum consectetur lectus augue sit amet justo. diff --git a/src/Dialog/__tests__/__snapshots__/Dialog.test.js.snap b/src/Dialog/__tests__/__snapshots__/Dialog.test.js.snap index f6258d65e..b6daf1fb4 100644 --- a/src/Dialog/__tests__/__snapshots__/Dialog.test.js.snap +++ b/src/Dialog/__tests__/__snapshots__/Dialog.test.js.snap @@ -39,45 +39,45 @@ exports[`renders correctly for a default dialog 1`] = ` outline-offset: 2px; } -.c5 { +.c7 { font-weight: 700; line-height: 1.2; margin-bottom: 1rem; } -.heading.c5 + .sub-heading { +.heading.c7 + .sub-heading { margin-top: -1rem; } -.c5:last-child { +.c7:last-child { margin-bottom: 0; } -h1.c5 { +h1.c7 { font-size: 3rem; } -h2.c5 { +h2.c7 { font-size: 2.5rem; } -h3.c5 { +h3.c7 { font-size: 2rem; } -h4.c5 { +h4.c7 { font-size: 1.5rem; } -h5.c5 { +h5.c7 { font-size: 1.25rem; } -h6.c5 { +h6.c7 { font-size: 1rem; } -.c5 { +.c7 { font-weight: 600; } @@ -93,48 +93,327 @@ h6.c5 { border: 1px solid #e6e6e6; } +.c4 { + padding: 1.25rem; + max-height: 50vh; + overflow-y: scroll; +} + +.c5 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + border-bottom: 1px solid #e6e6e6; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; + padding: 1.25rem; + width: 100%; +} + .c6 { + margin-bottom: 0px; +} + +.c2 { + border-radius: 5px; +} + +@media (max-width:480px) { + h1.c7 { + font-size: 2rem; + } +} + +@media (max-width:480px) { + h2.c7 { + font-size: 1.8rem; + } +} + +@media (max-width:480px) { + h3.c7 { + font-size: 1.6rem; + } +} + +@media (max-width:480px) { + h4.c7 { + font-size: 1.4rem; + } +} + +@media (max-width:480px) { + h5.c7 { + font-size: 1.2rem; + } +} + +
+ +
+`; + +exports[`renders correctly for a dialog with a close button 1`] = ` +.c1 { + margin: unset; + padding: unset; + border: unset; + background: unset; + font: unset; + font-family: inherit; + font-size: 100%; + box-sizing: border-box; + background-color: unset; + color: inherit; +} + +.c9 { + margin: unset; + padding: unset; + border: unset; + background: unset; + font: unset; + font-family: inherit; + font-size: 100%; + box-sizing: border-box; + background-color: #fcfcfc; + color: inherit; +} + +.c0 { + box-sizing: border-box; + font-family: system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Fira Sans', 'Droid Sans','Helvetica Neue',sans-serif; + font-size: 16px; + font-weight: 400; + line-height: 1.5; + margin: 0; + padding: 0; + overflow-x: hidden; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + color: #435a6f; +} + +.c0 *, +.c0 *::before, +.c0 *::after { + box-sizing: inherit; +} + +.c0 *:focus { + outline: 2px solid #7467c0; + outline-offset: 2px; +} + +.c8 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + background-color: #fcfcfc; + border: 1px solid #bfbfbf; + border-radius: 4px; + color: #435a6f; + cursor: pointer; + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + font-weight: 600; + height: 2.5em; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + padding: 0 0.8rem; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c8:focus { + outline: unset; + z-index: 2; + box-shadow: #7467c0 0px 0px 0px 2px; +} + +.c8[disabled] { + cursor: not-allowed; + opacity: 0.7; + outline: unset; + pointer-events: unset; +} + +.c8 { + border: 0; + background: unset; + color: #435a6f; + -webkit-text-decoration: underline; + text-decoration: underline; +} + +.c8:hover { + color: #000; +} + +.c6 { + font-weight: 700; + line-height: 1.2; + margin-bottom: 1rem; +} + +.heading.c6 + .sub-heading { + margin-top: -1rem; +} + +.c6:last-child { + margin-bottom: 0; +} + +h1.c6 { + font-size: 3rem; +} + +h2.c6 { + font-size: 2.5rem; +} + +h3.c6 { + font-size: 2rem; +} + +h4.c6 { + font-size: 1.5rem; +} + +h5.c6 { + font-size: 1.25rem; +} + +h6.c6 { + font-size: 1rem; +} + +.c6 { + font-weight: 600; +} + +.c3 { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + border-radius: 3px; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + border: 1px solid #e6e6e6; +} + +.c11 { padding: 1.25rem; max-height: 50vh; overflow-y: scroll; } .c4 { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; border-bottom: 1px solid #e6e6e6; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; padding: 1.25rem; width: 100%; } +.c5 { + margin-bottom: 0px; +} + +.c7 { + height: 2em; + width: 2em; + padding: 0px; +} + +.c7:hover { + background-color: #f2f2f2; +} + .c2 { border-radius: 5px; } +.c10 { + fill: #435a6f; + position: relative; + top: 0.1em; +} + @media (max-width:480px) { - h1.c5 { + h1.c6 { font-size: 2rem; } } @media (max-width:480px) { - h2.c5 { + h2.c6 { font-size: 1.8rem; } } @media (max-width:480px) { - h3.c5 { + h3.c6 { font-size: 1.6rem; } } @media (max-width:480px) { - h4.c5 { + h4.c6 { font-size: 1.4rem; } } @media (max-width:480px) { - h5.c5 { + h5.c6 { font-size: 1.2rem; } } @@ -144,18 +423,40 @@ h6.c5 { >