Skip to main content
Browse docs

Marwes documentation

Dialog

High-risk modal family with a non-modal shell, canonical modal overlay layer, and stable purpose-dialog wrappers.

What this family solves

High-risk modal family with a non-modal shell, canonical modal overlay layer, and stable purpose-dialog wrappers.

Use when

  • A workflow needs a named dialog shell or a canonical modal overlay with consistent focus and dismissal behavior.
  • The product flow maps clearly to confirm, destructive, or informational dialog intent.
  • The team wants React and Vue modal behavior to stay aligned through shared contracts.

Avoid when

  • A lower-weight surface such as a tooltip or other non-modal help pattern is the more honest interaction model.
  • Parent code cannot own a shell modal boundary intentionally when using the Dialog modal escape hatch.
  • The team needs background-isolation guarantees that go beyond the currently shipped modal hardening level.

Public imports

Choose an adapter in the verified examples. The inventory below reflects each framework package exactly.

React — @marwes-ui/react

Components

ConfirmDialog, DestructiveDialog, Dialog, DialogModal, InfoDialog

Types

ConfirmDialogProps, DestructiveDialogProps, DialogFooterControls, DialogModalProps, DialogProps, InfoDialogProps

Vue — @marwes-ui/vue

Components

ConfirmDialog, DestructiveDialog, Dialog, DialogModal, InfoDialog

Types

ConfirmDialogProps, DestructiveDialogProps, DialogFooterControls, DialogModalProps, DialogProps, InfoDialogProps

Svelte — @marwes-ui/svelte

Components

ConfirmDialog, DestructiveDialog, Dialog, DialogModal, InfoDialog

Types

ConfirmDialogProps, DestructiveDialogProps, DialogFooterControls, DialogModalProps, DialogProps, InfoDialogProps

Verified minimal examples

These examples come from the same fixtures verified by the repository checks.

React

import { Button, ButtonVariant, DialogModal, Drawer, Paragraph } from "@marwes-ui/react"
import { useState } from "react"

export function Example() {
  const [dialogOpen, setDialogOpen] = useState(false)
  const [drawerOpen, setDrawerOpen] = useState(false)

  return (
    <>
      <Button variant={ButtonVariant.primary} onClick={() => setDialogOpen(true)}>
        Open dialog →
      </Button>
      <Button variant={ButtonVariant.secondary} onClick={() => setDrawerOpen(true)}>
        Open drawer →
      </Button>

      <DialogModal
        open={dialogOpen}
        onOpenChange={setDialogOpen}
        title="Dialog title"
        description="This is a dialog component."
        footer={
          <Button variant={ButtonVariant.primary} onClick={() => setDialogOpen(false)}>
            Close
          </Button>
        }
      >
        <Paragraph>Dialog content goes here.</Paragraph>
      </DialogModal>

      {drawerOpen && (
        <Drawer
          modal
          title="Drawer"
          size="medium"
          placement="right"
          onClose={() => setDrawerOpen(false)}
          footer={
            <Button variant={ButtonVariant.secondary} onClick={() => setDrawerOpen(false)}>
              Close drawer
            </Button>
          }
        >
          <p>Drawer content goes here.</p>
        </Drawer>
      )}
    </>
  )
}

Vue

<script setup lang="ts">
import { ref } from "vue"
import { Button, DialogModal, Drawer, Paragraph } from "@marwes-ui/vue"

const dialogOpen = ref(false)
const drawerOpen = ref(false)
</script>

<template>
  <Button variant="primary" @click="dialogOpen = true">Open dialog →</Button>
  <Button variant="secondary" @click="drawerOpen = true">Open drawer →</Button>

  <DialogModal
    v-model:open="dialogOpen"
    title="Dialog title"
    description="This is a dialog component."
  >
    <Paragraph>Dialog content goes here.</Paragraph>
    <template #footer>
      <Button variant="primary" @click="dialogOpen = false">Close</Button>
    </template>
  </DialogModal>

  <Drawer
    v-if="drawerOpen"
    modal
    title="Drawer"
    size="medium"
    placement="right"
    @close="drawerOpen = false"
  >
    <p>Drawer content goes here.</p>
    <template #footer>
      <Button variant="secondary" @click="drawerOpen = false">Close drawer</Button>
    </template>
  </Drawer>
</template>

Svelte

<script lang="ts">
  import { Button, DialogModal, Drawer, Paragraph } from "@marwes-ui/svelte"

  let dialogOpen = $state(false)
  let drawerOpen = $state(false)
</script>

<Button variant="primary" onclick={() => (dialogOpen = true)}>Open dialog →</Button>
<Button variant="secondary" onclick={() => (drawerOpen = true)}>Open drawer →</Button>

<DialogModal
  bind:open={dialogOpen}
  title="Dialog title"
  description="This is a dialog component."
>
  <Paragraph>Dialog content goes here.</Paragraph>
  {#snippet footer()}
    <Button variant="primary" onclick={() => (dialogOpen = false)}>Close</Button>
  {/snippet}
</DialogModal>

{#if drawerOpen}
  <Drawer
    modal
    title="Drawer"
    size="medium"
    placement="right"
    onclose={() => (drawerOpen = false)}
  >
    <p>Drawer content goes here.</p>
    {#snippet footer()}
      <Button variant="secondary" onclick={() => (drawerOpen = false)}>Close drawer</Button>
    {/snippet}
  </Drawer>
{/if}

Accessibility requirements

  • Focus return on close: Keep restoreFocus enabled so closing a dialog returns focus to its trigger.
  • Escape and scrim behavior: Verify closeOnEscape and closeOnScrimClick match the real risk of losing unsaved input.
  • Focus and escape review: Test focus entry, focus return, dismissal, and escape-key behavior in context.
  • Manual review boundary: Real browser and assistive-technology validation for modal flows.
  • Manual review 2: Future background-isolation hardening such as inert or equivalent sibling management.
  • Manual review 3: Advanced parent-managed modal-shell compositions that use the Dialog modal escape hatch intentionally.

Theming

Dialog uses Marwes preset CSS and theme variables. Customize it through the theme passed to MarwesProvider; do not add a second component stylesheet. See the theming guide for configuration and token details.

Resources