Skip to content

Commit

Permalink
feat: modal sizes
Browse files Browse the repository at this point in the history
  • Loading branch information
abelflopes committed Jul 21, 2024
1 parent 6ba53a8 commit 33a7126
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 92 deletions.
10 changes: 5 additions & 5 deletions packages/components/container/src/styles/_variables.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
$container-width-large: 1300px;

$container-width-medium: 800px;

$container-width-small: 450px;
$container-sizes: (
s: 450px,
m: 800px,
l: 1300px,
);
14 changes: 4 additions & 10 deletions packages/components/container/src/styles/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,10 @@

// Container size

.size_l {
@include define-css-var(container, max-width, shared.$container-width-large);
}

.size_m {
@include define-css-var(container, max-width, shared.$container-width-medium);
}

.size_s {
@include define-css-var(container, max-width, shared.$container-width-small);
@each $key, $value in shared.$container-sizes {
.size_#{$key} {
@include define-css-var(container, max-width, $value);
}
}

// Container Spacing Vertical
Expand Down
124 changes: 55 additions & 69 deletions packages/components/modal/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ import { ModalFooter } from "./ModalFooter";
*/

interface ModalProps extends React.HTMLAttributes<HTMLDivElement> {
/** Modal width */
size?: "s" | "m" | "l" | "xl" | "full";
/** Determines whether the modal is open or closed */
open?: boolean;
/** Determines if the modal can be dismissed by clicking outside or close button */
dismissible?: boolean;
/** Dismiss Callback, also determines if the modal can be dismissed by clicking outside or close button */
onDismiss?: () => void;
}

// TODO: add a11y https://react.dev/reference/react-dom/createPortal#rendering-a-modal-dialog-with-a-portal

// TODO: create scroll lock utility
let openModals = 0;

/**
Expand All @@ -37,16 +39,12 @@ let openModals = 0;
*/

const Modal = ({
open = true,
dismissible = true,
size = "m",
children,
className,
onDismiss,
...otherProps
}: Readonly<ModalProps>): React.ReactNode => {
// Internal open state, allows component to be uncontrolled
const [internalOpen, setInternalOpen] = useState(open);

// State child compound components' props
const [props, setProps] = useState<ModalContextValue>({
header: undefined,
Expand All @@ -58,13 +56,6 @@ const Modal = ({
setProps((v) => ({ ...v, ...value }));
}, []);

// Close callback
const handleClose = useCallback(() => {
if (!dismissible) return;
setInternalOpen(false);
onDismiss?.();
}, [dismissible, onDismiss]);

// Build context for child compound components
const contextProps = useMemo<ModalContextProps>(
() => ({
Expand All @@ -73,68 +64,63 @@ const Modal = ({
[setContextValue],
);

// Synchronize internal state with external state
useEffect(() => {
setInternalOpen(open);

if (!open) onDismiss?.();
}, [onDismiss, open]);

// Lock scroll if there are open modals
useEffect(() => {
if (internalOpen) openModals += 1;
else openModals -= 1;
openModals += 1;

if (openModals > 1) document.body.classList.add(`${styles.lock_scroll}`);
else document.body.classList.remove(`${styles.lock_scroll}`);
}, [internalOpen]);

return () => {
openModals -= 1;

if (openModals === 0) document.body.classList.remove(`${styles.lock_scroll}`);
};
}, []);

return (
internalOpen && (
<Layer elevation="overlay">
<div {...otherProps} className={classNames(styles.root, className)}>
<Overlay
className={classNames(dismissible && styles.clickable_overlay)}
onClick={handleClose}
/>

<div className={styles.card}>
<ModalContext.Provider value={contextProps}>
{props.header ? (
<header
{...props.header}
className={classNames(styles.header, props.header.className)}>
<Text variation="h3" as="p" margin="none">
{props.header.heading}
</Text>

{dismissible ? (
<Button
skin="ghost"
icon={
<Icon>
<IconClose />
</Icon>
}
onClick={handleClose}
/>
) : null}
</header>
) : null}

<ScrollableContainer>{children}</ScrollableContainer>

{props.footer ? (
<footer
{...props.footer}
className={classNames(styles.footer, props.footer.className)}
/>
) : null}
</ModalContext.Provider>
</div>
<Layer elevation="overlay">
<div {...otherProps} className={classNames(styles.root, className)}>
<Overlay
className={classNames(onDismiss && styles.clickable_overlay)}
onClick={onDismiss}
/>

<div className={classNames(styles.card, `${styles[`size_${size}`]}`)}>
<ModalContext.Provider value={contextProps}>
{props.header ? (
<header
{...props.header}
className={classNames(styles.header, props.header.className)}>
<Text variation="h3" as="p" margin="none">
{props.header.heading}
</Text>

{onDismiss ? (
<Button
skin="ghost"
icon={
<Icon>
<IconClose />
</Icon>
}
onClick={onDismiss}
/>
) : null}
</header>
) : null}

<ScrollableContainer>{children}</ScrollableContainer>

{props.footer ? (
<footer
{...props.footer}
className={classNames(styles.footer, props.footer.className)}
/>
) : null}
</ModalContext.Provider>
</div>
</Layer>
)
</div>
</Layer>
);
};

Expand Down
9 changes: 9 additions & 0 deletions packages/components/modal/src/styles/_variables.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@use "@react-ck/container";
@use "@react-ck/scss-utils";

$modal-sizes: (
s: scss-utils.map-get-strict(container.$container-sizes, s),
m: scss-utils.map-get-strict(container.$container-sizes, m) * 0.7,
l: scss-utils.map-get-strict(container.$container-sizes, m),
xl: scss-utils.map-get-strict(container.$container-sizes, l),
);
26 changes: 18 additions & 8 deletions packages/components/modal/src/styles/index.module.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
@use "@react-ck/card";
@use "@react-ck/container";

@use "variables";
@import "@react-ck/theme";
@import "@react-ck/elevation";

@keyframes appear {
0% {
opacity: 0;
}

100% {
opacity: 1;
}
Expand All @@ -21,14 +21,14 @@
top: 0;
left: 0;
display: flex;
overflow: hidden;
width: 100%;
height: 100%;
box-sizing: border-box;
align-items: center;
justify-content: center;
animation: appear 0.3s ease-in forwards;
padding: calc(get-css-var(modal, spacing) * 2);
box-sizing: border-box;
overflow: hidden;
animation: appear 0.3s ease-in forwards;
}

// Add to document body to prevent back scrolling
Expand All @@ -45,12 +45,22 @@
@include card.base;
@include card.skin-shadowed;

display: flex;
flex-direction: column;
position: relative; // Bring to front (z-index)
display: flex;
width: 100%;
max-height: 100%;
flex-direction: column;
padding: get-css-var(modal, spacing);
max-width: container.$container-width-large;
}

@each $key, $value in variables.$modal-sizes {
.size_#{$key} {
max-width: $value;
}
}

.size_full {
max-width: 100%;
}

.header {
Expand Down

0 comments on commit 33a7126

Please sign in to comment.