Skip to content

MichaelOstermann/signals-modal

Repository files navigation

signals-modal

Minified Minzipped

Composable modal management.

Documentation

Example

const modal = createModal("key", () => {
    const { $status } = withModalStatus();

    const $anchorElement = withAnchorElement();
    const $anchorMeasurement = withAnchorMeasurement({
        $anchorElement,
        $status,
    });

    const $floatingElement = withFloatingElement();
    const $floatingMeasurement = withFloatingMeasurement({
        $floatingElement,
        $status,
    });

    const $boundary = withBoundary({
        $status,
        transform: (rect) => rect,
    });

    const $placement = withPlacement({
        placement: "down-center",
        $anchorMeasurement,
        $boundary,
        $floatingMeasurement,
    });

    const $position = withPosition({
        $anchorMeasurement,
        $boundary,
        $floatingMeasurement,
        $placement,
    });

    return {
        $anchorElement,
        $floatingElement,
        $position,
        $status,
    };
});

Installation

npm install @monstermann/signals-modal
pnpm add @monstermann/signals-modal
yarn add @monstermann/signals-modal
bun add @monstermann/signals-modal

Anchor

withAnchorElement

function withAnchorElement(
    anchorElement?: HTMLElement,
): Signal<HTMLElement | null>;

Assigns an anchor element to the current modal. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withAnchorElement,
    setAnchorElement,
    getAnchorElement,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withAnchorElement();
});

setAnchorElement("key", document.querySelector(".anchor"));
getAnchorElement("key"); // HTMLElement

withAnchorMeasurement

function withAnchorMeasurement(options: {
    $anchorElement: Reactive<HTMLElement | null>;
    $status: Reactive<ModalStatus>;
    transform?: (rect: Rect) => Rect;
}): Memo<Rect>;

Takes an anchor element and continuously measures its position while the modal is visible, to be used to position eg. a popover next to an element. This function must be called inside a createModal callback.

The optional transform option can be used to eg. make the anchor bigger, resulting with a margin between the anchor and floating popover.

Example

import {
    createModal,
    withAnchorElement,
    withModalStatus,
    withAnchorMeasurement,
    setAnchorElement,
    setModalStatus,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    const $anchorElement = withAnchorElement();
    // Memo({ top: number, left: number, width: number, height: number })
    const $anchorMeasurement = withAnchorMeasurement({
        $status,
        $anchorElement,
    });
});

setAnchorElement("key", document.querySelector(".anchor"));
setModalStatus("key", "opened");

withMouseAnchor

function withMouseAnchor(options: {
    $status: Reactive<ModalStatus>;
    transform?: (rect: Rect) => Rect;
}): Memo<Rect>;

This can be used to make the mouse cursor the anchor, instead of an element. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withModalStatus,
    withMouseAnchor,
    setModalStatus,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    // Memo({ top: number, left: number, width: number, height: number })
    const $anchorMeasurement = withMouseAnchor({ $status });
});

// Updates $anchorMeasurement to the current mouse coordinates (once).
setModalStatus("key", "opened");

Core

createModal

function createModal(
    key: string,
    setup: () => T,
): T & {
    key: string;
    dispose: () => void;
    isDisposed: () => boolean;
    onDispose: (dispose: MaybeDispose) => void;
};

Creates a new modal.

Example

import { createModal } from "@monstermann/signals-modal";

const modal = createModal("key", () => ({}));
modal.key;
modal.dispose();
modal.onDispose(callback);

currentModal

function currentModal(): {
    key: string;
    dispose: () => void;
    onDispose: (dispose: MaybeDispose) => void;
};

Retrieves the current modal.

Example

import { createModal, currentModal } from "@monstermann/signals-modal";

createModal(() => {
    const modal = currentModal();
});

onModalDisposed

const onModalDisposed: Emitter<string>;

An emitter that fires when a modal gets disposed. The emitted value is the modal key.

Example

import { createModal, onModalDisposed } from "@monstermann/signals-modal";

const modal = createModal("key", () => {});

const stopListening = onModalDisposed((key) => {
    console.log(`Modal ${key} disposed`);
});

modal.dispose();

stopListening();

Floating

withFloatingElement

function withFloatingElement(
    floatingElement?: HTMLElement,
): Signal<HTMLElement | null>;

Assigns an floating element to the current modal. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withFloatingElement,
    setFloatingElement,
    getFloatingElement,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withFloatingElement();
});

