MessageBox
A set of modal boxes simulating system message box.
| Name | Category | Description | Type | Default |
|---|---|---|---|---|
type | ? Style | Message type | 'success' | 'warning' | 'info' | 'danger' | 'error' | — |
cancelButtonType | ? Style | Cancel button type | ButtonType | — |
confirmButtonType | ? Style | Confirm button type | ButtonType | 'primary' |
center | ? Style | Whether to center layout | boolean | false |
inputType | ? Style | Input type | 'text' | 'textarea' | 'password' | 'number' | 'text' |
customClass | ? Style | Custom class name applied to dialog root | string | — |
customStyle | ? Style | Custom inline styles applied to dialog root | CSSProperties | — |
width | ? Style | Custom dialog width (number = px, or CSS string) | string | number | 420 |
overlayClass | ? Style | Custom class for the overlay backdrop | string | string[] | Record<string, boolean> | — |
showClose | ? Behavior | Whether to show close button | boolean | true |
showCancelButton | ? Behavior | Whether to show cancel button | boolean | false |
showConfirmButton | ? Behavior | Whether to show confirm button | boolean | true |
lockScroll | ? Behavior | Whether to lock scroll | boolean | true |
closeOnClickModal | ? Behavior | Whether to close on modal click | boolean | true |
showInput | ? Behavior | Whether to show input | boolean | false |
callback | ? Behavior | Callback after closing | (action: MessageBoxAction | { value: string; action: MessageBoxAction }) => void | — |
beforeClose | ? Behavior | Callback before closing; call done to close. If a Promise is returned, the button automatically shows a loading spinner | (action: MessageBoxAction, instance: MessageBoxOptions, done: () => void) => void | Promise<void> | — |
closeOnPressEscape | ? Behavior | Whether to close on Escape key press | boolean | true |
closeOnHashChange | ? Behavior | Whether to close on URL hash change | boolean | true |
inputSchema | ? Behavior | Zod validation schema for prompt input | ZodType | — |
distinguishCancelAndClose | ? Behavior | Whether close button fires "close" instead of "cancel" | boolean | true |
draggable | ? Behavior | Whether the dialog is draggable by its header | boolean | false |
title | ? Content | Title | string | — |
message | ? Content | Message content | string | VNode | — |
cancelButtonText | ? Content | Cancel button text | string | 'No' |
confirmButtonText | ? Content | Confirm button text | string | 'Yes' |
inputPlaceholder | ? Content | Input placeholder | string | — |
inputValue | ? Content | Input initial value | string | — |
inputErrorMessage | ? Content | Custom error message when input validation fails | string | — |
footer | ? Content | Custom footer VNode or render function replacing default buttons | VNode | (() => VNode) | — |
PxMessageBox | ? Method | Open message box | (options: MessageBoxOptions) => Promise<MessageBoxData> | — |
PxMessageBox.alert | ? Method | Open alert box | (message, title, options?) => Promise<MessageBoxData> | — |
PxMessageBox.confirm | ? Method | Open confirm box | (message, title, options?) => Promise<MessageBoxData> | — |
PxMessageBox.prompt | ? Method | Open prompt box | (message, title, options?) => Promise<MessageBoxData> | — |
PxMessageBox.close | ? Method | Close current box | () => void | — |
Alert
Used to alert users, only has a confirm button.
<template>
<px-button @click="showAlert">Show Alert</px-button>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
const showAlert = () => {
PxMessageBox.alert('This is an alert message', 'Alert').catch(() => {});
};
</script>Confirm
Used to ask users to confirm an operation, has confirm and cancel buttons.
<template>
<px-button @click="showConfirm">Show Confirm</px-button>
</template>
<script setup lang="ts">
import { PxMessage, PxMessageBox } from 'sakana-element';
const showConfirm = async () => {
try {
await PxMessageBox.confirm('Are you sure to delete this item?', 'Confirm');
PxMessage.success('Deleted successfully');
} catch {
PxMessage.info('Cancelled');
}
};
</script>Prompt
Used to prompt users to input content.
<template>
<px-button @click="showPrompt">Show Prompt</px-button>
</template>
<script setup lang="ts">
import { PxMessage, PxMessageBox } from 'sakana-element';
const showPrompt = async () => {
try {
const { value } = await PxMessageBox.prompt('Please input your name', 'Prompt');
PxMessage.success(`Your name is: ${value}`);
} catch {
PxMessage.info('Cancelled');
}
};
</script>Custom Content
Message box content can be customized.
<template>
<px-button @click="showCustom">Custom MessageBox</px-button>
</template>
<script setup lang="ts">
import { PxMessage, PxMessageBox } from 'sakana-element';
const showCustom = async () => {
try {
await PxMessageBox({
title: 'Warning',
message: 'This action will permanently delete the file. Continue?',
type: 'warning',
showCancelButton: true,
confirmButtonText: 'Yes, delete it',
cancelButtonText: 'No, cancel',
});
PxMessage.success('Deleted!');
} catch {
PxMessage.info('Cancelled');
}
};
</script>Center Layout
Use center to align the title and footer to the center.
<template>
<px-button @click="showCenter">Center Layout</px-button>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
const showCenter = () => {
PxMessageBox({
title: 'Warning',
message: 'This will center the title and footer.',
type: 'warning',
center: true,
showCancelButton: true,
}).catch(() => {});
};
</script>BeforeClose Callback
Use beforeClose to intercept the close action. The callback receives the action, the instance, and a done function — call done() to actually close the dialog. If beforeClose returns a Promise, the clicked button automatically shows a loading state until the Promise resolves.
<template>
<div style="display: flex; gap: 8px; flex-wrap: wrap">
<px-button @click="showCallbackStyle">Callback Style</px-button>
<px-button @click="showAsyncStyle">Async / Promise Style</px-button>
</div>
</template>
<script setup lang="ts">
import { PxMessage, PxMessageBox } from 'sakana-element';
const showCallbackStyle = () => {
PxMessageBox({
title: 'Confirm',
message: 'Are you sure? The dialog will close after 1 second.',
showCancelButton: true,
beforeClose: (action, _instance, done) => {
if (action === 'confirm') {
setTimeout(() => {
done();
PxMessage.success('Confirmed after delay');
}, 1000);
} else {
done();
}
},
});
};
const showAsyncStyle = () => {
PxMessageBox({
title: 'Async Confirm',
message: 'The confirm button will show a loading spinner for 1.5 seconds.',
showCancelButton: true,
beforeClose: (action, _instance, done) => {
if (action === 'confirm') {
return new Promise<void>((resolve) => {
setTimeout(() => {
done();
PxMessage.success('Async operation completed');
resolve();
}, 1500);
});
}
done();
},
});
};
</script>Type-Colored Borders
Setting type to 'info', 'success', 'warning', or 'danger' colors the border, shadow, and divider to match the theme.
<template>
<div style="display: flex; gap: 8px; flex-wrap: wrap">
<px-button type="info" @click="showType('info')">Info</px-button>
<px-button type="success" @click="showType('success')">Success</px-button>
<px-button type="warning" @click="showType('warning')">Warning</px-button>
<px-button type="danger" @click="showType('danger')">Danger</px-button>
</div>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
const showType = (type: 'info' | 'success' | 'warning' | 'danger') => {
PxMessageBox({
title: `${type.charAt(0).toUpperCase() + type.slice(1)} Type`,
message: `This message box uses the "${type}" type, which colors the border, shadow, and divider.`,
type,
showCancelButton: true,
}).catch(() => {});
};
</script>Custom Appearance
Use customClass, customStyle, and width to customize the dialog appearance. The width prop accepts a number (pixels) or a CSS string value.
<template>
<div style="display: flex; gap: 8px; flex-wrap: wrap">
<px-button @click="showCustomClass">Custom Class</px-button>
<px-button @click="showCustomStyle">Custom Style</px-button>
<px-button @click="showWidth">Custom Width</px-button>
</div>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
const showCustomClass = () => {
PxMessageBox.alert('This dialog has a custom CSS class applied.', 'Custom Class', {
customClass: 'my-custom-msgbox',
}).catch(() => {});
};
const showCustomStyle = () => {
PxMessageBox.alert('This dialog has custom inline styles.', 'Custom Style', {
customStyle: {
'--px-message-box-bg': '#f0f9eb',
'--px-message-box-border-color': '#67c23a',
} as any,
}).catch(() => {});
};
const showWidth = () => {
PxMessageBox.alert('This dialog is 600px wide.', 'Custom Width (number)', { width: 600 }).catch(
() => {},
);
};
</script>
<style>
.my-custom-msgbox {
--px-message-box-bg: #fdf6ec;
--px-message-box-border-color: #e6a23c;
}
</style>Close Controls
Use closeOnPressEscape and closeOnHashChange to control how the dialog can be closed. Both default to true.
<template>
<div style="display: flex; gap: 8px; flex-wrap: wrap">
<px-button @click="showNoEscape">Disable ESC Close</px-button>
<px-button @click="showNoHashChange">Disable Hash Close</px-button>
</div>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
const showNoEscape = () => {
PxMessageBox({
title: 'No ESC Close',
message: 'Pressing Escape will NOT close this dialog. Use the buttons instead.',
showCancelButton: true,
closeOnPressEscape: false,
}).catch(() => {});
};
const showNoHashChange = () => {
PxMessageBox({
title: 'No Hash Close',
message: 'Changing the URL hash will NOT close this dialog.',
showCancelButton: true,
closeOnHashChange: false,
}).catch(() => {});
};
</script>Input Validation
Use inputSchema with a Zod schema to validate prompt input before allowing confirmation. Set inputErrorMessage to customize the error text shown below the input when validation fails.
<template>
<px-button @click="showValidation">Email Validation</px-button>
</template>
<script setup lang="ts">
import { PxMessage, PxMessageBox } from 'sakana-element';
import { z } from 'zod';
const showValidation = async () => {
try {
const { value } = await PxMessageBox.prompt(
'Please enter your email address',
'Email Validation',
{
inputPlaceholder: 'user@example.com',
inputSchema: z.string().email(),
inputErrorMessage: 'Please enter a valid email address',
},
);
PxMessage.success(`Email submitted: ${value}`);
} catch {
PxMessage.info('Cancelled');
}
};
</script>Distinguish Cancel and Close
When distinguishCancelAndClose is true (default), clicking the close button rejects with 'close', while clicking the cancel button rejects with 'cancel'. Set it to false to make both fire 'cancel'.
<template>
<div style="display: flex; gap: 8px; flex-wrap: wrap">
<px-button @click="show(true)">Distinguish (default)</px-button>
<px-button @click="show(false)">Not Distinguished</px-button>
</div>
</template>
<script setup lang="ts">
import { PxMessage, PxMessageBox } from 'sakana-element';
const show = async (distinguish: boolean) => {
try {
await PxMessageBox({
title: distinguish ? 'Distinguish Close' : 'Not Distinguished',
message: distinguish
? 'Close button fires "close", cancel button fires "cancel".'
: 'Both close button and cancel button fire "cancel".',
showCancelButton: true,
distinguishCancelAndClose: distinguish,
});
PxMessage.success('Action: confirm');
} catch (action) {
PxMessage.info(`Action: ${action}`);
}
};
</script>Draggable
Set draggable to true to allow the user to drag the dialog by its header. The dialog is constrained to the viewport.
<template>
<px-button @click="showDraggable">Draggable MessageBox</px-button>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
const showDraggable = () => {
PxMessageBox({
title: 'Draggable',
message: 'Drag the header to move this dialog around.',
showCancelButton: true,
draggable: true,
}).catch(() => {});
};
</script>Custom Footer
Use the footer option to provide a VNode or render function that replaces the default cancel/confirm buttons with custom content.
<template>
<px-button @click="showCustomFooter">Custom Footer</px-button>
</template>
<script setup lang="ts">
import { PxMessageBox } from 'sakana-element';
import { h } from 'vue';
const showCustomFooter = () => {
PxMessageBox({
title: 'Custom Footer',
message: 'This dialog replaces the default buttons with a custom footer.',
footer: () =>
h('div', { style: 'text-align: center; padding: 8px 0' }, [
h(
'a',
{
href: '#',
style: 'color: var(--px-color-primary); cursor: pointer',
onClick: (e: Event) => {
e.preventDefault();
PxMessageBox.close();
},
},
'I have read and agree to the terms',
),
]),
}).catch(() => {});
};
</script>