Appearance
Modal โ
A centered overlay dialog with header / title / subtitle / body / footer slots, six content sizes, ten theme colours, and a modelValue binding contract that matches drawer / popover / toast. Renders into a body portal to escape transformed ancestors and stays fully invisible while closed (no shadow halo bleed). Toggle Vue / CSS to switch the live demo and source together.
The look is Basecoat's .dialog (see Theme): one padded box โ the panel carries p-6 and gap-6 and the header / body / footer are unpadded, unbordered, untinted regions inside it โ on bg-popover with a ring-1 ring-foreground/10 edge and rounded-xl, over a bg-black/10 backdrop-blur-xs scrim. The tinted gradient header bar, the tinted footer and both divider rules are gone; --mono-modal-header-bg / -footer-bg (+ the matching -border / -border-width / -pad) put them back. Dark mode is built in.
Basic โ
Simple modal with a title, a subtitle (the muted description line under it โ hidden when empty), a body, and the close button.
Vue SFC
Header & footer slots โ
The header is a row: a heading column (title over subtitle) and the close โ beside it. The slots are:
| Slot | Alias | Renders |
|---|---|---|
header | head | Replaces the whole heading column โ title and subtitle. Beats the title / subtitle slots and props. The โ stays |
title | โ | Replaces the title line (beats the title prop) |
subtitle | โ | Replaces the subtitle line (beats the subtitle prop) |
body | (default slot) | Main content โ unslotted children land here |
footer | foot | Action row under the body |
header and footer are the preferred names and match mono-drawer, which has the same header model. The original head and foot still work, so existing markup keeps rendering. If you supply both spellings for the same region, the alias wins (header beats head) and the other is ignored. The header shows whenever there is a title, a subtitle, a header slot or the โ.
Changed
slot="header" / slot="head" used to replace the entire header row, close โ included. It now replaces only the title + subtitle column and the โ stays, matching the drawer. Use :dismissible="false" to drop the โ (that also disables dismissal), and remove a hand-rolled close button from your header content if you had one.
Vue SFC
Sizes โ
size sets the content scale โ header/title type, body type, padding, the close button and the corner radius โ across xs, sm, md (default), lg, xl and xxl. It does not change the panel width: every panel in the demo below is the same width. Use width for that โ it takes the same xsโฆxxl tokens, so size="sm" width="xl" gives you a compact, wide dialog.
Changed
size used to be a width preset (sm 380px โฆ xl 880px) and did nothing to the type scale. Panels that relied on size for their measure should now pass width instead.
Vue SFC
Width & height โ
For full control, set width, height, min-width, max-width, min-height or max-height directly. Each accepts:
- a preset token โ
xs,sm,md,lg,xl,xxl(see below); - a CSS string โ
"760px","12rem","80%"; - a number, treated as
pxโ:width="480"โ480px.
Both kebab-case (min-width) and camelCase (minWidth) work. Set both width and height to "100%" for true full screen.
Dimension presets โ
width="lg" is shorthand for a stock measure, so you rarely have to pick pixel values. Widths carry the same viewport clamp as the default, so no preset can overflow a phone; heights are viewport-relative and match the drawer's ladder.
| token | width / min-width / max-width | height / min-height / max-height |
|---|---|---|
xs | min(90vw, 300px) | 22vh |
sm | min(90vw, 380px) | 30vh |
md | min(90vw, 520px) โ the default width | 50vh |
lg | min(90vw, 680px) | 70vh |
xl | min(95vw, 880px) | 85vh |
xxl | min(95vw, 1080px) | 95vh |
These tokens are spelled the same as size but are a different axis: size scales the content, these name a measure. Mixing them is the point โ <mono-modal size="sm" width="xl"> is a compact, wide dialog.
Vue SFC
Auto full-screen โ
Set auto-fullscreen and the modal fills the screen on small viewports. It defaults to sm (under 640px); pass md, lg, xl or 2xl to move the boundary. Any authored width / height is overridden while it applies and restored above it.
Scroll lock โ
While open, a modal locks page scroll โ lock-scroll, default true. Opt out with :lock-scroll="false" when the page behind should stay scrollable.
vue
<mono-modal v-model="open" :lock-scroll="false" />The lock is shared, not per-instance: overlapping overlays (a modal opened from a drawer, stacked modals, a sidebar) all draw on one lock, so scroll is released only when the last one that wanted it closes. mono-sidebar takes the same prop.
It is the document root that gets overflow: hidden (the body too, but that is not the part that matters). The body's overflow only reaches the viewport while the root's computed overflow is visible โ CSS Overflow ยง3.5 โ so any reset that gives html an overflow of its own cancels the propagation and a body-only lock does nothing at all. Vuetify's reset ships html { overflow-y: scroll }; ress and sanitize.css do the same. Locking the root is immune to it.
The declaration is written !important on the element itself, because a normal inline style loses to a stylesheet that claims the root's overflow with !important โ and apps do that: Vuetify's own scroll block is .v-overlay-scroll-blocked:not(html) { overflow-y: hidden !important }, and a layout that drives <html class> (.overflow-auto { overflow: auto !important }) pins it for the life of the page. That failure is silent in the worst way: documentElement.style.overflow reads "hidden", so every style assertion passes while the page keeps scrolling, because the computed value never changed. An important declaration in the style attribute outranks an important one from a selector, so it cannot be out-cascaded. Whatever was there before โ value and priority โ is put back exactly on close.
The scrollbar goes away with it, and its width is handed back to the body as padding-right so nothing shifts sideways โ measured first, because a system with overlay scrollbars has no width to give back and compensating there would itself be the shift. Deliberately not scrollbar-gutter: stable, which reserves the space in one declaration but leaves Chrome painting the empty scrollbar track: the page then still looks like it has a scrollbar, which is usually the whole complaint.
iOS
overflow: hidden does not stop touch scrolling in iOS Safari. Locking there needs position: fixed plus scroll-position save/restore, which brings its own problems (lost position, focus jumps), so the modal does not attempt it.
Stacked โ
Set stackable to let modals stack โ open a modal from inside another, any depth. Each new modal sits above the previous, only one backdrop dims the screen, and Esc / overlay-click affect only the topmost. Without stackable a modal is exclusive: opening one closes any other open modal.
Vue SFC
Z-index โ
By default the modal takes its stacking level from mono's shared popup stack, so the newest layer is always on top. Set z-index to pin it instead โ for sitting above (or below) something the host app already positions, like a sticky header or a third-party widget. Accepts z-index="1500", :z-index="1500" and :zIndex="1500".
The value is the level of the whole dialog: .mono-modal is position: fixed and carries the z-index, so it forms a stacking context and the panel's internal +1 only orders it against its own overlay. Anything outside the modal has to clear the value itself.
Popups opened inside a pinned modal โ a mono-select, a mono-button-dropdown, a table menu โ stack above it automatically: the shared stack resumes its chain from the pinned level rather than from its base. The lower-level --mono-modal-z CSS variable does not get that treatment; set it and you own the whole chain.
Vue SFC
Draggable โ
Set draggable to let users move the modal by its header โ handy with stacked modals to slide the top one aside and see what's behind. The panel follows the pointer freely while dragging, but snaps back fully inside the viewport when you drop it.
Vue SFC
Colors โ
Pick a colour, then open the modal: the panel's thin ring and a faint glow under it take the colour, as do the close-button hover and a restored bar โ it re-paints live, so re-pick while it is open. Without color the ring stays neutral and there is no glow.
Vue SFC
Confirmation โ
Cancel + Confirm footer that triggers a status update.
Vue SFC
Form โ
Modal containing an input + submit button.
Vue SFC
Controller โ
controlMonoModal() (also exported as monoModal) drives a modal from code, the way controlMonoForm drives a form. Bind it with :control-modal.prop and the modal takes its props โ they win over the same attribute on the element โ and answers open() / close() / toggle() through its own show() / hide(), so open / close still fire. isOpen follows the screen: a โ, overlay or Escape close is reported back. setProps() merges into the live props and subscribe() hears every change.
ts
import 'mono-helper/ui/modal'
import { controlMonoModal } from 'mono-helper'
const modal = controlMonoModal({ props: { title: 'Detail', size: 'sm', width: 'lg' } })vue
<mono-modal :control-modal.prop="modal">โฆ</mono-modal>
<mono-button @click="modal.open()">Open</mono-button>The modal's events go in props too, as on<Event> keys โ onOpen, onClose, onToggle โ attached to every bound <mono-modal> as listeners with the same event a template @close would get (event.detail.source says whether it was the โ, the overlay, Escape or code). A template listener still fires beside them.
ts
const modal = controlMonoModal({
props: { title: 'Detail', onClose: (event) => audit(event.detail.source) },
}) Vue SFC
Dialog โ
The controller also owns a dialog: a compact question the user has to answer. modal.dialog.show() builds a small <mono-modal> by code โ size="xs", hugging its text, the actions centred under it โ opens it and returns a promise. It cannot be dismissed: no โ, no overlay click, no Escape. The only way out is a button that answers (or dialog.close() from code), because a question left unanswered is the bug this exists to prevent.
ts
const modal = controlMonoModal({
dialog: {
title: 'Lock Budget Reminder',
subtitle: 'Budget 2025', // optional muted line under the title
body: 'Sudah selesai meng-input budget?<br/>Pastikan sudah lock sebelum menambahkan program.',
buttons: [
{ label: 'Ya, lanjut', color: 'success', value: true },
{ label: 'Belum, tetap di sini', variant: 'outline', color: 'secondary', value: false },
],
},
})
const ok = await modal.dialog.show() // true โ the 'Ya' button answeredbody is rendered as HTML (or pass a Node). Each entry of buttons is a <mono-button> โ every button prop works โ (size defaults to xs) plus label, icon and the answer. A button's value is its answer: pressing it closes the dialog and resolves show() with that value. A button without one runs onClick and leaves the dialog open (a "show details" link, say). onClick(event, { dialog, button }) is the button's work: dialog is the dialog controller (close(), isOpen, element) and button is the <mono-button> pressed. Return a promise and the button shows its spinner (and a value close waits) until it settles; a rejection keeps the dialog open.
That gives two ways to write a dialog, and which one depends on where the decision lives. When the code after await show() decides, use value โ it is the only channel back to that code (the example above). When the button itself does the work, there is nothing to report: do it in onClick and close with a bare dialog.close():
ts
buttons: [
{ label: 'Lihat detail', variant: 'text', onClick: () => openDetails() }, // no close โ stays open
{ label: 'Hapus', color: 'danger', onClick: async (_e, { dialog }) => {
await api.remove(id) // spinner on; a throw keeps it open
dialog.close()
} },
{ label: 'Batal', variant: 'tonal', color: 'secondary', onClick: (_e, { dialog }) => dialog.close() },
]
await modal.dialog.show() // nothing to check โ the buttons already did the workThe first button is focused on open (focus picks another, or 'none'). show(override) merges one-off options over the ones the controller was created with; dialog.setProps() changes them for good; dialog.props reaches the dialog's own modal (color, width, zIndex, โฆ) but never its locks. A dialog is stackable, so it sits over whatever modal is already open, draggable by its header, and dims the page only lightly with no blur โ what it asks about stays readable behind it.
Vue SFC
Persistent โ
Overlay-click and Escape do not close โ only the buttons or the โ work.
Vue SFC
No overlay โ
Page behind stays interactive. A click outside the panel still closes the modal (close-on-overlay, on by default โ the page is the outside) and the click goes through to the page; :close-on-overlay="false" keeps it open.
Vue SFC
Event log โ
The modal emits toggle on every state change, plus open (on open) and close (on close) โ matching the drawer. Each event's detail.source (overlay / close / escape / manual) says what triggered it. The log below shows the close events and their source.
Vue SFC
Customized โ
Override per-element styling with cssClass (Vue) or utility classes (CSS).
Vue SFC
CSS Variables โ
Vue SFC
Every modal is themed through --mono-modal-* custom properties. Because the dialog renders through a <body> portal, --mono-modal-* set inline on the <mono-modal> element are forwarded to the portal (so per-instance theming works); you can also set them on :root to theme every modal, and they pierce the shadow-DOM boundary for the shadow build. The size and color props set presets, but an explicit --mono-modal-* override always wins. To re-skin globally, set the underlying tokens (--popover, --border, --mono-mode-backdrop โฆ) or switch flavor. Scroll areas use the shared --mono-scrollbar-* tokens.
| Variable | Default | Controls |
|---|---|---|
--mono-modal-bg (alias -surface) / -text | --popover / --popover-foreground | The panel's fill and ink |
--mono-modal-ring-color / -ring-width | --foreground/10 / --mono-border-width | The ring-1 edge |
--mono-modal-shadow | --mono-shadow-lg | The panel's elevation |
--mono-modal-accent-ring / --mono-modal-glow | accent 35% on --border / a 24px halo of the accent at 45% | Only while color is set: the ring becomes a thin line of the colour and a faint glow of it sits under the elevation |
--mono-modal-radius / -radius-<size> | --mono-radius-xl at md | Panel corner |
--mono-modal-pad-<size> / -gap-<size> | 6 ร --mono-spacing at md (p-6 gap-6) | The panel's padding, and the gap between header / body / footer |
--mono-modal-width | --mono-container-md (upstream's sm:max-w-md), capped at 100% - 2rem | Panel width โ not set by size; use the width prop (a length, or an xsโฆxxl token) |
--mono-modal-title-font-<size> / -title-weight / -title-color | --mono-text-sm / medium / the panel ink | The title. Four of the eight flavors bump it to text-base and sera to text-lg |
--mono-modal-subtitle-font / -subtitle-color / -subtitle-line-height | the body font (--mono-text-sm at md) / --muted-foreground / --mono-leading-normal | The subtitle โ Basecoat's dialog description (text-muted-foreground text-sm leading-normal) |
--mono-modal-body-font-<size> / -body-line-height | --mono-text-sm at md | The body |
--mono-modal-header-gap-<size> / -footer-gap-<size> | 2 ร --mono-spacing (gap-2) | Inside the header row and the footer row |
--mono-modal-heading-gap | the header gap | Between the title and the subtitle |
--mono-modal-header-bg (alias -head-bg) / -header-border / -header-border-width / -header-pad | transparent / transparent / 0 / 0 | The header BAR โ off, because upstream has none. Set the four to bring the pre-port bar back |
--mono-modal-footer-bg / -footer-border / -footer-border-width / -footer-pad / -footer-margin / -footer-radius | all off | The footer bar. nova's flavor is exactly this: bg-muted/50, a top rule, p-4 and a negative margin so it bleeds to the panel's edge |
--mono-modal-close-size-<size> / -close-glyph / -close-bg / -close-color / -close-opacity / -close-hover-opacity / -close-hover-bg | 7 ร --mono-spacing / size-4 / transparent / the panel ink / 0.7 / 1 / transparent | The โ. luma, sera and rhea give it a bg-secondary resting fill |
--mono-modal-overlay-bg / -overlay-backdrop-filter | --mono-mode-backdrop (black/10) / blur(--mono-blur-xs) | The scrim |
--mono-modal-accent / -<role> | --primary / the ten roles | The colour a restored bar, the โ hover and the ring tint draw from (set by color) |
--mono-modal-duration | --mono-duration-slow | Open/close animation; 0s for an instant modal |
--mono-modal-z | 600 | Base z-index (the popup stack overwrites this per level; prefer the z-index prop, and note an inline var still wins over it) |
Types โ
controlMonoModal is also exported as monoModal, and :control-modal is also accepted as :data-modal.
Import
import { ModalProps, MonoModalOptions, MonoDialogOptions, MonoDialogButton, MonoModalController, MonoDialogController } from 'mono-helper'| Prop | Value | Default | Description |
|---|---|---|---|
<mono-modal> | |||
modelValue | boolean | โ | Open state, two-way bound for v-model-style usage. |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | โ | Width preset of the modal panel. |
color | 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'teal' | 'purple' | 'neutral' | 'dark' | โ | Theme color applied to accents. |
title | string | โ | Heading text shown in the modal header. `slot="title"` replaces it. |
subtitle | string | โ | Secondary line under the title โ muted and smaller, hidden when empty. `slot="subtitle"` replaces it; `slot="header"` replaces title + subtitle together (the close โ stays). |
dismissible | boolean | โ | Shows the close button and allows dismissal. |
persistent | boolean | โ | Prevents closing via overlay click or escape. |
overlay | boolean | โ | Renders a backdrop overlay behind the panel. |
closeOnEscape | boolean | โ | Closes the modal when the Escape key is pressed. |
closeOnOverlay | boolean | โ | Closes the modal on a click outside the panel: the overlay, or โ with `overlay: false` โ the page itself (the click still reaches the page). |
lockScroll | boolean | โ | Locks body scroll while the modal is open. |
draggable | boolean | โ | Allow dragging the modal by its header; it snaps back inside the viewport on drop. |
autoFullscreen | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | boolean | โ | Fill the screen at a breakpoint and below (default `false`). `auto-fullscreen` on its own means Tailwind's `sm` (< 640px); a token moves the boundary, so `auto-fullscreen="lg"` covers everything `lg:` does not match (< 1024px). |
stackable | boolean | โ | Allow this modal to stack on top of others. When false (default) it is exclusive โ opening it closes any other open modals. |
width | number | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | string & {} | โ | Explicit panel sizing. Each accepts a preset token (`"xs"`โฆ`"xxl"` โ see {@link ModalDimensionPreset}), a CSS length string (`"12px"`, `"12rem"`, `"80%"`), or a number / numeric string (interpreted as px). Set both `width` and `height` to `"100%"` for true full-screen. |
height | number | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | string & {} | โ | โ |
minWidth | number | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | string & {} | โ | โ |
maxWidth | number | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | string & {} | โ | โ |
minHeight | number | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | string & {} | โ | โ |
maxHeight | number | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | string & {} | โ | โ |
zIndex | string | number | โ | Pin the modal to an explicit stacking level. Unset (the default) lets the shared popup stack assign one so the newest layer is always on top. The value is the overlay's `z-index`; the panel sits one above it. |
cssClass | ModalCssClass | โ | Per-part class overrides for internal elements. |
cssClassName | string | โ | Plain root class string applied to the modal. |
controlModal | MonoModalController | โ | The controller (`monoModal()` / `controlMonoModal()`) driving this modal. Bind with `.prop`: `:control-modal.prop="modal"`. `dataModal` is the same field. |
dataModal | MonoModalController | โ | โ |
controlMonoModal(options) | |||
props | Partial<ModalProps> & MonoEventProps<ModalEvents> | โ | Props pushed onto every `<mono-modal>` bound with `:control-modal.prop`. They WIN over the same attribute written on the element (matching `monoForm`'s `setProp`). The modal's events are accepted as `on<Event>` keys โ `onOpen`, `onClose`, `onToggle`, โฆ โ and attached to every bound element as listeners. |
dialog | MonoDialogOptions | โ | Defaults for the programmatic dialog โ see {@link MonoDialogOptions}. |
options.dialog | |||
title | string | โ | Header text. No header at all when omitted (together with `subtitle`). |
subtitle | string | โ | Secondary line under the title, muted and smaller. |
body | string | Node | โ | The question. A string is rendered as HTML; a Node is appended as-is. |
buttons | MonoDialogButton[] | โ | The actions, centred under the body. |
focus | number | 'none' | โ | Which button gets focus once open (index), or `'none'`. Default `0`. |
props | Partial<ModalProps> & MonoEventProps<ModalEvents> | โ | Overrides for the dialog's own `<mono-modal>` โ `color`, `size`, `width`, `zIndex`, `cssClass`โฆ โ merged over the compact defaults. The dismissal locks (`persistent`, `dismissible: false`, `closeOnEscape: false`) are applied AFTER this and cannot be overridden. Takes the modal's events as `on<Event>` keys too (`onOpen`, `onClose`, โฆ). |
dialog.buttons[] | |||
label | string | โ | Button text (the button's default slot). |
icon | string | โ | Iconify class for the leading icon, e.g. `i-mdi-check`. |
className | string | โ | Extra class on the button element. |
value | unknown | โ | The answer this button gives: once `onClick` settles, the dialog closes and `show()` resolves with this value โ for when the code AFTER `await show()` decides what happens. Without it the button leaves the dialog open unless `onClick` closes it itself (a "see details" link, say). |
onClick | (event: MouseEvent, ctx: MonoDialogButtonCtx) => unknown | โ | The button's work, run on the click. `ctx.dialog` is the dialog controller; a button that does its own work ends with a bare `dialog.close()` โ it already knows it was pressed, so there is nothing to report. Returning a promise keeps the button's spinner on (and defers the `value` close) until it settles; a rejection keeps the dialog open. |
color | 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'teal' | 'purple' | 'neutral' | 'dark' | 'light' | โ | Color theme of the button. |
variant | 'outline' | 'solid' | 'tonal' | 'text' | โ | Visual style variant (solid, outline, tonal, text). `text` has no background and no border at rest โ just the coloured label โ and takes the tonal look on hover or keyboard focus. |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | โ | Visual size of the button. |
rounded | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | 'none' | 'full' | โ | Corner radius โ `none`, the `xs`โฆ`xxl` scale, or `full`. Unset follows the theme's per-size radius. |
throttle | null | string | number | ThrottleConfig | boolean | โ | Rate-limit clicks: at most `limit` executions per `interval` ms, the rest queued and replayed rather than dropped. A bare number is the interval. Emits `throttle` per execution. |
debounce | null | string | number | DebounceConfig | boolean | โ | Collapse a burst of clicks into one execution, `wait` ms after the last. A bare number is the wait. Emits `debounce` per execution. |
loading | boolean | โ | Shows a loading state and blocks clicks. |
glass | boolean | โ | Applies a translucent glass effect. |
type | 'button' | 'submit' | 'reset' | โ | Native button type attribute. |
width | string | number | โ | Explicit sizing. Each accepts a CSS length string (`"220px"`, `"80%"`) or a number (interpreted as px). Use `width="100%"` for a full-width button. |
height | string | number | โ | โ |
minWidth | string | number | โ | โ |
maxWidth | string | number | โ | โ |
minHeight | string | number | โ | โ |
maxHeight | string | number | โ | โ |
cssClass | ButtonCssClass | โ | Per-element class overrides. |
disabled | boolean | โ | Disables interaction and dims the button. |
href | string | โ | Renders the button as an anchor with this URL. |
target | string | โ | Anchor target window when href is set. |
iconPosition | 'left' | 'right' | โ | Placement of the icon relative to the text. |
prepend | string | ButtonAffixProps | โ | Config for the leading affix (`<span slot="prepend">`). The slot supplies the content; this only says how the zone behaves. Bind with `.prop`. NOTE: this name deliberately SHADOWS `ParentNode.prepend()` on the element. `monoButtonEl.prepend(node)` therefore stops being callable โ reading it returns this config object instead of the DOM method. Nothing inside the library calls it (slot placement uses `appendChild`), but consumer code and third-party helpers that do will break on a `<mono-button>`. |
append | string | ButtonAffixProps | โ | Config for the trailing affix (`<span slot="append">`). Bind with `.prop`. Shadows `ParentNode.append()` โ see the note on `prepend`. |
badge | string | โ | Badge text shown on the button. |
badgeColor | 'red' | 'green' | 'orange' | 'cobalt' | โ | Color of the badge. |
iconOnly | boolean | โ | Renders an icon-only button without text. |
tooltip | string | โ | Tooltip text shown on hover. |
ariaLabelText | string | โ | Accessible label text for screen readers. |
noAutoLoading | boolean | โ | Opt out of the self-driven spinner; `loading` stays fully consumer-controlled. |
controller | |||
props | () => Partial<ModalProps> | โ | The stable props object every bound element pulls on notify. |
setProps | (patch: Partial<ModalProps>) => void | โ | Merge into `props()` and notify the bound elements. |
open | () => void | โ | Open the bound modal(s) โ `show('manual')`, so `open` fires. |
close | () => void | โ | Close the bound modal(s) โ `hide('manual')`, so `close` fires. |
toggle | () => void | โ | โ |
isOpen | boolean | โ | Open state of the bound modal; follows user-driven closes (โ, overlay, Escape) too. |
element | null | HTMLElement | โ | The first bound `<mono-modal>`, or `null`. |
dialog | MonoDialogController | โ | The programmatic dialog. |
subscribe | (cb: () => void) => () => void | โ | Called after every state or props change. Returns an unsubscribe. |
dispose | () => void | โ | Closes an open dialog (resolving `false`), drops subscribers and bindings. |
controller.dialog | |||
show | <T = boolean>(override?: Partial<MonoDialogOptions> | undefined) => Promise<T> | โ | Build, open and await the dialog. `override` is merged over the options the controller was created with, for this show only. Resolves with the value the answering button supplied โ its `value`, or what its `onClick` passed to `dialog.close(value)` โ `false` when `close()` is called bare, and `false` when a second `show()` pre-empts it. |
close | (value?: unknown) => void | โ | Close the open dialog, resolving its `show()` with `value` (default `false`). |
isOpen | boolean | โ | Whether a dialog is currently open. |
element | null | HTMLElement | โ | The open dialog's `<mono-modal>` element, or `null`. |
setProps | (patch: Partial<MonoDialogOptions>) => void | โ | Merge new defaults for future `show()`s. |