Modals fixes (#16310)
* . * dark * simplify and add stories * update stories and docs * fix
This commit is contained in:
parent
188877a865
commit
c9ef2ac15c
16 changed files with 278 additions and 180 deletions
|
|
@ -1,26 +1,22 @@
|
|||
@import '../config/import';
|
||||
|
||||
.crayons-modal {
|
||||
--modal-max-width: 768px;
|
||||
--modal-body-padding: var(--su-3);
|
||||
--modal-header-padding: var(--su-2) var(--su-2) var(--su-2) var(--su-3);
|
||||
--modal-header-font-size: var(--fs-l);
|
||||
--modal-body-font-size: var(--fs-base);
|
||||
--modal-max-width: 640px;
|
||||
--modal-padding: var(--su-3);
|
||||
--modal-backdrop-pointer-events: none;
|
||||
--modal-border: none;
|
||||
--modal-header-border: 1px solid var(--divider);
|
||||
--modal-header-padding: var(--su-2) var(--su-2) var(--su-2)
|
||||
var(--modal-padding);
|
||||
--modal-alignment: unset;
|
||||
--modal-header-alignment: space-between;
|
||||
|
||||
@media (min-width: $breakpoint-s) {
|
||||
--modal-header-padding: var(--su-2) var(--su-2) var(--su-2) var(--su-4);
|
||||
--modal-body-padding: var(--su-4);
|
||||
--modal-padding: var(--su-4);
|
||||
}
|
||||
|
||||
@media (min-width: $breakpoint-m) {
|
||||
--modal-header-padding: var(--su-3) var(--su-3) var(--su-3) var(--su-6);
|
||||
--modal-body-padding: var(--su-6);
|
||||
--modal-header-font-size: var(--fs-xl);
|
||||
--modal-body-font-size: var(--fs-l);
|
||||
}
|
||||
|
||||
@media (min-width: $breakpoint-l) {
|
||||
--modal-body-padding: var(--su-8);
|
||||
--modal-padding: var(--su-7);
|
||||
}
|
||||
|
||||
position: fixed;
|
||||
|
|
@ -34,82 +30,103 @@
|
|||
z-index: var(--z-modal);
|
||||
pointer-events: none;
|
||||
|
||||
&__overlay {
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
opacity: 0.5;
|
||||
&--bg-dismissible {
|
||||
--modal-backdrop-pointer-events: auto;
|
||||
}
|
||||
|
||||
&--prompt {
|
||||
--modal-header-border: none;
|
||||
--modal-header-padding: var(--modal-padding) var(--su-8) 0
|
||||
var(--modal-padding);
|
||||
--modal-body-margin: 0;
|
||||
|
||||
@media (min-width: $breakpoint-m) {
|
||||
--modal-body-margin: calc((var(--modal-padding) * -1) + var(--su-4));
|
||||
}
|
||||
|
||||
.crayons-modal__dismiss {
|
||||
position: absolute;
|
||||
right: var(--su-2);
|
||||
top: var(--su-2);
|
||||
}
|
||||
}
|
||||
|
||||
&--centered {
|
||||
--modal-header-padding: var(--su-7) var(--su-8) 0 var(--su-8);
|
||||
--modal-alignment: center;
|
||||
--modal-header-alignment: center;
|
||||
}
|
||||
|
||||
&--danger {
|
||||
--modal-border: 4px solid var(--modal-danger-border-color);
|
||||
}
|
||||
|
||||
&__backdrop {
|
||||
background: var(--modal-backdrop);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
pointer-events: auto;
|
||||
|
||||
&.background-clickable {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__box {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
max-width: var(--modal-max-width);
|
||||
background: var(--card-bg);
|
||||
color: var(--card-color);
|
||||
background: var(--modal-bg);
|
||||
z-index: var(--z-elevate);
|
||||
max-height: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
pointer-events: auto;
|
||||
border-radius: var(--radius-large-auto);
|
||||
border: var(--modal-border);
|
||||
text-align: var(--modal-alignment);
|
||||
box-shadow: var(--shadow-2);
|
||||
|
||||
@media (min-width: $breakpoint-s) {
|
||||
background: var(--card-bg);
|
||||
color: var(--card-color);
|
||||
max-height: calc(100% - var(--su-6));
|
||||
height: auto;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
&__header {
|
||||
border-bottom: 1px solid var(--base-a5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: var(--modal-header-border);
|
||||
padding: var(--modal-header-padding);
|
||||
flex-shrink: 0;
|
||||
|
||||
&__title {
|
||||
font-size: var(--modal-header-font-size);
|
||||
}
|
||||
display: flex;
|
||||
justify-content: var(--modal-header-alignment);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__body {
|
||||
font-size: var(--modal-body-font-size);
|
||||
padding: var(--modal-body-padding);
|
||||
padding: var(--modal-padding);
|
||||
margin-top: var(--modal-body-margin);
|
||||
max-height: 100%;
|
||||
overflow-y: auto;
|
||||
grid-auto-rows: min-content;
|
||||
}
|
||||
}
|
||||
|
||||
&--s {
|
||||
&--small {
|
||||
@media (min-width: $breakpoint-s) {
|
||||
--modal-max-width: 480px;
|
||||
--modal-body-padding: var(--su-6);
|
||||
--modal-header-font-size: var(--fs-l);
|
||||
--modal-body-font-size: var(--fs-base);
|
||||
}
|
||||
}
|
||||
|
||||
&--m {
|
||||
&--large {
|
||||
@media (min-width: $breakpoint-m) {
|
||||
--modal-max-width: 640px;
|
||||
--modal-body-padding: var(--su-7);
|
||||
--modal-header-padding: var(--su-3) var(--su-5);
|
||||
--modal-header-font-size: var(--fs-xl);
|
||||
--modal-body-font-size: var(--fs-l);
|
||||
--modal-max-width: 768px;
|
||||
}
|
||||
}
|
||||
|
||||
&--prompt {
|
||||
@media (min-width: $breakpoint-s) {
|
||||
--modal-max-width: 480px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -276,6 +276,14 @@
|
|||
--indicator-info-bg: var(--accent-brand);
|
||||
--indicator-info-color: rgb(var(--white));
|
||||
|
||||
/***********************************************
|
||||
** Modals **************************************
|
||||
***********************************************/
|
||||
|
||||
--modal-bg: rgb(var(--white));
|
||||
--modal-backdrop: rgba(var(--black), 0.6);
|
||||
--modal-danger-border-color: rgb(var(--red-500));
|
||||
|
||||
/***********************************************
|
||||
** Colors **************************************
|
||||
***********************************************/
|
||||
|
|
@ -301,6 +309,9 @@
|
|||
/* Focus */
|
||||
--focus: var(--accent-brand);
|
||||
|
||||
/* Divider */
|
||||
--divider: rgb(var(--grey-200));
|
||||
|
||||
/* Shadows */
|
||||
--shadow-1: 0 10px 15px -3px rgba(var(--black), 0.1),
|
||||
0 4px 6px -2px rgba(var(--black), 0.05), 0 0 0 1px rgba(var(--black), 0.1);
|
||||
|
|
|
|||
|
|
@ -284,6 +284,14 @@
|
|||
--indicator-info-bg: rgb(var(--indigo-700));
|
||||
--indicator-info-color: rgb(var(--indigo-100));
|
||||
|
||||
/***********************************************
|
||||
** Modals **************************************
|
||||
***********************************************/
|
||||
|
||||
--modal-bg: rgb(var(--grey-900));
|
||||
--modal-backdrop: rgba(var(--black), 0.6);
|
||||
--modal-danger-border-color: rgb(var(--red-400));
|
||||
|
||||
/***********************************************
|
||||
** Colors **************************************
|
||||
***********************************************/
|
||||
|
|
@ -308,6 +316,9 @@
|
|||
/* Focus */
|
||||
--focus: var(--accent-brand-lighter);
|
||||
|
||||
/* Divider */
|
||||
--divider: rgb(var(--grey-700));
|
||||
|
||||
/* Shadows */
|
||||
--shadow-1: 0 10px 15px -3px rgba(var(--black), 0.5),
|
||||
0 4px 6px -2px rgba(var(--black), 0.25), inset 0 0 0 1px rgba(var(--white), 0.1);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export const adminModal = function ({
|
|||
rightCustomDataAttr = null,
|
||||
}) {
|
||||
return `
|
||||
<div class="crayons-modal crayons-modal--s">
|
||||
<div class="crayons-modal crayons-modal--small">
|
||||
<div class="crayons-modal__box">
|
||||
<header class="crayons-modal__box__header">
|
||||
<p class="fw-bold fs-l">${title}</p>
|
||||
|
|
|
|||
|
|
@ -1,102 +1,59 @@
|
|||
import { h } from 'preact';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames/bind';
|
||||
import { FocusTrap } from '../../shared/components/focusTrap';
|
||||
import { defaultChildrenPropTypes } from '../../common-prop-types';
|
||||
import { Button } from '@crayons';
|
||||
import { ButtonNew as Button } from '@crayons';
|
||||
import CloseIcon from '@images/x.svg';
|
||||
|
||||
function getAdditionalClassNames({ size, className }) {
|
||||
let additionalClassNames = '';
|
||||
|
||||
if (size && size.length > 0 && size !== 'default') {
|
||||
additionalClassNames += ` crayons-modal--${size}`;
|
||||
}
|
||||
|
||||
if (className && className.length > 0) {
|
||||
additionalClassNames += ` ${className}`;
|
||||
}
|
||||
|
||||
return additionalClassNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* A modal component which can be presented with or without an overlay.
|
||||
* The modal is presented within a focus trap for accessibility purposes - please note that the selector used for the focusTrap must be unique on the given page, otherwise focus may be trapped on the wrong element.
|
||||
*
|
||||
* @param {Object} props
|
||||
* @param {Array} props.children The content to be displayed inside the Modal. Can be provided by composition (see example).
|
||||
* @param {string} props.size The desired modal size ('s', 'm' or 'default')
|
||||
* @param {string} props.className Optional additional classnames to apply to the modal container
|
||||
* @param {string} props.title The title to be displayed in the modal heading. If provided, a title bar with a close button will be displayed.
|
||||
* @param {boolean} props.overlay Whether or not to show a semi-opaque overlay behind the modal
|
||||
* @param {Function} props.onClose Callback for any function to be executed on close button click or Escape
|
||||
* @param {boolean} props.closeOnClickOutside Whether the modal should close if the user clicks outside of it
|
||||
* @param {string} props.focusTrapSelector The CSS selector for where to trap the user's focus. This should be unique to the page in which the modal is presented.
|
||||
*
|
||||
* @example
|
||||
* <Modal
|
||||
overlay={true}
|
||||
title="Example modal title"
|
||||
onClose={cancelAction}
|
||||
size="s"
|
||||
focusTrapSelector="#window-modal"
|
||||
closeOnClickOutside={false}
|
||||
className=".additional-class-name"
|
||||
>
|
||||
<div>
|
||||
<p>Some modal content</p>
|
||||
</div>
|
||||
</Modal>
|
||||
*/
|
||||
export const Modal = ({
|
||||
children,
|
||||
size,
|
||||
className,
|
||||
title,
|
||||
overlay = true,
|
||||
prompt,
|
||||
centered,
|
||||
noBackdrop,
|
||||
backdropDismissible = false,
|
||||
onClose = () => {},
|
||||
closeOnClickOutside = false,
|
||||
focusTrapSelector = '.crayons-modal',
|
||||
focusTrapSelector = '.crayons-modal__box',
|
||||
}) => {
|
||||
const classes = classNames('crayons-modal', {
|
||||
[`crayons-modal--${size}`]: size && size !== 'medium',
|
||||
'crayons-modal--prompt': prompt,
|
||||
'crayons-modal--centered': centered && prompt,
|
||||
'crayons-modal--bg-dismissible': !noBackdrop && backdropDismissible,
|
||||
[className]: className,
|
||||
});
|
||||
|
||||
return (
|
||||
<FocusTrap
|
||||
onDeactivate={onClose}
|
||||
clickOutsideDeactivates={closeOnClickOutside}
|
||||
clickOutsideDeactivates={backdropDismissible}
|
||||
selector={focusTrapSelector}
|
||||
>
|
||||
<div
|
||||
data-testid="modal-container"
|
||||
className={`crayons-modal${getAdditionalClassNames({
|
||||
size,
|
||||
className,
|
||||
})}`}
|
||||
>
|
||||
<div data-testid="modal-container" className={classes}>
|
||||
<div
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label="modal"
|
||||
className="crayons-modal__box"
|
||||
>
|
||||
{title && (
|
||||
<div className="crayons-modal__box__header">
|
||||
<h2>{title}</h2>
|
||||
<Button
|
||||
icon={CloseIcon}
|
||||
variant="ghost"
|
||||
contentType="icon"
|
||||
aria-label="Close"
|
||||
onClick={onClose}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<header className="crayons-modal__box__header">
|
||||
<h2 class="crayons-subtitle-2">{title}</h2>
|
||||
<Button
|
||||
icon={CloseIcon}
|
||||
aria-label="Close"
|
||||
className="crayons-modal__dismiss"
|
||||
onClick={onClose}
|
||||
/>
|
||||
</header>
|
||||
<div className="crayons-modal__box__body">{children}</div>
|
||||
</div>
|
||||
{overlay && (
|
||||
{!noBackdrop && (
|
||||
<div
|
||||
data-testid="modal-overlay"
|
||||
className={`crayons-modal__overlay ${
|
||||
closeOnClickOutside ? 'background-clickable' : ''
|
||||
}`}
|
||||
className="crayons-modal__backdrop"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -106,16 +63,15 @@ export const Modal = ({
|
|||
|
||||
Modal.displayName = 'Modal';
|
||||
|
||||
Modal.defaultProps = {
|
||||
size: 'default',
|
||||
};
|
||||
|
||||
Modal.propTypes = {
|
||||
children: defaultChildrenPropTypes.isRequired,
|
||||
className: PropTypes.string,
|
||||
title: PropTypes.string.isRequired,
|
||||
overlay: PropTypes.bool,
|
||||
backdrop: PropTypes.bool,
|
||||
backdropDismissible: PropTypes.bool,
|
||||
prompt: PropTypes.bool,
|
||||
centered: PropTypes.bool,
|
||||
onClose: PropTypes.func,
|
||||
size: PropTypes.oneOf(['default', 's', 'm']).isRequired,
|
||||
size: PropTypes.oneOf(['small', 'medium', 'large']),
|
||||
focusTrapSelector: PropTypes.string,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,24 +15,49 @@ export default {
|
|||
control: {
|
||||
type: 'select',
|
||||
options: {
|
||||
default: 'default',
|
||||
small: 's',
|
||||
medium: 'm',
|
||||
Small: 'small',
|
||||
'Medium (default)': undefined,
|
||||
Large: 'large',
|
||||
},
|
||||
},
|
||||
description:
|
||||
'There are several sizes available - use appropriate size depending on how much content you need to display inside modal.',
|
||||
table: {
|
||||
defaultValue: { summary: 'default' },
|
||||
},
|
||||
},
|
||||
overlay: {
|
||||
noBackdrop: {
|
||||
description: 'Removes the default backdrop overlay.',
|
||||
table: {
|
||||
defaultValue: { summary: true },
|
||||
},
|
||||
},
|
||||
backdropDismissible: {
|
||||
description:
|
||||
'If `backdrop` is visible you can also make it clickable so clicking it would dismiss the Modal',
|
||||
table: {
|
||||
defaultValue: { summary: false },
|
||||
},
|
||||
},
|
||||
prompt: {
|
||||
description:
|
||||
'Special style for Modals that should be used for short prompts (short messages or confirmations). Prompts can only be used with size `small` (`s`).',
|
||||
table: {
|
||||
defaultValue: { summary: false },
|
||||
},
|
||||
},
|
||||
centered: {
|
||||
description:
|
||||
'In some cases it might be "nicer" to center Modals content. This will only work with `prompt` though.',
|
||||
table: {
|
||||
defaultValue: { summary: false },
|
||||
},
|
||||
},
|
||||
title: {
|
||||
control: {
|
||||
type: 'text',
|
||||
},
|
||||
description: '🤷♂️',
|
||||
table: {
|
||||
defaultValue: { summary: 'Modal title' },
|
||||
},
|
||||
|
|
@ -40,7 +65,7 @@ export default {
|
|||
},
|
||||
};
|
||||
|
||||
export const Default = (args) => {
|
||||
const Template = (args) => {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
|
||||
return (
|
||||
|
|
@ -48,19 +73,77 @@ export const Default = (args) => {
|
|||
<Button onClick={() => setIsModalOpen(true)}>Open modal</Button>
|
||||
{isModalOpen && (
|
||||
<Modal onClose={() => setIsModalOpen(false)} {...args}>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
|
||||
odio est, ultricies vel euismod ut, fringilla quis tellus. Sed at
|
||||
dui mi. Fusce cursus nibh lectus, vitae lobortis orci volutpat quis.{' '}
|
||||
</p>
|
||||
<div class="flex flex-col gap-4">
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Suspendisse odio est, ultricies vel euismod ut, fringilla quis
|
||||
tellus. Sed at dui mi. Fusce cursus nibh lectus, vitae lobortis
|
||||
orci volutpat quis.
|
||||
</p>
|
||||
{!args.prompt && (
|
||||
<p>
|
||||
Sed at dui mi. Fusce cursus nibh lectus, vitae lobortis orci
|
||||
volutpat quis. Lorem ipsum dolor sit amet, consectetur
|
||||
adipiscing elit. Suspendisse odio est, ultricies vel euismod ut,
|
||||
fringilla quis tellus. Sed at dui mi. Fusce cursus nibh lectus,
|
||||
vitae lobortis orci volutpat quis.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</Modal>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
size: 'default',
|
||||
title: 'My modal',
|
||||
overlay: true,
|
||||
size: undefined,
|
||||
title: 'Modal title',
|
||||
noBackdrop: false,
|
||||
backdropDismissible: false,
|
||||
prompt: false,
|
||||
centered: false,
|
||||
};
|
||||
|
||||
export const Prompt = Template.bind({});
|
||||
Prompt.args = {
|
||||
size: undefined,
|
||||
title:
|
||||
'Are you sure you want to remove Paweł Ludwiczak from Design Department?',
|
||||
noBackdrop: false,
|
||||
backdropDismissible: false,
|
||||
prompt: true,
|
||||
centered: false,
|
||||
};
|
||||
|
||||
export const PromptCentered = Template.bind({});
|
||||
PromptCentered.args = {
|
||||
size: undefined,
|
||||
title:
|
||||
'Are you sure you want to remove Paweł Ludwiczak from Design Department?',
|
||||
noBackdrop: false,
|
||||
backdropDismissible: false,
|
||||
prompt: true,
|
||||
centered: true,
|
||||
};
|
||||
|
||||
export const BackdropDismissible = Template.bind({});
|
||||
BackdropDismissible.args = {
|
||||
size: undefined,
|
||||
title: 'Modal title',
|
||||
noBackdrop: false,
|
||||
backdropDismissible: true,
|
||||
prompt: false,
|
||||
centered: false,
|
||||
};
|
||||
|
||||
export const NoBackdrop = Template.bind({});
|
||||
NoBackdrop.args = {
|
||||
size: undefined,
|
||||
title: 'Modal title',
|
||||
noBackdrop: true,
|
||||
backdropDismissible: false,
|
||||
prompt: false,
|
||||
centered: false,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,11 +1,48 @@
|
|||
## Modals
|
||||
# Modals
|
||||
|
||||
Modals should be positioned centered in relation to entire viewport. So relation
|
||||
to its trigger doesn’t really matter.
|
||||
to its trigger doesn't really matter.
|
||||
|
||||
Use your best judgements when choosing the right size.
|
||||
|
||||
### Modal accessibility
|
||||
## Sizes
|
||||
|
||||
We have 3 possible sizes to use:
|
||||
|
||||
- Small - 480px - for displaying small amount of data/text.
|
||||
- Medium - 640px (this is default one) - you will probably want to use this one in most cases.
|
||||
- Large - 768px - use for long and/or complex contnet.
|
||||
|
||||
## Prompts
|
||||
|
||||
Except classic Modals you can also use `prompt` style (prop) to apply _special styling_.
|
||||
It will work best with really short messages or some sort of confirmation prompts, for example:
|
||||
|
||||
> Are you sure you want to remove Ben's account?
|
||||
>
|
||||
> [YES] [NO]
|
||||
|
||||
The "special styling" means it will:
|
||||
|
||||
- always use Small (480px) size,
|
||||
- remove the divider between title and content so it all looks more like a one message.
|
||||
|
||||
### Centered prompt
|
||||
|
||||
Some prompts may visually benefit from centering the content.
|
||||
Leave the decision to designers but keep it mind this is possible with `centered` prop
|
||||
(and it will only work in combination with `prompt`).
|
||||
|
||||
## Backdrop
|
||||
|
||||
By default Modals come with dark backdrop (a layer overlaying underlaying content).
|
||||
It is possible to not show it but it should be used in some very rare scenarios, when underlaying
|
||||
content might still be important as additional context.
|
||||
|
||||
Because of having that backdrop is a "good default", you should use `noBackdrop` prop cerfaully,
|
||||
ideally after consulting with your desinger.
|
||||
|
||||
## Modal accessibility
|
||||
|
||||
The Preact Modal component utilises the `focus-trap` library to ensure that:
|
||||
|
||||
|
|
@ -16,3 +53,7 @@ The Preact Modal component utilises the `focus-trap` library to ensure that:
|
|||
- While the modal is open, focus is trapped inside so that when a user presses
|
||||
the Tab key, interactive items behind the modal are not focused
|
||||
- When the modal is open, pressing the Escape key will close it
|
||||
|
||||
## Design
|
||||
|
||||
<iframe style="border: 1px solid rgba(0, 0, 0, 0.1);" width="100%" height="450" src="https://www.figma.com/embed?embed_host=share&url=https%3A%2F%2Fwww.figma.com%2Ffile%2FgHpwugeu9jFGW4d9u3ReuR%2FCrayons%3Fnode-id%3D456%253A215" allowfullscreen></iframe>
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ it('should close on click outside, if enabled', () => {
|
|||
<Modal
|
||||
title="This is a modal title"
|
||||
onClose={onClose}
|
||||
closeOnClickOutside
|
||||
backdropDismissible
|
||||
>
|
||||
This is the modal body content
|
||||
</Modal>
|
||||
|
|
@ -130,9 +130,9 @@ it('should render with additional class names', async () => {
|
|||
).toEqual(true);
|
||||
});
|
||||
|
||||
it('should render with an overlay', async () => {
|
||||
it('should render with a backdrop', async () => {
|
||||
const { getByTestId } = render(
|
||||
<Modal title="This is a modal title" overlay onClose={jest.fn()}>
|
||||
<Modal title="This is a modal title" backdrop onClose={jest.fn()}>
|
||||
This is the modal body content
|
||||
</Modal>,
|
||||
);
|
||||
|
|
@ -144,12 +144,7 @@ it('should render with an overlay', async () => {
|
|||
|
||||
it('should render with a different size modal', async () => {
|
||||
const { getByTestId } = render(
|
||||
<Modal
|
||||
title="This is a modal title"
|
||||
size="large"
|
||||
className="some-additional-class-name"
|
||||
onClose={jest.fn()}
|
||||
>
|
||||
<Modal title="This is a modal title" size="large" onClose={jest.fn()}>
|
||||
This is the modal body content
|
||||
</Modal>,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export class EmailPreferencesForm extends Component {
|
|||
return (
|
||||
<div
|
||||
data-testid="onboarding-email-preferences-form"
|
||||
className="onboarding-main crayons-modal"
|
||||
className="onboarding-main crayons-modal crayons-modal--large"
|
||||
>
|
||||
<div
|
||||
className="crayons-modal__box"
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ export class FollowTags extends Component {
|
|||
return (
|
||||
<div
|
||||
data-testid="onboarding-follow-tags"
|
||||
className="onboarding-main crayons-modal"
|
||||
className="onboarding-main crayons-modal crayons-modal--large"
|
||||
>
|
||||
<div
|
||||
className="crayons-modal__box overflow-auto"
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ export class FollowUsers extends Component {
|
|||
return (
|
||||
<div
|
||||
data-testid="onboarding-follow-users"
|
||||
className="onboarding-main crayons-modal"
|
||||
className="onboarding-main crayons-modal crayons-modal--large"
|
||||
>
|
||||
<div
|
||||
className="crayons-modal__box overflow-auto"
|
||||
|
|
|
|||
|
|
@ -57,30 +57,21 @@ export class IntroSlide extends Component {
|
|||
}
|
||||
|
||||
isButtonDisabled() {
|
||||
const {
|
||||
checked_code_of_conduct,
|
||||
checked_terms_and_conditions,
|
||||
} = this.state;
|
||||
const { checked_code_of_conduct, checked_terms_and_conditions } =
|
||||
this.state;
|
||||
|
||||
return !checked_code_of_conduct || !checked_terms_and_conditions;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
slidesCount,
|
||||
currentSlideIndex,
|
||||
prev,
|
||||
communityConfig,
|
||||
} = this.props;
|
||||
const {
|
||||
checked_code_of_conduct,
|
||||
checked_terms_and_conditions,
|
||||
text,
|
||||
} = this.state;
|
||||
const { slidesCount, currentSlideIndex, prev, communityConfig } =
|
||||
this.props;
|
||||
const { checked_code_of_conduct, checked_terms_and_conditions, text } =
|
||||
this.state;
|
||||
|
||||
if (text) {
|
||||
return (
|
||||
<div className="onboarding-main crayons-modal crayons-modal--m">
|
||||
<div className="onboarding-main crayons-modal crayons-modal--large">
|
||||
<div className="crayons-modal__box overflow-auto">
|
||||
<div className="onboarding-content terms-and-conditions-wrapper">
|
||||
<button
|
||||
|
|
@ -104,7 +95,7 @@ export class IntroSlide extends Component {
|
|||
return (
|
||||
<div
|
||||
data-testid="onboarding-intro-slide"
|
||||
className="onboarding-main introduction crayons-modal crayons-modal--m"
|
||||
className="onboarding-main introduction crayons-modal"
|
||||
>
|
||||
<div
|
||||
className="crayons-modal__box overflow-auto"
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ export class ProfileForm extends Component {
|
|||
return (
|
||||
<div
|
||||
data-testid="onboarding-profile-form"
|
||||
className="onboarding-main crayons-modal"
|
||||
className="onboarding-main crayons-modal crayons-modal--large"
|
||||
>
|
||||
<div
|
||||
className="crayons-modal__box"
|
||||
|
|
|
|||
|
|
@ -60,13 +60,7 @@ window.Forem = {
|
|||
}
|
||||
return Promise.all(this.modalImports);
|
||||
},
|
||||
showModal: async ({
|
||||
title,
|
||||
contentSelector,
|
||||
overlay = false,
|
||||
size = 's',
|
||||
onOpen,
|
||||
}) => {
|
||||
showModal: async ({ title, contentSelector, size = 'small', onOpen }) => {
|
||||
const [{ Modal }, { render, h }] = await window.Forem.getModalImports();
|
||||
|
||||
// Guard against two modals being opened at once
|
||||
|
|
@ -81,7 +75,6 @@ window.Forem = {
|
|||
|
||||
render(
|
||||
<Modal
|
||||
overlay={overlay}
|
||||
title={title}
|
||||
onClose={() => {
|
||||
render(null, currentModalContainer);
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ export function FlagUserModal({ modCenterArticleUrl, authorId }) {
|
|||
return (
|
||||
<div
|
||||
data-testid="flag-user-modal"
|
||||
class="crayons-modal crayons-modal--s absolute flag-user-modal"
|
||||
class="crayons-modal crayons-modal--small absolute flag-user-modal"
|
||||
>
|
||||
<div class="crayons-modal__box">
|
||||
<header class="crayons-modal__box__header flag-user-modal-header">
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div id="user-subscription-confirmation-modal" class="hidden">
|
||||
<div class="crayons-modal crayons-modal--s">
|
||||
<div class="crayons-modal crayons-modal--small">
|
||||
<div class="crayons-modal__box">
|
||||
<header class="crayons-modal__box__header">
|
||||
<h2 class="fs-l fw-bold mt-0 mb-0">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue