@indico-data/design-system 2.45.6 → 2.47.0
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/badge/Badge.d.ts +2 -0
- package/lib/components/badge/Badge.stories.d.ts +7 -0
- package/lib/components/badge/__tests__/Badge.test.d.ts +1 -0
- package/lib/components/badge/index.d.ts +1 -0
- package/lib/components/badge/types.d.ts +7 -0
- package/lib/components/index.d.ts +2 -0
- package/lib/components/menu/Menu.d.ts +2 -1
- package/lib/components/modal/Modal.d.ts +2 -0
- package/lib/components/modal/Modal.stories.d.ts +7 -0
- package/lib/components/modal/__tests__/Modal.test.d.ts +1 -0
- package/lib/components/modal/index.d.ts +1 -0
- package/lib/components/modal/types.d.ts +15 -0
- package/lib/index.css +142 -0
- package/lib/index.d.ts +39 -49
- package/lib/index.esm.css +142 -0
- package/lib/index.esm.js +11224 -11378
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +11223 -11377
- package/lib/index.js.map +1 -1
- package/lib/legacy/components/index.d.ts +0 -1
- package/package.json +1 -1
- package/src/components/badge/Badge.mdx +36 -0
- package/src/components/badge/Badge.stories.tsx +109 -0
- package/src/components/badge/Badge.tsx +18 -0
- package/src/components/badge/__tests__/Badge.test.tsx +17 -0
- package/src/components/badge/index.ts +1 -0
- package/src/components/badge/styles/Badge.scss +61 -0
- package/src/components/badge/types.ts +8 -0
- package/src/components/card/Card.tsx +1 -1
- package/src/components/index.ts +2 -0
- package/src/components/menu/Menu.tsx +3 -2
- package/src/components/modal/Modal.mdx +111 -0
- package/src/components/modal/Modal.stories.tsx +275 -0
- package/src/components/modal/Modal.tsx +61 -0
- package/src/components/modal/__tests__/Modal.test.tsx +60 -0
- package/src/components/modal/index.ts +1 -0
- package/src/components/modal/styles/Modal.scss +100 -0
- package/src/components/modal/types.ts +15 -0
- package/src/index.ts +3 -9
- package/src/legacy/components/index.ts +0 -1
- package/src/setup/setupIcons.ts +2 -0
- package/src/styles/index.scss +2 -0
- package/lib/legacy/components/modals/ConfirmModal/ConfirmModal.d.ts +0 -17
- package/lib/legacy/components/modals/ConfirmModal/ConfirmModal.stories.d.ts +0 -44
- package/lib/legacy/components/modals/ConfirmModal/ConfirmModal.styles.d.ts +0 -1
- package/lib/legacy/components/modals/ConfirmModal/index.d.ts +0 -1
- package/lib/legacy/components/modals/ModalBase/ModalBase.d.ts +0 -26
- package/lib/legacy/components/modals/ModalBase/ModalBase.stories.d.ts +0 -9
- package/lib/legacy/components/modals/ModalBase/ModalBase.styles.d.ts +0 -4
- package/lib/legacy/components/modals/ModalBase/index.d.ts +0 -2
- package/lib/legacy/components/modals/index.d.ts +0 -2
- package/src/legacy/components/modals/ConfirmModal/ConfirmModal.stories.tsx +0 -76
- package/src/legacy/components/modals/ConfirmModal/ConfirmModal.styles.ts +0 -27
- package/src/legacy/components/modals/ConfirmModal/ConfirmModal.tsx +0 -79
- package/src/legacy/components/modals/ConfirmModal/index.ts +0 -1
- package/src/legacy/components/modals/ModalBase/ModalBase.stories.tsx +0 -45
- package/src/legacy/components/modals/ModalBase/ModalBase.styles.tsx +0 -72
- package/src/legacy/components/modals/ModalBase/ModalBase.tsx +0 -79
- package/src/legacy/components/modals/ModalBase/index.ts +0 -2
- package/src/legacy/components/modals/index.ts +0 -2
package/package.json
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Canvas, Meta, Controls, Story } from '@storybook/blocks';
|
|
2
|
+
import * as Badge from './Badge.stories';
|
|
3
|
+
import { Container, Row, Col } from '../grid';
|
|
4
|
+
import { fas } from '@fortawesome/free-solid-svg-icons';
|
|
5
|
+
import { registerFontAwesomeIcons } from '@/setup/setupIcons';
|
|
6
|
+
import { indiconDefinitions } from '@/components/icons/indicons';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
<Meta title="Components/Badge" name="Badge" of={Badge} />
|
|
10
|
+
|
|
11
|
+
# Badge
|
|
12
|
+
The Badge component is designed to display concise information about an item. It is versatile and can be used in various contexts, such as within dropdowns or other interactive elements.
|
|
13
|
+
|
|
14
|
+
<Canvas of={Badge.String} />
|
|
15
|
+
|
|
16
|
+
### The following props are available for the Badge component:
|
|
17
|
+
|
|
18
|
+
<Controls of={Badge.String} />
|
|
19
|
+
|
|
20
|
+
<Container>
|
|
21
|
+
<Row>
|
|
22
|
+
<Col xs={12}>
|
|
23
|
+
<h2 >Usage</h2>
|
|
24
|
+
</Col>
|
|
25
|
+
<Col sm={6}>
|
|
26
|
+
<h3>String</h3>
|
|
27
|
+
<p>The string prop is used to display a string inside the badge.</p>
|
|
28
|
+
<Canvas of={Badge.String} />
|
|
29
|
+
</Col>
|
|
30
|
+
<Col sm={6}>
|
|
31
|
+
<h3>With Dropdown</h3>
|
|
32
|
+
<p>The dropdown prop is used to display a dropdown inside the badge as a child element.</p>
|
|
33
|
+
<Canvas of={Badge.WithDropdown} />
|
|
34
|
+
</Col>
|
|
35
|
+
</Row>
|
|
36
|
+
</Container>
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Badge } from './Badge';
|
|
3
|
+
import { Col, Container, Row } from '../grid';
|
|
4
|
+
import { FloatUI } from '../floatUI';
|
|
5
|
+
import { Menu } from '../menu';
|
|
6
|
+
import { Icon } from '../icons';
|
|
7
|
+
|
|
8
|
+
const meta: Meta = {
|
|
9
|
+
title: 'Components/Badge',
|
|
10
|
+
component: Badge,
|
|
11
|
+
argTypes: {
|
|
12
|
+
size: {
|
|
13
|
+
control: 'select',
|
|
14
|
+
options: ['xs', 'sm', 'md', 'lg', 'xl'],
|
|
15
|
+
description: 'The size of the badge',
|
|
16
|
+
table: {
|
|
17
|
+
category: 'Props',
|
|
18
|
+
type: {
|
|
19
|
+
summary: 'string',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
className: {
|
|
24
|
+
control: 'text',
|
|
25
|
+
description: 'Additional classes for the badge component',
|
|
26
|
+
table: {
|
|
27
|
+
category: 'Props',
|
|
28
|
+
type: {
|
|
29
|
+
summary: 'string',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
children: {
|
|
34
|
+
control: false,
|
|
35
|
+
description: 'The content of the badge (superseded by the string prop)',
|
|
36
|
+
table: {
|
|
37
|
+
category: 'Props',
|
|
38
|
+
type: {
|
|
39
|
+
summary: 'React.ReactNode',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
string: {
|
|
44
|
+
control: 'text',
|
|
45
|
+
description: 'The string to display in the badge. (supersedes children prop)',
|
|
46
|
+
table: {
|
|
47
|
+
category: 'Props',
|
|
48
|
+
type: {
|
|
49
|
+
summary: 'string',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default meta;
|
|
57
|
+
|
|
58
|
+
type Story = StoryObj<typeof Badge>;
|
|
59
|
+
|
|
60
|
+
export const String: Story = {
|
|
61
|
+
args: {
|
|
62
|
+
className: '',
|
|
63
|
+
string: 'Badge',
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
render: (args) => {
|
|
67
|
+
return (
|
|
68
|
+
<Container>
|
|
69
|
+
<Row>
|
|
70
|
+
<Col sm={4}>
|
|
71
|
+
<Badge {...args} />
|
|
72
|
+
</Col>
|
|
73
|
+
</Row>
|
|
74
|
+
</Container>
|
|
75
|
+
);
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const WithDropdown: Story = {
|
|
80
|
+
args: {
|
|
81
|
+
className: '',
|
|
82
|
+
size: 'sm',
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
render: (args) => {
|
|
86
|
+
return (
|
|
87
|
+
<Container>
|
|
88
|
+
<Row>
|
|
89
|
+
<Col sm={4} style={{ height: '130px' }}>
|
|
90
|
+
<Badge {...args}>
|
|
91
|
+
<FloatUI ariaLabel="Badge">
|
|
92
|
+
<div style={{ display: 'flex', alignItems: 'center', cursor: 'pointer' }}>
|
|
93
|
+
<p className="text-overline">Badge</p>
|
|
94
|
+
<Icon size="xs" className="ml-3" name="chevron-down" />
|
|
95
|
+
</div>
|
|
96
|
+
<Menu className="pa-2">
|
|
97
|
+
<li>Item 1</li>
|
|
98
|
+
<li>Item 2</li>
|
|
99
|
+
<li>Item 3</li>
|
|
100
|
+
<li>Item 4</li>
|
|
101
|
+
</Menu>
|
|
102
|
+
</FloatUI>
|
|
103
|
+
</Badge>
|
|
104
|
+
</Col>
|
|
105
|
+
</Row>
|
|
106
|
+
</Container>
|
|
107
|
+
);
|
|
108
|
+
},
|
|
109
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import { BadgeProps } from './types';
|
|
3
|
+
|
|
4
|
+
export const Badge = ({ className = '', children, size = 'md', string, ...rest }: BadgeProps) => {
|
|
5
|
+
const badgeClasses = classNames(
|
|
6
|
+
'badge',
|
|
7
|
+
{
|
|
8
|
+
[`badge--${size}`]: size,
|
|
9
|
+
},
|
|
10
|
+
className,
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div className={badgeClasses} {...rest}>
|
|
15
|
+
{string ? <p>{string}</p> : children}
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import { Badge } from '@/components/badge/Badge';
|
|
3
|
+
|
|
4
|
+
describe('Badge', () => {
|
|
5
|
+
it.each(['xs', 'sm', 'md', 'lg', 'xl'] as const)('renders the badge with size %s', (size) => {
|
|
6
|
+
render(<Badge size={size}>Badge</Badge>);
|
|
7
|
+
expect(screen.getByText('Badge')).toHaveClass(`badge--${size}`);
|
|
8
|
+
});
|
|
9
|
+
it('renders the badge with content inside', () => {
|
|
10
|
+
render(<Badge>Badge</Badge>);
|
|
11
|
+
expect(screen.getByText('Badge')).toBeInTheDocument();
|
|
12
|
+
});
|
|
13
|
+
it('renders the badge with string', () => {
|
|
14
|
+
render(<Badge string="Badge" />);
|
|
15
|
+
expect(screen.getByText('Badge')).toBeInTheDocument();
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Badge } from './Badge';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Common Variables
|
|
2
|
+
:root {
|
|
3
|
+
--pf-badge-rounded: var(--pf-rounded);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// Light Theme Specific Variables
|
|
7
|
+
:root [data-theme='light'] {
|
|
8
|
+
--pf-badge-background-color: var(--pf-white-color);
|
|
9
|
+
--pf-badge-border-color: var(--pf-border-color);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Dark Theme Specific Variables
|
|
13
|
+
:root [data-theme='dark'],
|
|
14
|
+
:root {
|
|
15
|
+
--pf-badge-background-color: var(--pf-primary-color-600);
|
|
16
|
+
--pf-badge-border-color: var(--pf-border-color);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.badge {
|
|
20
|
+
border-radius: var(--pf-rounded-lg);
|
|
21
|
+
padding: var(--pf-padding-3);
|
|
22
|
+
background: var(--pf-badge-background-color);
|
|
23
|
+
border: var(--pf-border-sm) solid var(--pf-badge-border-color);
|
|
24
|
+
box-sizing: border-box;
|
|
25
|
+
width: fit-content;
|
|
26
|
+
|
|
27
|
+
&--xs {
|
|
28
|
+
padding: var(--pf-padding-1);
|
|
29
|
+
p {
|
|
30
|
+
font-size: var(--pf-font-size-overline);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&--sm {
|
|
35
|
+
padding: var(--pf-padding-2);
|
|
36
|
+
p {
|
|
37
|
+
font-size: var(--pf-font-size-body2);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&--md {
|
|
42
|
+
padding: var(--pf-padding-3);
|
|
43
|
+
p {
|
|
44
|
+
font-size: var(--pf-font-size-body);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&--lg {
|
|
49
|
+
padding: var(--pf-padding-4);
|
|
50
|
+
p {
|
|
51
|
+
font-size: var(--pf-font-size-h2);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&--xl {
|
|
56
|
+
padding: var(--pf-padding-5);
|
|
57
|
+
p {
|
|
58
|
+
font-size: var(--pf-font-size-h1);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -18,3 +18,5 @@ export { DatePicker } from './forms/date/datePicker/DatePicker';
|
|
|
18
18
|
export { IconTriggerDatePicker } from './forms/date/iconTriggerDatePicker';
|
|
19
19
|
export { SingleInputDatePicker } from './forms/date/inputDatePicker';
|
|
20
20
|
export { InputDateRangePicker } from './forms/date/inputDateRangePicker';
|
|
21
|
+
export { Modal } from './modal';
|
|
22
|
+
export { Badge } from './badge';
|
|
@@ -3,11 +3,12 @@ import classNames from 'classnames';
|
|
|
3
3
|
|
|
4
4
|
export type MenuProps = {
|
|
5
5
|
children: React.ReactNode;
|
|
6
|
+
className?: string;
|
|
6
7
|
};
|
|
7
8
|
|
|
8
|
-
export function Menu({ children }: MenuProps) {
|
|
9
|
+
export function Menu({ children, className, ...rest }: MenuProps) {
|
|
9
10
|
return (
|
|
10
|
-
<div className=
|
|
11
|
+
<div className={classNames('menu', className)} {...rest}>
|
|
11
12
|
{React.Children.map(children, (child) =>
|
|
12
13
|
React.isValidElement(child)
|
|
13
14
|
? React.cloneElement(child as ReactElement, {
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Canvas, Meta, Controls, Story } from '@storybook/blocks';
|
|
2
|
+
import * as Modal from './Modal.stories';
|
|
3
|
+
|
|
4
|
+
<Meta title="Components/Modal" name="Modal" of={Modal} />
|
|
5
|
+
|
|
6
|
+
# Modal
|
|
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
|
+
|
|
10
|
+
### The following props are available for the Modal component:
|
|
11
|
+
|
|
12
|
+
<Controls of={Modal.Default} />
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
We have designed this modal with the intention for it to be used as a wrapper for content as you will see below. The recommended way to best use this component is to create your own wrapper in your application for specific modal needs. For example, you may create a wrapper component that displays a confirmation modal. You may also wish to create one for a stepper modal. The idea is that you wrap this modal in a component and build the body of your modal in that wrapped component so that you can reuse the modal component for different modal needs.
|
|
16
|
+
|
|
17
|
+
### Opening The Modal
|
|
18
|
+
To open the modal, you can use the following as an example. You create a state variable to control the modal's open/close state and then pass that state variable to the modal component.
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
22
|
+
|
|
23
|
+
const handleOpen = () => {
|
|
24
|
+
setIsOpen(true);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const handleClose = () => {
|
|
28
|
+
setIsOpen(false);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
<Button onClick={handleOpen}>Open Modal</Button>
|
|
32
|
+
|
|
33
|
+
// Modal Component
|
|
34
|
+
<Modal isOpen={isOpen} onRequestClose={handleClose}>
|
|
35
|
+
<h2>The Legend of Zelda</h2>
|
|
36
|
+
</Modal>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Content Modal
|
|
40
|
+
The content inside of the Modal tag will be displayed when you open the modal. Anything you pass to the modal should be visible. There is also no set width for the modal, it will take up the width you provide the body elements.
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
<Modal
|
|
44
|
+
isOpen={isOpen}
|
|
45
|
+
onRequestClose={() => {}}
|
|
46
|
+
shouldCloseOnEsc
|
|
47
|
+
shouldCloseOnOverlayClick
|
|
48
|
+
>
|
|
49
|
+
<h2>
|
|
50
|
+
The Legend of Zelda
|
|
51
|
+
</h2>
|
|
52
|
+
<p>
|
|
53
|
+
In the mystical realm of Hyrule, where ancient magic flows through verdant fields and towering mountains, a timeless tale unfolds across countless generations. The legendary hero Link, eternally reborn when darkness threatens the land, stands as the chosen wielder of the Master Sword and bearer of the Triforce of Courage. Through the ages, he has faced the malevolent forces of Ganon, whose insatiable desire for power has brought destruction and chaos to this peaceful kingdom.
|
|
54
|
+
</p>
|
|
55
|
+
<p>
|
|
56
|
+
Princess Zelda, blessed with the wisdom of the goddesses and keeper of the royal bloodline, serves as both ruler and guardian of Hyrule's most sacred treasures. Together with Link, she maintains the delicate balance between light and shadow, protecting the realm from those who would seek to corrupt its divine power. From the windswept peaks of Death Mountain to the depths of Lake Hylia, their epic saga continues to inspire hope and courage in all who call Hyrule home, as they battle against the forces of evil that would plunge their world into darkness.
|
|
57
|
+
</p>
|
|
58
|
+
<div className="actions text-align--right">
|
|
59
|
+
<hr />
|
|
60
|
+
<Button
|
|
61
|
+
ariaLabel="Close"
|
|
62
|
+
onClick={() => {}}
|
|
63
|
+
variant="outline"
|
|
64
|
+
>
|
|
65
|
+
Close
|
|
66
|
+
</Button>
|
|
67
|
+
</div>
|
|
68
|
+
</Modal>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Confirmation Modal
|
|
72
|
+
If you are looking for a confirmation modal, you can use the following as an example.
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
<Modal isOpen={isOpen} onRequestClose={handleClose}>
|
|
76
|
+
<h2>Would you like to continue?</h2>
|
|
77
|
+
<p>
|
|
78
|
+
If you would like to proceed, please click the confirm button. Otherwise, click the
|
|
79
|
+
cancel button.
|
|
80
|
+
</p>
|
|
81
|
+
<hr />
|
|
82
|
+
<Row nogutter justify="end" align="center">
|
|
83
|
+
<Col xs="content">
|
|
84
|
+
<Button
|
|
85
|
+
onClick={() => {
|
|
86
|
+
console.log('cancelled');
|
|
87
|
+
handleClose();
|
|
88
|
+
}}
|
|
89
|
+
className="mr-2"
|
|
90
|
+
variant="outline"
|
|
91
|
+
ariaLabel="Cancel"
|
|
92
|
+
>
|
|
93
|
+
Cancel
|
|
94
|
+
</Button>
|
|
95
|
+
<Button
|
|
96
|
+
onClick={() => {
|
|
97
|
+
console.log('confirmed');
|
|
98
|
+
handleClose();
|
|
99
|
+
}}
|
|
100
|
+
ariaLabel="Confirm"
|
|
101
|
+
>
|
|
102
|
+
Confirm
|
|
103
|
+
</Button>
|
|
104
|
+
</Col>
|
|
105
|
+
</Row>
|
|
106
|
+
</Modal>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Title vs Content
|
|
110
|
+
The title prop is optional for the modal. If you do not provide a title, the modal will only display the content. If you do provide a title, the modal will display the title and content.
|
|
111
|
+
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Modal } from './Modal';
|
|
3
|
+
import { Col, Container, Row } from '../grid';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import { Button } from '../button';
|
|
6
|
+
import { registerFontAwesomeIcons } from '@/setup/setupIcons';
|
|
7
|
+
import { indiconDefinitions } from '@/components/icons/indicons';
|
|
8
|
+
import { fas } from '@fortawesome/free-solid-svg-icons';
|
|
9
|
+
|
|
10
|
+
registerFontAwesomeIcons(...Object.values(fas), ...indiconDefinitions);
|
|
11
|
+
|
|
12
|
+
const meta: Meta = {
|
|
13
|
+
title: 'Components/Modal',
|
|
14
|
+
component: Modal,
|
|
15
|
+
argTypes: {
|
|
16
|
+
className: {
|
|
17
|
+
control: 'text',
|
|
18
|
+
description: 'Additional classes for the badge component',
|
|
19
|
+
table: {
|
|
20
|
+
category: 'Props',
|
|
21
|
+
type: {
|
|
22
|
+
summary: 'string',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
children: {
|
|
27
|
+
control: false,
|
|
28
|
+
description: 'The content of the badge (superseded by the string prop)',
|
|
29
|
+
table: {
|
|
30
|
+
category: 'Props',
|
|
31
|
+
type: {
|
|
32
|
+
summary: 'React.ReactNode',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
isOpen: {
|
|
37
|
+
control: false,
|
|
38
|
+
description: 'Whether the modal is open',
|
|
39
|
+
table: {
|
|
40
|
+
category: 'Props',
|
|
41
|
+
type: {
|
|
42
|
+
summary: 'boolean',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
onRequestClose: {
|
|
47
|
+
control: false,
|
|
48
|
+
description: 'Callback function to be called when the modal is closed',
|
|
49
|
+
table: {
|
|
50
|
+
category: 'Props',
|
|
51
|
+
type: {
|
|
52
|
+
summary: 'function',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
portalClassName: {
|
|
57
|
+
control: false,
|
|
58
|
+
description: 'Additional classes for the portal element',
|
|
59
|
+
table: {
|
|
60
|
+
category: 'Props',
|
|
61
|
+
type: {
|
|
62
|
+
summary: 'string',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
overlayClassName: {
|
|
67
|
+
control: false,
|
|
68
|
+
description: 'Additional classes for the overlay element',
|
|
69
|
+
table: {
|
|
70
|
+
category: 'Props',
|
|
71
|
+
type: {
|
|
72
|
+
summary: 'string',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
appElement: {
|
|
77
|
+
control: false,
|
|
78
|
+
description: 'The element to use as the app element',
|
|
79
|
+
table: {
|
|
80
|
+
category: 'Props',
|
|
81
|
+
type: {
|
|
82
|
+
summary: 'HTMLElement',
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
shouldCloseOnOverlayClick: {
|
|
87
|
+
control: 'boolean',
|
|
88
|
+
description: 'Whether the modal should close when the overlay is clicked',
|
|
89
|
+
table: {
|
|
90
|
+
category: 'Props',
|
|
91
|
+
type: {
|
|
92
|
+
summary: 'boolean',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
shouldCloseOnEsc: {
|
|
97
|
+
control: 'boolean',
|
|
98
|
+
description: 'Whether the modal should close when the escape key is pressed',
|
|
99
|
+
table: {
|
|
100
|
+
category: 'Props',
|
|
101
|
+
type: {
|
|
102
|
+
summary: 'boolean',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
contentElement: {
|
|
107
|
+
control: false,
|
|
108
|
+
description: 'Custom content element for the modal',
|
|
109
|
+
table: {
|
|
110
|
+
category: 'Props',
|
|
111
|
+
type: {
|
|
112
|
+
summary: 'React.ReactNode',
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
overlayElement: {
|
|
117
|
+
control: false,
|
|
118
|
+
description: 'Custom overlay element for the modal',
|
|
119
|
+
table: {
|
|
120
|
+
category: 'Props',
|
|
121
|
+
type: {
|
|
122
|
+
summary: 'React.ReactNode',
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
position: {
|
|
127
|
+
control: 'select',
|
|
128
|
+
options: ['top', 'center'],
|
|
129
|
+
description: 'The position of the modal opens on the page',
|
|
130
|
+
table: {
|
|
131
|
+
category: 'Props',
|
|
132
|
+
type: {
|
|
133
|
+
summary: 'string',
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
testId: {
|
|
138
|
+
table: {
|
|
139
|
+
disable: true,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export default meta;
|
|
146
|
+
|
|
147
|
+
type Story = StoryObj<typeof Modal>;
|
|
148
|
+
|
|
149
|
+
export const Default: Story = {
|
|
150
|
+
args: {
|
|
151
|
+
className: '',
|
|
152
|
+
onRequestClose: () => {
|
|
153
|
+
console.log('closed');
|
|
154
|
+
},
|
|
155
|
+
shouldCloseOnOverlayClick: true,
|
|
156
|
+
shouldCloseOnEsc: true,
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
render: (args) => {
|
|
160
|
+
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
161
|
+
|
|
162
|
+
const handleOpen = () => {
|
|
163
|
+
setIsOpen(true);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const handleClose = () => {
|
|
167
|
+
setIsOpen(false);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<Container>
|
|
172
|
+
<Row>
|
|
173
|
+
<Col sm={4}>
|
|
174
|
+
<Modal {...args} isOpen={isOpen} onRequestClose={handleClose}>
|
|
175
|
+
<h2>The Legend of Zelda</h2>
|
|
176
|
+
<p>
|
|
177
|
+
In the mystical realm of Hyrule, where ancient magic flows through verdant fields
|
|
178
|
+
and towering mountains, a timeless tale unfolds across countless generations. The
|
|
179
|
+
legendary hero Link, eternally reborn when darkness threatens the land, stands as
|
|
180
|
+
the chosen wielder of the Master Sword and bearer of the Triforce of Courage.
|
|
181
|
+
Through the ages, he has faced the malevolent forces of Ganon, whose insatiable
|
|
182
|
+
desire for power has brought destruction and chaos to this peaceful kingdom.
|
|
183
|
+
</p>
|
|
184
|
+
<p>
|
|
185
|
+
Princess Zelda, blessed with the wisdom of the goddesses and keeper of the royal
|
|
186
|
+
bloodline, serves as both ruler and guardian of Hyrule's most sacred treasures.
|
|
187
|
+
Together with Link, she maintains the delicate balance between light and shadow,
|
|
188
|
+
protecting the realm from those who would seek to corrupt its divine power. From the
|
|
189
|
+
windswept peaks of Death Mountain to the depths of Lake Hylia, their epic saga
|
|
190
|
+
continues to inspire hope and courage in all who call Hyrule home, as they battle
|
|
191
|
+
against the forces of evil that would plunge their world into darkness.
|
|
192
|
+
</p>
|
|
193
|
+
<div className="actions text-align--right">
|
|
194
|
+
<hr />
|
|
195
|
+
<Button onClick={handleClose} ariaLabel="Close" variant="outline">
|
|
196
|
+
Close
|
|
197
|
+
</Button>
|
|
198
|
+
</div>
|
|
199
|
+
</Modal>
|
|
200
|
+
<Button ariaLabel="open modal" onClick={handleOpen}>
|
|
201
|
+
Open modal
|
|
202
|
+
</Button>
|
|
203
|
+
</Col>
|
|
204
|
+
</Row>
|
|
205
|
+
</Container>
|
|
206
|
+
);
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export const ConfirmationModal: Story = {
|
|
211
|
+
args: {
|
|
212
|
+
className: '',
|
|
213
|
+
onRequestClose: () => {
|
|
214
|
+
console.log('closed');
|
|
215
|
+
},
|
|
216
|
+
shouldCloseOnOverlayClick: true,
|
|
217
|
+
shouldCloseOnEsc: true,
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
render: (args) => {
|
|
221
|
+
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
222
|
+
|
|
223
|
+
const handleOpen = () => {
|
|
224
|
+
setIsOpen(true);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const handleClose = () => {
|
|
228
|
+
setIsOpen(false);
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
return (
|
|
232
|
+
<Container>
|
|
233
|
+
<Row>
|
|
234
|
+
<Col sm={4}>
|
|
235
|
+
<Modal {...args} isOpen={isOpen} onRequestClose={handleClose}>
|
|
236
|
+
<h2>Would you like to continue?</h2>
|
|
237
|
+
<p>
|
|
238
|
+
If you would like to proceed, please click the confirm button. Otherwise, click the
|
|
239
|
+
cancel button.
|
|
240
|
+
</p>
|
|
241
|
+
<hr />
|
|
242
|
+
<Row nogutter justify="end" align="center">
|
|
243
|
+
<Col xs="content">
|
|
244
|
+
<Button
|
|
245
|
+
onClick={() => {
|
|
246
|
+
console.log('cancelled');
|
|
247
|
+
handleClose();
|
|
248
|
+
}}
|
|
249
|
+
className="mr-2"
|
|
250
|
+
variant="outline"
|
|
251
|
+
ariaLabel="Cancel"
|
|
252
|
+
>
|
|
253
|
+
Cancel
|
|
254
|
+
</Button>
|
|
255
|
+
<Button
|
|
256
|
+
onClick={() => {
|
|
257
|
+
console.log('confirmed');
|
|
258
|
+
handleClose();
|
|
259
|
+
}}
|
|
260
|
+
ariaLabel="Confirm"
|
|
261
|
+
>
|
|
262
|
+
Confirm
|
|
263
|
+
</Button>
|
|
264
|
+
</Col>
|
|
265
|
+
</Row>
|
|
266
|
+
</Modal>
|
|
267
|
+
<Button ariaLabel="open modal" onClick={handleOpen}>
|
|
268
|
+
Open modal
|
|
269
|
+
</Button>
|
|
270
|
+
</Col>
|
|
271
|
+
</Row>
|
|
272
|
+
</Container>
|
|
273
|
+
);
|
|
274
|
+
},
|
|
275
|
+
};
|