@indico-data/design-system 2.60.15 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/forms/date/inputDateRangePicker/InputDateRangePicker.d.ts +1 -1
- package/lib/components/index.d.ts +1 -1
- package/lib/components/modal/ConfirmationModal.d.ts +2 -0
- package/lib/components/modal/Modal.d.ts +1 -1
- package/lib/components/modal/Modal.stories.d.ts +3 -1
- package/lib/components/modal/index.d.ts +1 -0
- package/lib/components/modal/types.d.ts +18 -0
- package/lib/index.css +1827 -677
- package/lib/index.d.ts +22 -5
- package/lib/index.esm.css +1827 -677
- package/lib/index.esm.js +29 -6
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +29 -5
- package/lib/index.js.map +1 -1
- package/lib/types.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/badge/styles/Badge.scss +6 -6
- package/src/components/button/styles/Button.scss +7 -13
- package/src/components/button/styles/_variables.scss +47 -48
- package/src/components/card/styles/Card.scss +15 -6
- package/src/components/floatUI/styles/_variables.scss +3 -3
- package/src/components/forms/date/datePicker/styles/DatePicker.scss +15 -16
- package/src/components/forms/date/inputDateRangePicker/InputDateRangePicker.tsx +1 -1
- package/src/components/forms/form/styles/Form.scss +25 -25
- package/src/components/forms/select/__tests__/Select.test.tsx +11 -6
- package/src/components/forms/select/styles/Select.scss +9 -10
- package/src/components/index.ts +1 -1
- package/src/components/menu/styles/_variables.scss +8 -8
- package/src/components/modal/ConfirmationModal.mdx +69 -0
- package/src/components/modal/ConfirmationModal.tsx +132 -0
- package/src/components/modal/Modal.mdx +72 -42
- package/src/components/modal/Modal.stories.tsx +200 -40
- package/src/components/modal/Modal.tsx +20 -3
- package/src/components/modal/__tests__/Modal.test.tsx +12 -0
- package/src/components/modal/index.ts +1 -0
- package/src/components/modal/styles/Modal.scss +51 -20
- package/src/components/modal/types.ts +22 -0
- package/src/components/pill/Pill.stories.tsx +28 -14
- package/src/components/pill/Pill.tsx +7 -1
- package/src/components/pill/styles/Pill.scss +79 -55
- package/src/components/tanstackTable/styles/_variables.scss +23 -24
- package/src/components/tanstackTable/styles/table.scss +3 -3
- package/src/components/toast/Toast.mdx +32 -1
- package/src/components/toast/Toast.stories.tsx +32 -9
- package/src/components/toast/styles/Toast.scss +62 -12
- package/src/components/tooltip/Tooltip.tsx +6 -2
- package/src/components/tooltip/styles/Tooltip.scss +6 -2
- package/src/components/truncate/Truncate.tsx +1 -1
- package/src/index.ts +1 -1
- package/src/styles/_borders.scss +35 -4
- package/src/styles/_colors.scss +1 -1
- package/src/styles/globals.scss +107 -25
- package/src/styles/storybook.scss +23 -6
- package/src/styles/variables/_borders.scss +23 -7
- package/src/styles/variables/_padding.scss +0 -4
- package/src/styles/variables/themes/dark.scss +193 -133
- package/src/styles/variables/themes/light.scss +192 -133
- package/src/stylesAndAnimations/borders/BorderColor.tsx +87 -40
- package/src/stylesAndAnimations/colors/Swatch.tsx +0 -1
- package/src/stylesAndAnimations/colors/constants.ts +316 -193
- package/src/types.ts +5 -3
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Canvas, Meta, Controls, Story } from '@storybook/blocks';
|
|
2
|
+
import * as ModalStories from './Modal.stories';
|
|
3
|
+
|
|
4
|
+
<Meta title="Components/Modal" name="ConfirmationModal" of={ModalStories} />
|
|
5
|
+
|
|
6
|
+
# ConfirmationModal
|
|
7
|
+
The ConfirmationModal is a component that provides us with a way to display a confirmation modal. It extends the Modal component. For more information on props not listed here, please visit the [react-modal documentation](https://github.com/reactjs/react-modal).
|
|
8
|
+
|
|
9
|
+
<Canvas of={ModalStories.ConfirmationModalStory} source={{
|
|
10
|
+
code: `
|
|
11
|
+
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
12
|
+
|
|
13
|
+
const handleOpen = () => {
|
|
14
|
+
setIsOpen(true);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const handleClose = () => {
|
|
18
|
+
setIsOpen(false);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Container>
|
|
23
|
+
<Row>
|
|
24
|
+
<Col sm={4}>
|
|
25
|
+
<ConfirmationModal
|
|
26
|
+
className: '',
|
|
27
|
+
onRequestClose: () => {
|
|
28
|
+
console.log('closed');
|
|
29
|
+
},
|
|
30
|
+
title: 'Disable User',
|
|
31
|
+
confirmationButtonText: 'Delete',
|
|
32
|
+
confirmationButtonVariant: 'destructive',
|
|
33
|
+
cancelButtonText: 'Cancel',
|
|
34
|
+
shouldCloseOnOverlayClick: true,
|
|
35
|
+
icon: 'trash',
|
|
36
|
+
status: 'error',
|
|
37
|
+
shouldCloseOnEsc: true,
|
|
38
|
+
parentSelector: () => document.body,
|
|
39
|
+
maxWidthInPixels: 600,
|
|
40
|
+
isOpen={isOpen}
|
|
41
|
+
onRequestClose={handleClose}
|
|
42
|
+
>
|
|
43
|
+
<p>
|
|
44
|
+
Deleting user will no longer allow this person to have access to this organization.
|
|
45
|
+
You can always invite them again if you change your mind.
|
|
46
|
+
</p>
|
|
47
|
+
</ConfirmationModal>
|
|
48
|
+
<Button ariaLabel="open modal" onClick={handleOpen}>
|
|
49
|
+
Open modal
|
|
50
|
+
</Button>
|
|
51
|
+
</Col>
|
|
52
|
+
</Row>
|
|
53
|
+
</Container>
|
|
54
|
+
`
|
|
55
|
+
}} />
|
|
56
|
+
|
|
57
|
+
### The following props are available for the ConfirmationModal component:
|
|
58
|
+
|
|
59
|
+
<Controls of={ModalStories.ConfirmationModalStory} />
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
The ConfirmationModal component is designed to be used as a confirmation modal. It is a wrapper around the Modal component and extends it with the following additional props:
|
|
64
|
+
|
|
65
|
+
- **confirmationButtonText** (string): The text displayed on the confirmation button. Default: 'Confirm'
|
|
66
|
+
- **confirmationButtonVariant** (string): The variant of the confirmation button. Options: 'solid', 'outline', 'link', 'action', 'destructive', 'soft'. Default: 'solid'
|
|
67
|
+
- **cancelButtonText** (string): The text displayed on the cancel button. Default: 'Cancel'
|
|
68
|
+
- **status** (string): The status of the modal which determines the icon color. Options: 'info', 'success', 'error'. Default: 'info'
|
|
69
|
+
- **icon** (string): The icon to display in the modal. Uses the available icon names from the design system.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Button } from '../button/Button';
|
|
2
|
+
import { ButtonVariants } from '../button/types';
|
|
3
|
+
import { Checkbox } from '../forms/checkbox/Checkbox';
|
|
4
|
+
import { Col, Row } from '../grid';
|
|
5
|
+
import { Icon } from '../icons/Icon';
|
|
6
|
+
import { Modal } from './Modal';
|
|
7
|
+
import { ConfirmationModalProps } from './types';
|
|
8
|
+
import classNames from 'classnames';
|
|
9
|
+
import { useState } from 'react';
|
|
10
|
+
|
|
11
|
+
const defaultFooter = ({
|
|
12
|
+
onCancelRequest,
|
|
13
|
+
onConfirmRequest,
|
|
14
|
+
confirmationButtonText,
|
|
15
|
+
confirmationButtonVariant,
|
|
16
|
+
cancelButtonText,
|
|
17
|
+
hasDontShowAgainCheckbox,
|
|
18
|
+
isChecked,
|
|
19
|
+
onDontShowAgainChange,
|
|
20
|
+
}: {
|
|
21
|
+
onCancelRequest?: () => void;
|
|
22
|
+
onConfirmRequest?: ({
|
|
23
|
+
dontShowAgain,
|
|
24
|
+
}: {
|
|
25
|
+
dontShowAgain?: boolean;
|
|
26
|
+
}) => void | Promise<void> | Promise<boolean>;
|
|
27
|
+
confirmationButtonText?: string;
|
|
28
|
+
confirmationButtonVariant?: ButtonVariants;
|
|
29
|
+
cancelButtonText?: string;
|
|
30
|
+
hasDontShowAgainCheckbox?: boolean;
|
|
31
|
+
isChecked?: boolean;
|
|
32
|
+
onDontShowAgainChange?: (checked: boolean) => void;
|
|
33
|
+
}) => (
|
|
34
|
+
<Row gutterWidth={12} justify="end" align="center">
|
|
35
|
+
{hasDontShowAgainCheckbox && (
|
|
36
|
+
<Col>
|
|
37
|
+
<Checkbox
|
|
38
|
+
label="Don't display this again."
|
|
39
|
+
onChange={(e) => onDontShowAgainChange?.(e.target.checked)}
|
|
40
|
+
isChecked={isChecked}
|
|
41
|
+
id="dont-show-again"
|
|
42
|
+
name="dont-show-again"
|
|
43
|
+
/>
|
|
44
|
+
</Col>
|
|
45
|
+
)}
|
|
46
|
+
<Col xs="content">
|
|
47
|
+
<Button onClick={onCancelRequest} ariaLabel={cancelButtonText || 'Cancel'} variant="outline">
|
|
48
|
+
{cancelButtonText}
|
|
49
|
+
</Button>
|
|
50
|
+
</Col>
|
|
51
|
+
<Col xs="content">
|
|
52
|
+
<Button
|
|
53
|
+
onClick={() => onConfirmRequest?.({ dontShowAgain: isChecked })}
|
|
54
|
+
ariaLabel={confirmationButtonText || 'Confirm'}
|
|
55
|
+
variant={confirmationButtonVariant}
|
|
56
|
+
>
|
|
57
|
+
{confirmationButtonText}
|
|
58
|
+
</Button>
|
|
59
|
+
</Col>
|
|
60
|
+
</Row>
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
export const ConfirmationModal = ({
|
|
64
|
+
className,
|
|
65
|
+
overlayClassName,
|
|
66
|
+
testId,
|
|
67
|
+
isOpen,
|
|
68
|
+
onRequestClose,
|
|
69
|
+
portalClassName,
|
|
70
|
+
appElement,
|
|
71
|
+
parentSelector,
|
|
72
|
+
shouldCloseOnOverlayClick,
|
|
73
|
+
shouldCloseOnEsc,
|
|
74
|
+
contentElement,
|
|
75
|
+
overlayElement,
|
|
76
|
+
footer,
|
|
77
|
+
children,
|
|
78
|
+
onConfirmRequest,
|
|
79
|
+
onCancelRequest,
|
|
80
|
+
confirmationButtonText = 'Confirm',
|
|
81
|
+
cancelButtonText = 'Cancel',
|
|
82
|
+
confirmationButtonVariant = 'solid',
|
|
83
|
+
icon,
|
|
84
|
+
title,
|
|
85
|
+
status = 'info',
|
|
86
|
+
maxWidthInPixels,
|
|
87
|
+
hasDontShowAgainCheckbox,
|
|
88
|
+
}: ConfirmationModalProps) => {
|
|
89
|
+
const [dontShowAgain, setDontShowAgain] = useState(false);
|
|
90
|
+
|
|
91
|
+
const modalFooter =
|
|
92
|
+
footer ||
|
|
93
|
+
defaultFooter({
|
|
94
|
+
onCancelRequest,
|
|
95
|
+
onConfirmRequest,
|
|
96
|
+
confirmationButtonText,
|
|
97
|
+
cancelButtonText,
|
|
98
|
+
confirmationButtonVariant,
|
|
99
|
+
hasDontShowAgainCheckbox,
|
|
100
|
+
isChecked: dontShowAgain,
|
|
101
|
+
onDontShowAgainChange: setDontShowAgain,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<Modal
|
|
106
|
+
className={classNames('confirmation-modal', className)}
|
|
107
|
+
overlayClassName={overlayClassName}
|
|
108
|
+
testId={testId}
|
|
109
|
+
isOpen={isOpen}
|
|
110
|
+
onRequestClose={onRequestClose}
|
|
111
|
+
portalClassName={portalClassName}
|
|
112
|
+
appElement={appElement}
|
|
113
|
+
parentSelector={parentSelector}
|
|
114
|
+
shouldCloseOnOverlayClick={shouldCloseOnOverlayClick}
|
|
115
|
+
shouldCloseOnEsc={shouldCloseOnEsc}
|
|
116
|
+
contentElement={contentElement}
|
|
117
|
+
overlayElement={overlayElement}
|
|
118
|
+
footer={modalFooter}
|
|
119
|
+
maxWidthInPixels={maxWidthInPixels}
|
|
120
|
+
>
|
|
121
|
+
{icon && (
|
|
122
|
+
<Icon
|
|
123
|
+
name={icon}
|
|
124
|
+
className={classNames('confirmation-modal-icon', `color-${status}`)}
|
|
125
|
+
size="xl"
|
|
126
|
+
/>
|
|
127
|
+
)}
|
|
128
|
+
{title && <h2 className="confirmation-modal-title">{title}</h2>}
|
|
129
|
+
{children}
|
|
130
|
+
</Modal>
|
|
131
|
+
);
|
|
132
|
+
};
|
|
@@ -5,17 +5,85 @@ import * as Modal from './Modal.stories';
|
|
|
5
5
|
|
|
6
6
|
# Modal
|
|
7
7
|
The Modal component provides us with a way to display content in a modal window. It can be used as a confirmation modal or as a content modal. It extends the react-modal library. For more information on props not listed here, please visit the [react-modal documentation](https://github.com/reactjs/react-modal).
|
|
8
|
-
<Canvas of={Modal.Default}
|
|
9
|
-
|
|
8
|
+
<Canvas of={Modal.Default} source={{
|
|
9
|
+
code: `
|
|
10
|
+
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
11
|
+
|
|
12
|
+
const handleOpen = () => {
|
|
13
|
+
setIsOpen(true);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const handleClose = () => {
|
|
17
|
+
setIsOpen(false);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const footer = (
|
|
21
|
+
<>
|
|
22
|
+
<Row gutterWidth={12} justify="end" align="center">
|
|
23
|
+
<Col xs="content">
|
|
24
|
+
<Button onClick={handleClose} ariaLabel="Cancel" variant="outline">
|
|
25
|
+
Cancel
|
|
26
|
+
</Button>
|
|
27
|
+
</Col>
|
|
28
|
+
<Col xs="content">
|
|
29
|
+
<Button onClick={handleClose} ariaLabel="Confirm" variant="solid">
|
|
30
|
+
Confirm
|
|
31
|
+
</Button>
|
|
32
|
+
</Col>
|
|
33
|
+
</Row>
|
|
34
|
+
</>
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<Container>
|
|
39
|
+
<Row>
|
|
40
|
+
<Col sm={4}>
|
|
41
|
+
<Modal
|
|
42
|
+
title: 'The Legend of Zelda',
|
|
43
|
+
subtitle: 'A timeless tale of courage and adventure',
|
|
44
|
+
className: '',
|
|
45
|
+
maxWidthInPixels: 800,
|
|
46
|
+
onRequestClose: () => {
|
|
47
|
+
console.log('closed');
|
|
48
|
+
},
|
|
49
|
+
shouldCloseOnOverlayClick: true,
|
|
50
|
+
shouldCloseOnEsc: true,
|
|
51
|
+
>
|
|
52
|
+
<p className="mb-4">
|
|
53
|
+
In the mystical realm of Hyrule, where ancient magic flows through verdant fields
|
|
54
|
+
and towering mountains, a timeless tale unfolds across countless generations. The
|
|
55
|
+
legendary hero Link, eternally reborn when darkness threatens the land, stands as
|
|
56
|
+
the chosen wielder of the Master Sword and bearer of the Triforce of Courage.
|
|
57
|
+
Through the ages, he has faced the malevolent forces of Ganon, whose insatiable
|
|
58
|
+
desire for power has brought destruction and chaos to this peaceful kingdom.
|
|
59
|
+
</p>
|
|
60
|
+
<p className="mb-4">
|
|
61
|
+
Princess Zelda, blessed with the wisdom of the goddesses and keeper of the royal
|
|
62
|
+
bloodline, serves as both ruler and guardian of Hyrule's most sacred treasures.
|
|
63
|
+
Together with Link, she maintains the delicate balance between light and shadow,
|
|
64
|
+
protecting the realm from those who would seek to corrupt its divine power. From the
|
|
65
|
+
windswept peaks of Death Mountain to the depths of Lake Hylia, their epic saga
|
|
66
|
+
continues to inspire hope and courage in all who call Hyrule home, as they battle
|
|
67
|
+
against the forces of evil that would plunge their world into darkness.
|
|
68
|
+
</p>
|
|
69
|
+
</Modal>
|
|
70
|
+
<Button ariaLabel="open modal" onClick={handleOpen}>
|
|
71
|
+
Open modal
|
|
72
|
+
</Button>
|
|
73
|
+
</Col>
|
|
74
|
+
</Row>
|
|
75
|
+
</Container>
|
|
76
|
+
)
|
|
77
|
+
` }} />
|
|
10
78
|
### The following props are available for the Modal component:
|
|
11
79
|
|
|
12
80
|
<Controls of={Modal.Default} />
|
|
13
81
|
|
|
14
82
|
## Usage
|
|
15
|
-
|
|
83
|
+
The modal component is designed to be an opinionated wrapper for your content. The header has conditionals that will reveal a horizontal line if there is atleast a title or a subtitle. The footer is also conditionally rendered based on the presence of a footer prop. If you need a simple confirmation modal, you can use the ConfirmationModal component. If you need something a little more custom, you should use this component.
|
|
16
84
|
|
|
17
85
|
### Parent Selector
|
|
18
|
-
You may have an issue with styling and require the modal to be displayed in a specific part of your application. You can use the `parentSelector` prop to pass in a function that returns the element you want to use as the parent element for the modal. In insights we have the following example.
|
|
86
|
+
You may have an issue with styling and require the modal to be displayed in a specific part of your application. You can use the `parentSelector` prop to pass in a function that returns the element you want to use as the parent element for the modal. In insights we have the following example. This is baked into the modal as of the latst version.
|
|
19
87
|
|
|
20
88
|
```tsx
|
|
21
89
|
const parentSelector = () =>
|
|
@@ -81,41 +149,3 @@ The content inside of the Modal tag will be displayed when you open the modal. A
|
|
|
81
149
|
</div>
|
|
82
150
|
</Modal>
|
|
83
151
|
```
|
|
84
|
-
|
|
85
|
-
### Confirmation Modal
|
|
86
|
-
If you are looking for a confirmation modal, you can use the following as an example.
|
|
87
|
-
|
|
88
|
-
```tsx
|
|
89
|
-
<Modal isOpen={isOpen} onRequestClose={handleClose}>
|
|
90
|
-
<h2>Would you like to continue?</h2>
|
|
91
|
-
<p>
|
|
92
|
-
If you would like to proceed, please click the confirm button. Otherwise, click the
|
|
93
|
-
cancel button.
|
|
94
|
-
</p>
|
|
95
|
-
<hr />
|
|
96
|
-
<Row nogutter justify="end" align="center">
|
|
97
|
-
<Col xs="content">
|
|
98
|
-
<Button
|
|
99
|
-
onClick={() => {
|
|
100
|
-
console.log('cancelled');
|
|
101
|
-
handleClose();
|
|
102
|
-
}}
|
|
103
|
-
className="mr-2"
|
|
104
|
-
variant="outline"
|
|
105
|
-
ariaLabel="Cancel"
|
|
106
|
-
>
|
|
107
|
-
Cancel
|
|
108
|
-
</Button>
|
|
109
|
-
<Button
|
|
110
|
-
onClick={() => {
|
|
111
|
-
console.log('confirmed');
|
|
112
|
-
handleClose();
|
|
113
|
-
}}
|
|
114
|
-
ariaLabel="Confirm"
|
|
115
|
-
>
|
|
116
|
-
Confirm
|
|
117
|
-
</Button>
|
|
118
|
-
</Col>
|
|
119
|
-
</Row>
|
|
120
|
-
</Modal>
|
|
121
|
-
```
|
|
@@ -6,6 +6,7 @@ import { Button } from '../button';
|
|
|
6
6
|
import { registerFontAwesomeIcons } from '@/setup/setupIcons';
|
|
7
7
|
import { indiconDefinitions } from '@/components/icons/indicons';
|
|
8
8
|
import { fas } from '@fortawesome/free-solid-svg-icons';
|
|
9
|
+
import { ConfirmationModal } from './ConfirmationModal';
|
|
9
10
|
|
|
10
11
|
registerFontAwesomeIcons(...Object.values(fas), ...indiconDefinitions);
|
|
11
12
|
|
|
@@ -150,6 +151,109 @@ const meta: Meta = {
|
|
|
150
151
|
disable: true,
|
|
151
152
|
},
|
|
152
153
|
},
|
|
154
|
+
title: {
|
|
155
|
+
control: 'text',
|
|
156
|
+
description: 'The title of the modal',
|
|
157
|
+
table: {
|
|
158
|
+
category: 'Props',
|
|
159
|
+
type: {
|
|
160
|
+
summary: 'string',
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
footer: {
|
|
165
|
+
control: false,
|
|
166
|
+
description: 'The footer of the modal. It accepts a React Component',
|
|
167
|
+
table: {
|
|
168
|
+
category: 'Props',
|
|
169
|
+
type: {
|
|
170
|
+
summary: 'React.ReactNode',
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
subtitle: {
|
|
175
|
+
control: 'text',
|
|
176
|
+
description: 'The subtitle of the modal',
|
|
177
|
+
table: {
|
|
178
|
+
category: 'Props',
|
|
179
|
+
type: {
|
|
180
|
+
summary: 'string',
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
maxWidthInPixels: {
|
|
185
|
+
control: 'number',
|
|
186
|
+
description: 'The maximum width of the modal in pixels',
|
|
187
|
+
table: {
|
|
188
|
+
category: 'Props',
|
|
189
|
+
type: {
|
|
190
|
+
summary: 'number',
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
confirmationButtonText: {
|
|
195
|
+
control: 'text',
|
|
196
|
+
description: 'The text of the confirmation button',
|
|
197
|
+
table: {
|
|
198
|
+
category: 'Confirmation Modal',
|
|
199
|
+
type: {
|
|
200
|
+
summary: 'string',
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
confirmationButtonVariant: {
|
|
205
|
+
control: 'select',
|
|
206
|
+
options: ['solid', 'outline', 'link', 'action', 'destructive', 'soft'],
|
|
207
|
+
description: 'The variant of the confirmation button. ',
|
|
208
|
+
table: {
|
|
209
|
+
category: 'Confirmation Modal',
|
|
210
|
+
type: {
|
|
211
|
+
summary: 'string',
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
cancelButtonText: {
|
|
216
|
+
control: 'text',
|
|
217
|
+
description: 'The text of the cancel button',
|
|
218
|
+
table: {
|
|
219
|
+
category: 'Confirmation Modal',
|
|
220
|
+
type: {
|
|
221
|
+
summary: 'string',
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
status: {
|
|
226
|
+
control: 'select',
|
|
227
|
+
options: ['info', 'success', 'error'],
|
|
228
|
+
description: 'The status of the modal. This will determine the color of the icon.',
|
|
229
|
+
table: {
|
|
230
|
+
category: 'Confirmation Modal',
|
|
231
|
+
type: {
|
|
232
|
+
summary: 'string',
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
icon: {
|
|
237
|
+
control: 'select',
|
|
238
|
+
options: Object.keys(indiconDefinitions),
|
|
239
|
+
description: 'The icon of the modal',
|
|
240
|
+
table: {
|
|
241
|
+
category: 'Confirmation Modal',
|
|
242
|
+
type: {
|
|
243
|
+
summary: 'string',
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
hasDontShowAgainCheckbox: {
|
|
248
|
+
control: 'boolean',
|
|
249
|
+
description: 'Whether the modal should have a checkbox to not show again',
|
|
250
|
+
table: {
|
|
251
|
+
category: 'Confirmation Modal',
|
|
252
|
+
type: {
|
|
253
|
+
summary: 'boolean',
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
},
|
|
153
257
|
},
|
|
154
258
|
};
|
|
155
259
|
|
|
@@ -159,12 +263,17 @@ type Story = StoryObj<typeof Modal>;
|
|
|
159
263
|
|
|
160
264
|
export const Default: Story = {
|
|
161
265
|
args: {
|
|
266
|
+
title: 'The Legend of Zelda',
|
|
267
|
+
subtitle: 'A timeless tale of courage and adventure',
|
|
162
268
|
className: '',
|
|
269
|
+
maxWidthInPixels: 800,
|
|
163
270
|
onRequestClose: () => {
|
|
164
271
|
console.log('closed');
|
|
165
272
|
},
|
|
166
273
|
shouldCloseOnOverlayClick: true,
|
|
167
274
|
shouldCloseOnEsc: true,
|
|
275
|
+
parentSelector: () =>
|
|
276
|
+
document.getElementById('theme-root') || document.getElementById('root') || document.body,
|
|
168
277
|
},
|
|
169
278
|
|
|
170
279
|
render: (args) => {
|
|
@@ -178,12 +287,28 @@ export const Default: Story = {
|
|
|
178
287
|
setIsOpen(false);
|
|
179
288
|
};
|
|
180
289
|
|
|
290
|
+
const footer = (
|
|
291
|
+
<>
|
|
292
|
+
<Row gutterWidth={12} justify="end" align="center">
|
|
293
|
+
<Col xs="content">
|
|
294
|
+
<Button onClick={handleClose} ariaLabel="Cancel" variant="outline">
|
|
295
|
+
Cancel
|
|
296
|
+
</Button>
|
|
297
|
+
</Col>
|
|
298
|
+
<Col xs="content">
|
|
299
|
+
<Button onClick={handleClose} ariaLabel="Confirm" variant="solid">
|
|
300
|
+
Confirm
|
|
301
|
+
</Button>
|
|
302
|
+
</Col>
|
|
303
|
+
</Row>
|
|
304
|
+
</>
|
|
305
|
+
);
|
|
306
|
+
|
|
181
307
|
return (
|
|
182
308
|
<Container>
|
|
183
309
|
<Row>
|
|
184
310
|
<Col sm={4}>
|
|
185
|
-
<Modal {...args} isOpen={isOpen} onRequestClose={handleClose}>
|
|
186
|
-
<h2 className="mb-4">The Legend of Zelda</h2>
|
|
311
|
+
<Modal {...args} isOpen={isOpen} onRequestClose={handleClose} footer={footer}>
|
|
187
312
|
<p className="mb-4">
|
|
188
313
|
In the mystical realm of Hyrule, where ancient magic flows through verdant fields
|
|
189
314
|
and towering mountains, a timeless tale unfolds across countless generations. The
|
|
@@ -201,12 +326,6 @@ export const Default: Story = {
|
|
|
201
326
|
continues to inspire hope and courage in all who call Hyrule home, as they battle
|
|
202
327
|
against the forces of evil that would plunge their world into darkness.
|
|
203
328
|
</p>
|
|
204
|
-
<div className="actions text-align--right">
|
|
205
|
-
<hr />
|
|
206
|
-
<Button onClick={handleClose} ariaLabel="Close" variant="outline">
|
|
207
|
-
Close
|
|
208
|
-
</Button>
|
|
209
|
-
</div>
|
|
210
329
|
</Modal>
|
|
211
330
|
<Button ariaLabel="open modal" onClick={handleOpen}>
|
|
212
331
|
Open modal
|
|
@@ -218,14 +337,24 @@ export const Default: Story = {
|
|
|
218
337
|
},
|
|
219
338
|
};
|
|
220
339
|
|
|
221
|
-
export const
|
|
340
|
+
export const ConfirmationModalStory: StoryObj<typeof ConfirmationModal> = {
|
|
222
341
|
args: {
|
|
223
342
|
className: '',
|
|
224
343
|
onRequestClose: () => {
|
|
225
344
|
console.log('closed');
|
|
226
345
|
},
|
|
346
|
+
title: 'Disable User',
|
|
347
|
+
confirmationButtonText: 'Delete',
|
|
348
|
+
confirmationButtonVariant: 'destructive',
|
|
349
|
+
cancelButtonText: 'Cancel',
|
|
227
350
|
shouldCloseOnOverlayClick: true,
|
|
351
|
+
subtitle: '',
|
|
352
|
+
icon: 'trash',
|
|
353
|
+
status: 'error',
|
|
228
354
|
shouldCloseOnEsc: true,
|
|
355
|
+
parentSelector: () => document.body,
|
|
356
|
+
maxWidthInPixels: 600,
|
|
357
|
+
hasDontShowAgainCheckbox: false,
|
|
229
358
|
},
|
|
230
359
|
|
|
231
360
|
render: (args) => {
|
|
@@ -243,38 +372,69 @@ export const ConfirmationModal: Story = {
|
|
|
243
372
|
<Container>
|
|
244
373
|
<Row>
|
|
245
374
|
<Col sm={4}>
|
|
246
|
-
<
|
|
247
|
-
<
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
cancel button.
|
|
375
|
+
<ConfirmationModal {...args} isOpen={isOpen} onRequestClose={handleClose}>
|
|
376
|
+
<p>
|
|
377
|
+
Deleting user will no longer allow this person to have access to this organization.
|
|
378
|
+
You can always invite them again if you change your mind.
|
|
251
379
|
</p>
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
380
|
+
</ConfirmationModal>
|
|
381
|
+
<Button ariaLabel="open modal" onClick={handleOpen}>
|
|
382
|
+
Open modal
|
|
383
|
+
</Button>
|
|
384
|
+
</Col>
|
|
385
|
+
</Row>
|
|
386
|
+
</Container>
|
|
387
|
+
);
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
export const ConfirmationModalStoryWithCheckbox: StoryObj<typeof ConfirmationModal> = {
|
|
392
|
+
args: {
|
|
393
|
+
className: '',
|
|
394
|
+
onRequestClose: () => {
|
|
395
|
+
console.log('closed');
|
|
396
|
+
},
|
|
397
|
+
title: 'Disable User',
|
|
398
|
+
confirmationButtonText: 'Delete',
|
|
399
|
+
confirmationButtonVariant: 'destructive',
|
|
400
|
+
cancelButtonText: 'Cancel',
|
|
401
|
+
shouldCloseOnOverlayClick: true,
|
|
402
|
+
icon: 'trash',
|
|
403
|
+
status: 'error',
|
|
404
|
+
shouldCloseOnEsc: true,
|
|
405
|
+
parentSelector: () => document.body,
|
|
406
|
+
maxWidthInPixels: 600,
|
|
407
|
+
hasDontShowAgainCheckbox: true,
|
|
408
|
+
},
|
|
409
|
+
|
|
410
|
+
render: (args) => {
|
|
411
|
+
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
412
|
+
|
|
413
|
+
const handleOpen = () => {
|
|
414
|
+
setIsOpen(true);
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
const handleClose = () => {
|
|
418
|
+
setIsOpen(false);
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
return (
|
|
422
|
+
<Container>
|
|
423
|
+
<Row>
|
|
424
|
+
<Col sm={4}>
|
|
425
|
+
<ConfirmationModal
|
|
426
|
+
{...args}
|
|
427
|
+
isOpen={isOpen}
|
|
428
|
+
onConfirmRequest={({ dontShowAgain }) => {
|
|
429
|
+
console.log('confirmed', dontShowAgain);
|
|
430
|
+
}}
|
|
431
|
+
onRequestClose={handleClose}
|
|
432
|
+
>
|
|
433
|
+
<p>
|
|
434
|
+
Deleting user will no longer allow this person to have access to this organization.
|
|
435
|
+
You can always invite them again if you change your mind.
|
|
436
|
+
</p>
|
|
437
|
+
</ConfirmationModal>
|
|
278
438
|
<Button ariaLabel="open modal" onClick={handleOpen}>
|
|
279
439
|
Open modal
|
|
280
440
|
</Button>
|
|
@@ -20,15 +20,20 @@ export const Modal = ({
|
|
|
20
20
|
contentElement,
|
|
21
21
|
overlayElement,
|
|
22
22
|
position = 'center',
|
|
23
|
-
parentSelector,
|
|
23
|
+
parentSelector = () => document.getElementById('theme-root') || document.getElementById('root')!, // default for our apps, storybook needs a different one
|
|
24
|
+
title,
|
|
25
|
+
subtitle,
|
|
26
|
+
footer,
|
|
27
|
+
maxWidthInPixels,
|
|
24
28
|
...rest
|
|
25
29
|
}: ModalProps) => {
|
|
26
30
|
const modalClasses = classNames('modal', `modal--${position}`, className);
|
|
27
31
|
const overlayClasses = classNames('modal-overlay', overlayClassName);
|
|
28
32
|
|
|
33
|
+
const hasHeader = title || subtitle;
|
|
34
|
+
|
|
29
35
|
return (
|
|
30
36
|
<ReactModal
|
|
31
|
-
style={{}}
|
|
32
37
|
className={modalClasses}
|
|
33
38
|
overlayClassName={overlayClasses}
|
|
34
39
|
testId={testId}
|
|
@@ -43,7 +48,7 @@ export const Modal = ({
|
|
|
43
48
|
overlayElement={overlayElement}
|
|
44
49
|
{...rest}
|
|
45
50
|
>
|
|
46
|
-
<div className="modal-content">
|
|
51
|
+
<div className="modal-content" style={{ maxWidth: `${maxWidthInPixels}px` }}>
|
|
47
52
|
<Button
|
|
48
53
|
className="modal-close-button"
|
|
49
54
|
onClick={onRequestClose}
|
|
@@ -52,7 +57,19 @@ export const Modal = ({
|
|
|
52
57
|
iconLeft="x-close"
|
|
53
58
|
ariaLabel="Close"
|
|
54
59
|
/>
|
|
60
|
+
{hasHeader && (
|
|
61
|
+
<div className="modal-header">
|
|
62
|
+
<Row justify="between" align="center">
|
|
63
|
+
<Col>
|
|
64
|
+
{title && <h2 className="modal-title">{title}</h2>}
|
|
65
|
+
{subtitle && <p className="modal-subtitle">{subtitle}</p>}
|
|
66
|
+
</Col>
|
|
67
|
+
</Row>
|
|
68
|
+
</div>
|
|
69
|
+
)}
|
|
70
|
+
|
|
55
71
|
<div className="modal-body">{children}</div>
|
|
72
|
+
{footer && <div className="modal-footer">{footer}</div>}
|
|
56
73
|
</div>
|
|
57
74
|
</ReactModal>
|
|
58
75
|
);
|