setFloatingElement("key", document.querySelector(".floating"));
getFloatingElement("key"); // HTMLElement

withFloatingMeasurement

function withFloatingMeasurement(options: {
    $floatingElement: Reactive<HTMLElement | null>;
    $status: Reactive<ModalStatus>;
    transform?: (rect: Rect) => Rect;
}): Memo<Rect>;

Takes an floating element and continuously measures its position while the modal is visible, to be used to position eg. a popover next to an element. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withFloatingElement,
    withModalStatus,
    withFloatingMeasurement,
    setFloatingElement,
    setModalStatus,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    const $floatingElement = withFloatingElement();
    // Memo({ top: number, left: number, width: number, height: number })
    const $floatingMeasurement = withFloatingMeasurement({
        $status,
        $floatingElement,
    });
});

setFloatingElement("key", document.querySelector(".floating"));
setModalStatus("key", "opened");

Groups

getDialogs

Reactive

function getDialogs(): ReadonlySet<string>;

Returns all dialog keys from the modalGroups.dialog group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    getDialogs,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.dialog]);
});

getDialogs(); // Set(["key"])

getGroupsForModal

Reactive

function getGroupsForModal(key: string): ReadonlySet<string>;

Returns all groups the given key belongs to.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    getGroupsForModal,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.dialog]);
});

getGroupsForModal("key"); // Set(["dialog"])

getModalsForGroup

Reactive

function getModalsForGroup(group: string): ReadonlySet<string>;

Returns all keys the given group belongs to.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    getModalsForGroup,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.dialog]);
});

getModalsForGroup(modalGroups.dialog); // Set(["key"])

getPopovers

Reactive

function getPopovers(): ReadonlySet<string>;

Returns all popover keys from the modalGroups.popover group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    getPopovers,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.popover]);
});

getPopovers(); // Set(["key"])

getTooltips

Reactive

function getTooltips(): ReadonlySet<string>;

Returns all tooltip keys from the modalGroups.tooltip group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    getTooltips,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.tooltip]);
});

getTooltips(); // Set(["key"])

isDialog

Reactive

function isDialog(key: string): boolean;

Returns a boolean indicating whether the given key belongs to the modalGroups.dialog group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    isDialog,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.popover]);
});

isDialog("key"); // true

isModalInGroup

Reactive

function isModalInGroup(key: string, group: string): boolean;

Returns a boolean indicating whether the given key belongs to the group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    isModalInGroup,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.popover]);
});

isModalInGroup("key", modalGroups.popover); // true

isPopover

Reactive

function isPopover(key: string): boolean;

Returns a boolean indicating whether the given key belongs to the modalGroups.popover group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    isPopover,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.popover]);
});

isPopover("key"); // true

isTooltip

Reactive

function isTooltip(key: string): boolean;

Returns a boolean indicating whether the given key belongs to the modalGroups.tooltip group.

Example

import {
    createModal,
    withModalGroups,
    modalGroups,
    isTooltip,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups([modalGroups.popover]);
});

isTooltip("key"); // true

modalGroups

const modalGroups = {
    dialog: "dialog",
    popover: "popover",
    tooltip: "tooltip",
};

A record containing common modal groups.

withModalGroups

function withModalGroups(groups: Iterable<string>): Memo<ReadonlySet<string>>;

Assigns the current modal to a list of groups. Can be used to for example mark the modal as a dialog/popover/tooltip. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withModalGroups,
    getDialogs,
    getGroupsForModal,
    getModalsForGroup,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalGroups(["dialog"]);
});

getGroupsForModal("key"); // Set(["dialog"])
getModalsForGroup("dialog"); // Set(["key"])

Position

withBoundary

function withBoundary(options: {
    $status: Reactive<ModalStatus>;
    transform?: (rect: Rect) => Rect;
}): Memo<Rect>;

Constructs a Rect resembling the window dimensions, to be fed into withPlacement and withPosition, used to constrain the floating element to be within the window boundary. This function must be called inside a createModal callback.

The optional transform option can be used to eg. make the Rect smaller, increasing the distance between the floating element and the edges of the window.

Example

import {
    createModal,
    withModalStatus,
    withBoundary,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    const $boundary = withBoundary({ $status });
});

withPlacement

