Merge pull request 'ui/modal: refactor mounting and controlled state' (#4807) from render-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4807
This commit is contained in:
@@ -35,3 +35,11 @@
|
|||||||
.header_divider {
|
.header_divider {
|
||||||
@apply bg-def-3 h-[6px] border-def-2 border-t-[1px];
|
@apply bg-def-3 h-[6px] border-def-2 border-t-[1px];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.backdrop {
|
||||||
|
@apply absolute left-0 top-0 z-50 size-full bg-white/90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contentWrapper {
|
||||||
|
@apply absolute left-0 top-0 z-50 flex size-full items-center justify-center;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, createSignal, JSX, Show } from "solid-js";
|
import { Component, JSX, Show } from "solid-js";
|
||||||
import { Dialog as KDialog } from "@kobalte/core/dialog";
|
import { Dialog as KDialog } from "@kobalte/core/dialog";
|
||||||
import styles from "./Modal.module.css";
|
import styles from "./Modal.module.css";
|
||||||
import { Typography } from "../Typography/Typography";
|
import { Typography } from "../Typography/Typography";
|
||||||
@@ -19,53 +19,58 @@ export interface ModalProps {
|
|||||||
class?: string;
|
class?: string;
|
||||||
metaHeader?: Component;
|
metaHeader?: Component;
|
||||||
disablePadding?: boolean;
|
disablePadding?: boolean;
|
||||||
|
open: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Modal = (props: ModalProps) => {
|
export const Modal = (props: ModalProps) => {
|
||||||
const [open, setOpen] = createSignal(true);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KDialog id={props.id} open={open()} modal={true}>
|
<Show when={props.open}>
|
||||||
<KDialog.Portal mount={props.mount}>
|
<KDialog id={props.id} open={props.open} modal={true}>
|
||||||
<KDialog.Content class={cx(styles.modal_content, props.class)}>
|
<KDialog.Portal mount={props.mount}>
|
||||||
<div class={styles.modal_header}>
|
<div class={styles.backdrop} />
|
||||||
<Typography
|
<div class={styles.contentWrapper}>
|
||||||
class={styles.modal_title}
|
<KDialog.Content class={cx(styles.modal_content, props.class)}>
|
||||||
hierarchy="label"
|
<div class={styles.modal_header}>
|
||||||
family="mono"
|
<Typography
|
||||||
size="xs"
|
class={styles.modal_title}
|
||||||
>
|
hierarchy="label"
|
||||||
{props.title}
|
family="mono"
|
||||||
</Typography>
|
size="xs"
|
||||||
<KDialog.CloseButton
|
>
|
||||||
onClick={() => {
|
{props.title}
|
||||||
setOpen(false);
|
</Typography>
|
||||||
props.onClose();
|
<KDialog.CloseButton
|
||||||
}}
|
onClick={() => {
|
||||||
>
|
props.onClose();
|
||||||
<Icon icon="Close" size="0.75rem" />
|
}}
|
||||||
</KDialog.CloseButton>
|
>
|
||||||
|
<Icon icon="Close" size="0.75rem" />
|
||||||
|
</KDialog.CloseButton>
|
||||||
|
</div>
|
||||||
|
<Show when={props.metaHeader}>
|
||||||
|
{(metaHeader) => (
|
||||||
|
<>
|
||||||
|
<div class="flex h-9 items-center px-6 py-2 bg-def-1">
|
||||||
|
<Dynamic component={metaHeader()} />
|
||||||
|
</div>
|
||||||
|
<div class={styles.header_divider} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Show>
|
||||||
|
<div
|
||||||
|
class={styles.modal_body}
|
||||||
|
data-no-padding={props.disablePadding}
|
||||||
|
>
|
||||||
|
{props.children({
|
||||||
|
close: () => {
|
||||||
|
props.onClose();
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</KDialog.Content>
|
||||||
</div>
|
</div>
|
||||||
<Show when={props.metaHeader}>
|
</KDialog.Portal>
|
||||||
{(metaHeader) => (
|
</KDialog>
|
||||||
<>
|
</Show>
|
||||||
<div class="flex h-9 items-center px-6 py-2 bg-def-1">
|
|
||||||
<Dynamic component={metaHeader()} />
|
|
||||||
</div>
|
|
||||||
<div class={styles.header_divider} />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Show>
|
|
||||||
<div class={styles.modal_body} data-no-padding={props.disablePadding}>
|
|
||||||
{props.children({
|
|
||||||
close: () => {
|
|
||||||
setOpen(false);
|
|
||||||
props.onClose();
|
|
||||||
},
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</KDialog.Content>
|
|
||||||
</KDialog.Portal>
|
|
||||||
</KDialog>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ const MockCreateMachine = (props: MockProps) => {
|
|||||||
return (
|
return (
|
||||||
<div ref={(el) => (container = el)} class="create-backdrop">
|
<div ref={(el) => (container = el)} class="create-backdrop">
|
||||||
<Modal
|
<Modal
|
||||||
|
open={true}
|
||||||
mount={container!}
|
mount={container!}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
reset(form);
|
reset(form);
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { Component, createEffect, on } from "solid-js";
|
import { Component, createEffect, on } from "solid-js";
|
||||||
import { RouteSectionProps, useNavigate } from "@solidjs/router";
|
import { RouteSectionProps, useNavigate } from "@solidjs/router";
|
||||||
import { activeClanURI, setActiveClanURI } from "@/src/stores/clan";
|
import { activeClanURI } from "@/src/stores/clan";
|
||||||
import { navigateToClan } from "@/src/hooks/clan";
|
import { navigateToClan } from "@/src/hooks/clan";
|
||||||
import { Button } from "../components/Button/Button";
|
|
||||||
|
|
||||||
export const Layout: Component<RouteSectionProps> = (props) => {
|
export const Layout: Component<RouteSectionProps> = (props) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|||||||
@@ -69,17 +69,14 @@ export const Machine = (props: RouteSectionProps) => {
|
|||||||
>
|
>
|
||||||
Install me!
|
Install me!
|
||||||
</Button>
|
</Button>
|
||||||
|
{/* Unmount the whole component to destroy the store and form values */}
|
||||||
<Show when={showInstall()}>
|
<Show when={showInstall()}>
|
||||||
<div
|
<InstallModal
|
||||||
class="absolute left-0 top-0 z-50 flex size-full items-center justify-center bg-white/90"
|
open={showInstall()}
|
||||||
ref={(el) => (container = el)}
|
machineName={useMachineName()}
|
||||||
>
|
mount={container!}
|
||||||
<InstallModal
|
onClose={() => setShowModal(false)}
|
||||||
machineName={useMachineName()}
|
/>
|
||||||
mount={container!}
|
|
||||||
onClose={() => setShowModal(false)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Show>
|
</Show>
|
||||||
{sidebarPane(useMachineName())}
|
{sidebarPane(useMachineName())}
|
||||||
</Show>
|
</Show>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ export interface InstallModalProps {
|
|||||||
initialStep?: InstallSteps[number]["id"];
|
initialStep?: InstallSteps[number]["id"];
|
||||||
mount?: Node;
|
mount?: Node;
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
|
open: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const steps = [
|
const steps = [
|
||||||
@@ -85,12 +86,12 @@ export const InstallModal = (props: InstallModalProps) => {
|
|||||||
<StepperProvider stepper={stepper}>
|
<StepperProvider stepper={stepper}>
|
||||||
<Modal
|
<Modal
|
||||||
class="h-[30rem] w-screen max-w-3xl"
|
class="h-[30rem] w-screen max-w-3xl"
|
||||||
mount={props.mount}
|
|
||||||
title="Install machine"
|
title="Install machine"
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
console.log("Install modal closed");
|
console.log("Install modal closed");
|
||||||
props.onClose?.();
|
props.onClose?.();
|
||||||
}}
|
}}
|
||||||
|
open={props.open}
|
||||||
// @ts-expect-error some steps might not have
|
// @ts-expect-error some steps might not have
|
||||||
metaHeader={stepper.currentStep()?.title ? <MetaHeader /> : undefined}
|
metaHeader={stepper.currentStep()?.title ? <MetaHeader /> : undefined}
|
||||||
// @ts-expect-error some steps might not have
|
// @ts-expect-error some steps might not have
|
||||||
|
|||||||
Reference in New Issue
Block a user