Dialog
A family of modal dialogs for confirmations and prompts.
Usage
Bottom Dialog
TxBottomDialog is a mobile-style bottom confirmation, also used as a checkpoint before destructive actions.
Action Rows and Icons
Each button renders as a full-width action row, with icon as its leading glyph.
Button Types
Only type: 'error' colors a row; info, warning, and success all render as neutral rows.
const btns = [
{ content: 'Neutral row', type: 'info', onClick: () => true },
{ content: 'Also neutral', type: 'success', onClick: () => true },
{ content: 'Destructive row', type: 'error', onClick: () => true },
]
Auto Confirm
time counts down in seconds and clicks the row when it reaches zero.
const btns = [
{ content: 'Auto confirm', type: 'success', time: 5, onClick: () => true },
]
Loading State
While onClick runs, the row is disabled and shows a spinner, so it can't be submitted twice.
const btns = [
{
content: 'Submit',
type: 'success',
onClick: async () => {
await saveData()
return true
},
},
]
Blow Dialog
TxBlowDialog is a centered, high-emphasis dialog that transforms the background as it opens.
Popper Dialog
TxPopperDialog is a compact centered prompt that keeps modal semantics.
Touch Tip
TxTouchTip is a touch-first guidance prompt with several action buttons.
Custom Content
TxBlowDialog and TxPopperDialog replace their default content with comp or render.
import CustomContent from './CustomContent.vue'
// Component
h(TxBlowDialog, { comp: CustomContent, close: () => {} })
// Render function
h(TxBlowDialog, {
render: () => h('div', [
h('h2', 'Dynamic content'),
h('p', 'Created with a render function'),
]),
close: () => {},
})
Best Practices
- Keep at most one destructive row, mark it
type: 'error', and state the consequence in its label; color only reinforces it. - Pass
iconas a class the host's icon pipeline generates statically (i-carbon-trash-can); a name built at runtime renders an empty box. - Reserve
TxBlowDialogfor rare, high-emphasis announcements; its background transform is dramatic. - On non-English surfaces, pass
closeLabeltoTxBottomDialog: the close button is icon-only, so this name is all a screen reader announces. - Never pass user-generated content to
messageHtmlunless it is sanitized and marked withasTrustedDialogHtml().
API Reference
TxBottomDialog
Props
| Name | Type | Default | Description |
|---|---|---|---|
title | string | '' | Title. |
message | string | '' | Plain-text body; line breaks are kept. |
stay | number | 0 | Reserved auto-close duration; currently starts no timer on its own. |
close | () => void | required | Close callback. |
btns | DialogButton[] | [] | Action row configs. |
icon | string | '' | Legacy icon class; not rendered. |
index | number | 0 | z-index offset added to the allocated layer. |
closeLabel | string | 'Close' | Accessible name of the header's close button. |
surface | 'pure' | 'mask' | 'blur' | 'glass' | 'refraction' | 'acrylic' | 'mica' | 'flat' | 'plain' | 'refraction' | Material of the panel. |
surfaceColor | string | '' | Colour laid under the material; follows the theme by default. |
surfaceOpacity | number | 0.96 for mask, 0.5 otherwise | Opacity of that colour, used by mask, blur, acrylic, glass and refraction; always opaque under pure and flat, and mica and plain lay no base colour. |
TxBlowDialog / TxPopperDialog
Props
Both take the same props.
| Name | Type | Default | Description |
|---|---|---|---|
title | string | '' | Title. |
message | string | '' | Plain-text body. |
messageHtml | DialogMessageHtml | '' | Sanitized, trusted HTML; takes precedence over message. |
confirmText | string | 'Confirm' | Confirm button text. |
close | () => void | required | Close callback. |
comp | Component | undefined | Component that replaces the default content. |
render | () => VNode | undefined | Render function that replaces the default content. |
surface | 'pure' | 'mask' | 'blur' | 'glass' | 'refraction' | 'acrylic' | 'mica' | 'flat' | 'plain' | 'refraction' | Material of the panel. |
surfaceColor | string | '' | Colour laid under the material; follows the theme by default. |
surfaceOpacity | number | 0.96 for mask, 0.5 otherwise | Opacity of that colour, used by mask, blur, acrylic, glass and refraction; always opaque under pure and flat, and mica and plain lay no base colour. |
TxTouchTip
Props
| Name | Type | Default | Description |
|---|---|---|---|
title | string | '' | Title. |
message | string | '' | Plain-text body. |
messageHtml | DialogMessageHtml | '' | Sanitized, trusted HTML; takes precedence over message. |
buttons | TouchTipButton[] | [] | Action button configs. |
close | () => void | required | Close callback. |
surface | 'pure' | 'mask' | 'blur' | 'glass' | 'refraction' | 'acrylic' | 'mica' | 'flat' | 'plain' | 'refraction' | Material of the panel. |
surfaceColor | string | '' | Colour laid under the material; follows the theme by default. |
surfaceOpacity | number | 0.96 for mask, 0.5 otherwise | Opacity of that colour, used by mask, blur, acrylic, glass and refraction; always opaque under pure and flat, and mica and plain lay no base colour. |
Types
interface DialogButton {
content: string
type?: 'info' | 'warning' | 'error' | 'success' // only 'error' colors the row
icon?: string // leading icon class
time?: number // countdown in seconds; clicks the row at zero
onClick: () => Promise<boolean> | boolean // true closes, false stays open
loading?: (done: () => void) => void // the row stays loading until done()
}
// TxTouchTip buttons: no icon or time
interface TouchTipButton {
content: string
type?: 'info' | 'warning' | 'error' | 'success'
onClick: () => Promise<boolean> | boolean
loading?: (done: () => void) => void
}
// The material props all four variants share
interface DialogSurfaceProps {
surface?: BaseSurfaceMode // 'refraction' by default
surfaceColor?: string // follows the theme by default
surfaceOpacity?: number // 0.96 for mask, 0.5 otherwise
}
function asTrustedDialogHtml(html: string): TrustedDialogHtml
Overview
- All four variants teleport to
bodyand take their layer from the shared z-index manager. - They emit no events and have no slots; they close only through the required
closecallback. - Escape calls
close()after the leave animation; theTxBottomDialogclose button also only cancels and never fires a row action. - Focus returns to the previously focused element on unmount;
useId()ids wire the title and body toaria-labelledby/aria-describedby. messagerenders as plain text with line breaks kept;messageHtmlaccepts only values marked byasTrustedDialogHtml(), which does not sanitize.- Bodies set
overflow-wrap: anywhereand cap their own height with scrolling, so long tokens don't widen the panel and long content isn't clipped. - The panel background is a card-preset
TxBaseSurface(fake) under the content,refractionby default: a 50% base colour keeps text legible while the page behind still shows through to be blurred and refracted. - The overlay dim of
TxBlowDialog,TxPopperDialogandTxTouchTip(and the blur ofTxBlowDialog) is painted on a pseudo-element of the overlay rather than on its own background and opacity, so the panel's material samples the page, not only the dim;TxBottomDialoghas no overlay. - Panels only move and scale as they open and close; they never fade as a whole. Once a panel's opacity animates, every backdrop filter inside it samples nothing but the panel, and the frost would drop out for the whole transition. What fades is each part of the panel instead: the content, the shadow and outline, and each layer of the material, so a material with a backdrop filter (such as the default
refraction) samples the page from the first frame to the last.
Technologies
- The entry exports the four variants (each wrapped with
withInstall),asTrustedDialogHtml, and the public types. - Under high contrast the panel's material turns solid on its own, and the
TxBlowDialogoverlay only dims the page without frosting it. - Under reduced motion (
prefers-reduced-motion: reduce) the panels fade in place, without scaling or moving; the zoom and fadeTxBlowDialogapplies to#appon open ignores this setting. - Source:
packages/tuffex/packages/components/src/dialog/.