function withPlacement(options: {
    placement: ModalPlacementOption;
    $boundary: () => Rect;
    $anchorMeasurement: () => Rect;
    $floatingMeasurement: () => Rect;
}): Memo<ModalPlacement>;

type ModalPlacementOption =
    | "vertical-center"
    | "vertical-left"
    | "vertical-right"
    | "horizontal-center"
    | "horizontal-up"
    | "horizontal-down"
    | "up-center"
    | "down-center"
    | "left-down"
    | "right-down";

type ModalPlacement =
    | "down-center"
    | "down-left"
    | "down-right"
    | "left-center"
    | "left-down"
    | "left-up"
    | "right-center"
    | "right-down"
    | "right-up"
    | "up-center"
    | "up-left"
    | "up-right";

Takes a ModalPlacementOption and resolves it to ModalPlacement, picking whichever side has more space. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withModalStatus,
    withAnchorElement,
    withAnchorMeasurement,
    withFloatingElement,
    withFloatingMeasurement,
    withBoundary,
    withPlacement,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    const $anchorElement = withAnchorElement();
    const $floatingElement = withFloatingElement();
    const $anchorMeasurement = withAnchorMeasurement({
        $status,
        $anchorElement,
    });
    const $floatingMeasurement = withFloatingMeasurement({
        $status,
        $floatingElement,
    });
    const $boundary = withBoundary({ $status });
    const $placement = withPlacement({
        placement: "vertical-center",
        $boundary,
        $anchorMeasurement,
        $floatingMeasurement,
    });
});

withPosition

function withPosition(options: {
    $boundary: () => Rect;
    $placement: () => ModalPlacement;
    $anchorMeasurement: () => Rect;
    $floatingMeasurement: () => Rect;
    transform?: (rect: Rect) => Rect;
}): Memo<{
    floatingX: number;
    floatingY: number;
    maxHeight: number;
    maxWidth: number;
    originX: number;
    originY: number;
}>;

Consumes a range of measurements and calculates the final position for the floating element. This function must be called inside a createModal callback.

Example

import {
    createModal,
    withModalStatus,
    withAnchorElement,
    withAnchorMeasurement,
    withFloatingElement,
    withFloatingMeasurement,
    withBoundary,
    withPlacement,
    withPosition,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    const $anchorElement = withAnchorElement();
    const $floatingElement = withFloatingElement();
    const $anchorMeasurement = withAnchorMeasurement({
        $status,
        $anchorElement,
    });
    const $floatingMeasurement = withFloatingMeasurement({
        $status,
        $floatingElement,
    });
    const $boundary = withBoundary({ $status });
    const $placement = withPlacement({
        placement: "vertical-center",
        $boundary,
        $anchorMeasurement,
        $floatingMeasurement,
    });
    const $position = withPosition({
        $boundary,
        $placement,
        $anchorMeasurement,
        $floatingMeasurement,
    });
});

Scroll

withCloseOnScroll

function withCloseOnScroll(options: {
    $anchorElement: Reactive<HTMLElement | null>;
    $status: Reactive<ModalStatus>;
}): void;

Automatically closes the modal when any scrollable ancestor of the anchor element is scrolled. This function must be called inside a createModal callback.

The function listens for scroll events on all scrollable parent elements of the anchor element and triggers a close when scrolling occurs. Scroll listeners are only active when the modal is opening or opened (not when closing or closed).

Example

import {
    createModal,
    withModalStatus,
    withAnchorElement,
    withCloseOnScroll,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    const $anchorElement = withAnchorElement();

    withCloseOnScroll({
        $status,
        $anchorElement,
    });
});

Status

closeAllModals

function closeAllModals(): void;

Closes all modals by setting their status to "closing". Skips modals that are already "closing" or "closed".

Example

import {
    createModal,
    withModalStatus,
    openModal,
    closeAllModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus();
});

openModal("modal1");
openModal("modal2");
closeAllModals();

closeModal

function closeModal(key: string): void;

Closes a modal by setting its status to "closing". Does nothing if the modal is already "closing" or "closed", or if the modal doesn't exist.

Example

import {
    createModal,
    withModalStatus,
    openModal,
    closeModal,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

openModal("key");
closeModal("key");

getClosedModals

Reactive

function getClosedModals(): string[];

Returns an array of all modal keys with status "closed".

Example

import {
    createModal,
    withModalStatus,
    getClosedModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus();
});

