Skip to content

Commit 4b4787d

Browse files
committed
feat: update modal component
- show modal overlay with pointer cursor when clickable - increase spacing - add internal & external open states, allowing to be uncontrolled - add open & close handlers
1 parent ba355c3 commit 4b4787d

File tree

2 files changed

+53
-30
lines changed

2 files changed

+53
-30
lines changed

packages/components/modal/src/Modal.tsx

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import classNames from "classnames";
22
import styles from "./styles/index.module.scss";
3-
import React, { useCallback, useMemo, useState } from "react";
3+
import React, { useCallback, useEffect, useMemo, useState } from "react";
44
import { ModalContext, type ModalContextProps, type ModalContextValue } from "./context";
55
import { Card } from "@react-ck/card";
66
import { Overlay } from "@react-ck/overlay";
@@ -40,33 +40,51 @@ export const Modal = ({
4040
[setContextValue],
4141
);
4242

43+
// Invoke open / close handlers
44+
useEffect(() => {
45+
if (internalOpen) onOpen?.();
46+
else onClose?.();
47+
}, [internalOpen, onClose, onOpen]);
48+
49+
// Synchronize internal state with external state
50+
useEffect(() => {
51+
setInternalOpen(open);
52+
}, [open]);
53+
4354
return (
44-
<Layer elevation="overlay">
45-
<div {...otherProps} className={classNames(styles.root, className)}>
46-
<Overlay />
47-
<Card className={styles.card}>
48-
<ModalContext.Provider value={contextProps}>
49-
{props.header && (
50-
<header
51-
{...props.header}
52-
className={classNames(styles.header, props.header.className)}>
53-
<Text type="h3" as="p" margin={false}>
54-
{props.header.heading}
55-
</Text>
55+
internalOpen && (
56+
<Layer elevation="overlay">
57+
<div {...otherProps} className={classNames(styles.root, className)}>
58+
<Overlay
59+
className={classNames(dismissable && styles.clickable_overlay)}
60+
onClick={handleClose}
61+
/>
62+
<Card className={styles.card}>
63+
<ModalContext.Provider value={contextProps}>
64+
{props.header && (
65+
<header
66+
{...props.header}
67+
className={classNames(styles.header, props.header.className)}>
68+
<Text type="h3" as="p" margin={false}>
69+
{props.header.heading}
70+
</Text>
5671

57-
<Button skin="ghost" icon={<Icon name="close" />} />
58-
</header>
59-
)}
60-
<main className={styles.content}>{children}</main>
61-
{props.footer && (
62-
<footer
63-
{...props.footer}
64-
className={classNames(styles.footer, props.footer.className)}
65-
/>
66-
)}
67-
</ModalContext.Provider>
68-
</Card>
69-
</div>
70-
</Layer>
72+
{dismissable && (
73+
<Button skin="ghost" icon={<Icon name="close" />} onClick={handleClose} />
74+
)}
75+
</header>
76+
)}
77+
<main className={styles.content}>{children}</main>
78+
{props.footer && (
79+
<footer
80+
{...props.footer}
81+
className={classNames(styles.footer, props.footer.className)}
82+
/>
83+
)}
84+
</ModalContext.Provider>
85+
</Card>
86+
</div>
87+
</Layer>
88+
)
7189
);
7290
};

packages/components/modal/src/styles/index.module.scss

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@import "@react-ck/theme";
22

33
.root {
4-
@include define-css-var(modal, spacing, get-spacing(4));
4+
@include define-css-var(modal, spacing, get-spacing(5));
55

66
display: flex;
77
align-items: center;
@@ -13,6 +13,10 @@
1313
width: 100%;
1414
}
1515

16+
.clickable_overlay {
17+
cursor: pointer;
18+
}
19+
1620
.card {
1721
position: relative;
1822
}
@@ -22,12 +26,13 @@
2226
align-items: center;
2327
justify-content: space-between;
2428
gap: get-css-var(modal, spacing);
25-
padding-bottom: get-css-var(modal, spacing);
29+
margin-bottom: get-css-var(modal, spacing);
2630
}
2731

2832
.footer {
2933
display: flex;
3034
align-items: center;
35+
justify-content: flex-end;
3136
gap: get-css-var(modal, spacing);
32-
padding-top: get-css-var(modal, spacing);
37+
margin-top: get-css-var(modal, spacing);
3338
}

0 commit comments

Comments
 (0)