ワンクリックで
implement-modus-modal-with-refs
// Create Modus modals using the callback ref pattern for programmatic control
// Create Modus modals using the callback ref pattern for programmatic control
Scaffold form components with proper Modus input integration, event handling, validation, and checkbox bug handling
Scaffold a new Modus wrapper component following established SolidJS patterns with proper TypeScript interfaces, event handling, and cleanup
Debug and fix common event handling problems with Modus web components
Apply the critical checkbox value inversion workaround when working with ModusCheckbox components
Help with correct Modus icon usage patterns including naming conventions, sizing, and accessibility
Build production-grade frontend interfaces using the Modus 2.0 Design System with Tailwind CSS. Use this skill when the user asks to build web components, pages, dashboards, or application screens. Enforces the 9-color semantic system, Modus Web Components, Modus Icons, and design system compliance. Framework-agnostic (works with SolidJS, React, Angular, or any framework).
| name | implement-modus-modal-with-refs |
| description | Create Modus modals using the callback ref pattern for programmatic control |
Create Modus modal components using the callback ref pattern for programmatic control in SolidJS.
Use this skill when:
Modus modals in SolidJS require:
ref) to expose methods to parent componentsonMount to call the ref callback with { openModal, closeModal }querySelector("dialog") to access the native dialog elementonCleanupSee src/components/ModusModal.tsx for the complete implementation.
import { onCleanup, onMount } from "solid-js";
import type { Component, JSX } from "solid-js";
interface ModusModalProps {
modalId: string;
ariaLabel?: string;
backdrop?: "default" | "static";
position?: "top" | "center" | "bottom";
fullscreen?: boolean;
showFullscreenToggle?: boolean;
showClose?: boolean;
customClass?: string;
header?: JSX.Element;
children: JSX.Element;
footer?: JSX.Element;
onClose?: () => void;
ref?: (handle: ModusModalRef) => void;
}
export interface ModusModalRef {
openModal: () => void;
closeModal: () => void;
}
const ModusModal: Component<ModusModalProps> = (props) => {
let modalEl: HTMLModusWcModalElement | undefined;
const openModal = () => {
if (modalEl) {
const dialog = modalEl.querySelector("dialog") as HTMLDialogElement;
if (dialog) dialog.showModal();
}
};
const closeModal = () => {
if (modalEl) {
const dialog = modalEl.querySelector("dialog") as HTMLDialogElement;
if (dialog) dialog.close();
}
};
onMount(() => {
props.ref?.({ openModal, closeModal });
const modal = modalEl;
if (modal) {
const handleClose = () => props.onClose?.();
const dialogElement = modal.querySelector("dialog");
if (dialogElement) {
dialogElement.addEventListener("close", handleClose);
onCleanup(() => {
dialogElement.removeEventListener("close", handleClose);
});
}
}
});
return (
<modus-wc-modal
ref={(el) => (modalEl = el)}
modal-id={props.modalId}
aria-label={props.ariaLabel}
backdrop={props.backdrop ?? "default"}
position={props.position ?? "center"}
fullscreen={props.fullscreen ?? false}
show-fullscreen-toggle={props.showFullscreenToggle ?? false}
show-close={props.showClose ?? true}
custom-class={props.customClass}
>
{props.header && <div slot="header">{props.header}</div>}
<div slot="content">{props.children}</div>
{props.footer && <div slot="footer">{props.footer}</div>}
</modus-wc-modal>
);
};
export default ModusModal;
import { createSignal } from "solid-js";
import ModusButton from "./components/ModusButton";
import ModusModal, { type ModusModalRef } from "./components/ModusModal";
function MyComponent() {
let modalHandle: ModusModalRef | undefined;
return (
<>
<ModusButton
onButtonClick={() => {
modalHandle?.openModal();
}}
>
Open Modal
</ModusButton>
<ModusModal
ref={(handle) => (modalHandle = handle)}
modalId="my-modal"
ariaLabel="Example modal"
onClose={() => {
console.log("Modal closed");
}}
header={
<div class="text-xl font-semibold text-foreground">
Modal Title
</div>
}
footer={
<div class="flex gap-2">
<ModusButton
variant="borderless"
onButtonClick={() => {
modalHandle?.closeModal();
}}
>
Cancel
</ModusButton>
<ModusButton
onButtonClick={() => {
modalHandle?.closeModal();
}}
>
Confirm
</ModusButton>
</div>
}
>
<div class="text-sm text-foreground opacity-80">
Modal content goes here.
</div>
</ModusModal>
</>
);
}
// Parent stores handle
let modalHandle: ModusModalRef | undefined;
// Modal passes handle via ref callback
<ModusModal ref={(handle) => (modalHandle = handle)} ... />
onMount(() => {
props.ref?.({ openModal, closeModal });
// ...
});
const openModal = () => {
if (modalEl) {
const dialog = modalEl.querySelector("dialog") as HTMLDialogElement;
if (dialog) {
dialog.showModal();
}
}
};
Critical: Always use querySelector("dialog") - don't try to access dialog methods directly on the web component.
Modus modals use slots for content:
<modus-wc-modal>
{props.header && <div slot="header">{props.header}</div>}
<div slot="content">{props.children}</div>
{props.footer && <div slot="footer">{props.footer}</div>}
</modus-wc-modal>
onMount(() => {
const modal = modalEl;
if (modal) {
const dialogElement = modal.querySelector("dialog");
if (dialogElement) {
dialogElement.addEventListener("close", handleClose);
onCleanup(() => {
dialogElement.removeEventListener("close", handleClose);
});
}
}
});
querySelector("dialog"), not direct property accessmodalEl before useclose event on dialog element, not web componentonCleanup to remove event listenerssrc/components/ModusModal.tsx - Complete implementationsrc/demos/modal-demo/page.tsx - Usage examples