getClosedModals(); // ["modal1", "modal2"]

getClosingModals

Reactive

function getClosingModals(): string[];

Returns an array of all modal keys with status "closing".

Example

import {
    createModal,
    withModalStatus,
    closeModal,
    getClosingModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus("opened");
});

createModal("modal2", () => {
    withModalStatus("opened");
});

closeModal("modal1");
closeModal("modal2");

getClosingModals(); // ["modal1", "modal2"]

getModalStatus

Reactive

function getModalStatus(key: string): ModalStatus;

Retrieves the current status of a modal. Returns "closed" if the modal doesn't exist.

ModalStatus can be one of: "closed", "opening", "opened", or "closing".

Example

import {
    createModal,
    withModalStatus,
    getModalStatus,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

getModalStatus("key"); // "closed"

getOpenedModals

Reactive

function getOpenedModals(): string[];

Returns an array of all modal keys with status "opened".

Example

import {
    createModal,
    withModalStatus,
    getOpenedModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus("opened");
});

createModal("modal2", () => {
    withModalStatus("opened");
});

getOpenedModals(); // ["modal1", "modal2"]

getOpeningModals

Reactive

function getOpeningModals(): string[];

Returns an array of all modal keys with status "opening".

Example

import {
    createModal,
    withModalStatus,
    openModal,
    getOpeningModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus();
});

openModal("modal1");
openModal("modal2");

getOpeningModals(); // ["modal1", "modal2"]

getOpenModals

Reactive

function getOpenModals(): string[];

Returns an array of all modal keys with status "opening" or "opened".

Example

import {
    createModal,
    withModalStatus,
    getOpenModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus("opening");
});

createModal("modal2", () => {
    withModalStatus("opened");
});

createModal("modal3", () => {
    withModalStatus("closed");
});

getOpenModals(); // ["modal1", "modal2"]

getVisibleModals

Reactive

function getVisibleModals(): string[];

Returns an array of all modal keys that are visible (not "closed"). This includes "opening", "opened", and "closing" statuses.

Example

import {
    createModal,
    withModalStatus,
    openModal,
    getVisibleModals,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus();
});

openModal("modal1");
openModal("modal2");

getVisibleModals(); // ["modal1", "modal2"]

isAnyModalClosed

Reactive

function isAnyModalClosed(): boolean;

Returns true if any modal has status "closed".

Example

import {
    createModal,
    withModalStatus,
    isAnyModalClosed,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus("opened");
});

isAnyModalClosed(); // true

isAnyModalClosing

Reactive

function isAnyModalClosing(): boolean;

Returns true if any modal has status "closing".

Example

import {
    createModal,
    withModalStatus,
    closeModal,
    isAnyModalClosing,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus("opened");
});

createModal("modal2", () => {
    withModalStatus();
});

closeModal("modal1");

isAnyModalClosing(); // true

isAnyModalOpen

Reactive

function isAnyModalOpen(): boolean;

Returns true if any modal has status "opening" or "opened".

Example

import {
    createModal,
    withModalStatus,
    isAnyModalOpen,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus("opened");
});

isAnyModalOpen(); // true

isAnyModalOpened

Reactive

function isAnyModalOpened(): boolean;

Returns true if any modal has status "opened".

Example

import {
    createModal,
    withModalStatus,
    isAnyModalOpened,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus("opened");
});

isAnyModalOpened(); // true

isAnyModalOpening

Reactive

function isAnyModalOpening(): boolean;

Returns true if any modal has status "opening".

Example

import {
    createModal,
    withModalStatus,
    openModal,
    isAnyModalOpening,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus();
});

openModal("modal1");

isAnyModalOpening(); // true

isAnyModalVisible

Reactive

function isAnyModalVisible(): boolean;

Returns true if any modal is visible (not "closed"). This includes "opening", "opened", and "closing" statuses.

Example

import {
    createModal,
    withModalStatus,
    isAnyModalVisible,
} from "@monstermann/signals-modal";

createModal("modal1", () => {
    withModalStatus();
});

createModal("modal2", () => {
    withModalStatus("opened");
});

isAnyModalVisible(); // true

isModalClosed

Reactive

function isModalClosed(key: string): boolean;

Returns true if the modal's status is "closed" or if the modal doesn't exist.

Example

import {
    createModal,
    withModalStatus,
    isModalClosed,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

isModalClosed("key"); // true

isModalClosing

Reactive

function isModalClosing(key: string): boolean;

Returns true if the modal's status is "closing".

Example

import {
    createModal,
    withModalStatus,
    openModal,
    closeModal,
    isModalClosing,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    $status("opened");
});

closeModal("key");
isModalClosing("key"); // true

isModalOpen

Reactive

function isModalOpen(key: string): boolean;

Returns true if the modal's status is "opening" or "opened".

Example

import {
    createModal,
    withModalStatus,
    isModalOpen,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus("opening");
});

isModalOpen("key"); // true

isModalOpened

Reactive

function isModalOpened(key: string): boolean;

Returns true if the modal's status is "opened".

Example

import {
    createModal,
    withModalStatus,
    openModal,
    isModalOpened,
} from "@monstermann/signals-modal";

createModal("key", () => {
    const { $status } = withModalStatus();
    $status("opened");
});

isModalOpened("key"); // true

isModalOpening

Reactive

function isModalOpening(key: string): boolean;

Returns true if the modal's status is "opening".

Example

import {
    createModal,
    withModalStatus,
    openModal,
    isModalOpening,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

openModal("key");
isModalOpening("key"); // true

isModalVisible

Reactive

function isModalVisible(key: string): boolean;

Returns true if the modal is visible (not "closed"). This includes "opening", "opened", and "closing" statuses.

Example

import {
    createModal,
    withModalStatus,
    openModal,
    isModalVisible,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

openModal("key");
isModalVisible("key"); // true

onModalClosed

const onModalClosed: Emitter<string>;

An emitter that fires when a modal transitions to the "closed" status. The emitted value is the modal key.

Example

import {
    createModal,
    withModalStatus,
    onModalClosed,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

const stopListening = onModalClosed((key) => {
    console.log(`Modal ${key} closed`);
});

stopListening();

onModalClosing

const onModalClosing: Emitter<string>;

An emitter that fires when a modal transitions to the "closing" status. The emitted value is the modal key.

Example

import {
    createModal,
    withModalStatus,
    onModalClosing,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

const stopListening = onModalClosing((key) => {
    console.log(`Modal ${key} closing`);
});

stopListening();

onModalOpened

const onModalOpened: Emitter<string>;

An emitter that fires when a modal transitions to the "opened" status. The emitted value is the modal key.

Example

import {
    createModal,
    withModalStatus,
    onModalOpened,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

const stopListening = onModalOpened((key) => {
    console.log(`Modal ${key} opened`);
});

stopListening();

onModalOpening

const onModalOpening: Emitter<string>;

An emitter that fires when a modal transitions to the "opening" status. The emitted value is the modal key.

Example

import {
    createModal,
    withModalStatus,
    onModalOpening,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

const stopListening = onModalOpening((key) => {
    console.log(`Modal ${key} opening`);
});

stopListening();

openModal

function openModal(key: string): void;

Opens a modal by setting its status to "opening". Does nothing if the modal is already "opening" or "opened", or if the modal doesn't exist.

Example

import {
    createModal,
    withModalStatus,
    openModal,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

openModal("key");

setModalStatus

function setModalStatus(key: string, status: ModalStatus): void;

Sets the status of a modal. Does nothing if the modal doesn't exist.

ModalStatus can be one of: "closed", "opening", "opened", or "closing".

Example

import {
    createModal,
    withModalStatus,
    setModalStatus,
} from "@monstermann/signals-modal";

createModal("key", () => {
    withModalStatus();
});

setModalStatus("key", "opened");

withModalStatus

function withModalStatus(status: ModalStatus = "closed"): {
    $status: Signal<ModalStatus>;
    $isOpen: Memo<boolean>;
    close: () => void;
    open: () => void;
};

Creates and returns a status signal for the current modal. This function must be called inside a createModal callback.

The optional status parameter sets the initial status of the modal (defaults to "closed").

ModalStatus can be one of: "closed", "opening", "opened", or "closing".

Example

import { createModal, withModalStatus } from "@monstermann/signals-modal";

// Default to "closed"
createModal("modal1", () => {
    const { $status } = withModalStatus();
    console.log($status()); // "closed"
});

// Start with a different initial status
createModal("modal2", () => {
    const { $status } = withModalStatus("opened");
    console.log($status()); // "opened"

    // Update the status
    $status("closing");
});

About

Composable modal management.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors