安裝
Terminal
pnpm dlx shadcn-vue add @admin/dialogimport { AdminDialog, AdminDialogClose, AdminDialogContent, AdminDialogDescription, AdminDialogFooter, AdminDialogHeader, AdminDialogTitle, AdminDialogTrigger,} from '@/components/admin/dialog'用法
以 v-model:open 控制顯示狀態;header 與 footer 之間放主要內容,trigger 模式由 admin-dialog-trigger 啟動。
<script setup lang="ts">import { ref } from 'vue'import { AdminButton } from '@/components/admin/button'import { AdminDialog, AdminDialogContent, AdminDialogDescription, AdminDialogFooter, AdminDialogHeader, AdminDialogTitle, AdminDialogTrigger} from '@/components/admin/dialog'const open = ref(false)</script><template> <admin-dialog v-model:open="open"> <admin-dialog-trigger as-child> <admin-button>Open dialog</admin-button> </admin-dialog-trigger> <admin-dialog-content> <admin-dialog-header> <admin-dialog-title>Confirm action</admin-dialog-title> <admin-dialog-description>This will save your changes.</admin-dialog-description> </admin-dialog-header> <admin-dialog-footer> <admin-button variant="outline" @click="open = false">Cancel</admin-button> <admin-button @click="open = false">Confirm</admin-button> </admin-dialog-footer> </admin-dialog-content> </admin-dialog></template>場景
帶表單的對話框
搭配 vee-validate 的 <Field> 與 useForm 做欄位驗證,並以 admin-field 版型(admin-field / admin-field-label / admin-field-content / admin-field-error)排版;<form> 包住欄位與 footer,透過 handleSubmit 攔截提交並在驗證通過後手動關閉 open。
<script setup lang="ts">import { useForm, Field as VeeField } from 'vee-validate'import { ref } from 'vue'import { AdminButton } from '@/components/admin/button'import { AdminDialog, AdminDialogContent, AdminDialogDescription, AdminDialogFooter, AdminDialogHeader, AdminDialogTitle, AdminDialogTrigger} from '@/components/admin/dialog'import { AdminField, AdminFieldContent, AdminFieldError, AdminFieldLabel} from '@/components/admin/field'import { AdminInput } from '@/components/admin/input'const open = ref(false)const { handleSubmit, resetForm } = useForm<{ name: string email: string}>({ initialValues: { name: '', email: '' }})function validateName(value: unknown) { if (typeof value !== 'string' || value.trim().length === 0) { return '請輸入名字。' } return true}function validateEmail(value: unknown) { if (typeof value !== 'string' || value.length === 0) { return '請輸入 Email。' } if (!value.includes('@') || !value.includes('.')) { return '請輸入有效的 Email 格式。' } return true}const onSubmit = handleSubmit(() => { open.value = false})function onCancel() { open.value = false resetForm()}</script><template> <admin-dialog v-model:open="open"> <admin-dialog-trigger as-child> <admin-button>編輯個人資料</admin-button> </admin-dialog-trigger> <admin-dialog-content class="sm:max-w-md"> <admin-dialog-header> <admin-dialog-title>個人資料</admin-dialog-title> <admin-dialog-description>更新您的名字與 email。</admin-dialog-description> </admin-dialog-header> <form class="flex flex-col gap-3 py-2" @submit="onSubmit"> <vee-field v-slot="{ componentField, errorMessage }" name="name" :rules="validateName"> <admin-field> <admin-field-label class="w-26 shrink-0 py-2.5">Name</admin-field-label> <admin-field-content class="min-h-full min-w-0"> <admin-input placeholder="您的名字" v-bind="componentField" :is-error="!!errorMessage" /> <admin-field-error :errors="errorMessage ? [errorMessage] : undefined" /> </admin-field-content> </admin-field> </vee-field> <vee-field v-slot="{ componentField, errorMessage }" name="email" :rules="validateEmail"> <admin-field> <admin-field-label class="w-26 shrink-0 py-2.5">Email</admin-field-label> <admin-field-content class="min-h-full min-w-0"> <admin-input placeholder="you@example.com" type="email" v-bind="componentField" :is-error="!!errorMessage" /> <admin-field-error :errors="errorMessage ? [errorMessage] : undefined" /> </admin-field-content> </admin-field> </vee-field> <admin-dialog-footer> <admin-button type="button" variant="outline" @click="onCancel">取消</admin-button> <admin-button type="submit">儲存</admin-button> </admin-dialog-footer> </form> </admin-dialog-content> </admin-dialog></template>可滾動內容
<script setup lang="ts">import { ref } from 'vue'import { AdminButton } from '@/components/admin/button'import { AdminDialog, AdminDialogContent, AdminDialogDescription, AdminDialogFooter, AdminDialogHeader, AdminDialogTitle, AdminDialogTrigger} from '@/components/admin/dialog'const open = ref(false)</script><template> <admin-dialog v-model:open="open"> <admin-dialog-trigger as-child> <admin-button>查看服務條款</admin-button> </admin-dialog-trigger> <admin-dialog-content class="sm:max-w-lg"> <admin-dialog-header> <admin-dialog-title>服務條款</admin-dialog-title> <admin-dialog-description>請閱讀以下條款後按同意。</admin-dialog-description> </admin-dialog-header> <div class="max-h-64 overflow-y-auto pr-2 typo-content-medium"> <p v-for="i in 20" :key="i" class="mb-3"> 第 {{ i }} 條:本條文為範例文字,用以示範捲動式對話框。可以放長篇幅的法務內容或政策說明。 </p> </div> <admin-dialog-footer> <admin-button variant="outline" @click="open = false">取消</admin-button> <admin-button @click="open = false">同意</admin-button> </admin-dialog-footer> </admin-dialog-content> </admin-dialog></template>API 參考
組成
<template> <admin-dialog v-model:open="isOpen"> <admin-dialog-trigger>開啟</admin-dialog-trigger> <admin-dialog-content> <admin-dialog-header> <admin-dialog-title>標題</admin-dialog-title> <admin-dialog-description>說明文字</admin-dialog-description> </admin-dialog-header> 主要內容 <admin-dialog-footer> <admin-dialog-close>取消</admin-dialog-close> </admin-dialog-footer> </admin-dialog-content> </admin-dialog></template>admin-dialog
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
open | boolean | undefined | — | The controlled open state of the dialog. Can be binded as `v-model:open`. |
defaultOpen | boolean | undefined | — | The open state of the dialog when it is initially rendered. Use when you do not need to control its open state. |
modal | boolean | undefined | — | The modality of the dialog When set to `true`, interaction with outside elements will be disabled and only dialog content will be visible to screen readers. |
unmountOnHide | boolean | undefined | true | When set to `false`, the dialog content will not be unmounted when closed, but instead hidden with CSS. Useful for SEO or when you want to improve performance by not remounting the component on every open. |
class | unknown | — | — |
Events
| 名稱 | Payload | 說明 |
|---|---|---|
update:open | boolean | — |
Slots
| 名稱 | Bindings | 說明 |
|---|---|---|
default | { open: boolean; close: () => void; } | — |
admin-dialog-content
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
forceMount | boolean | undefined | — | Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries. |
as | globalThis.Component | AsTag | undefined | "div" | The element or component this component should render as. Can be overwritten by `asChild`. |
asChild | boolean | undefined | — | Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
disableOutsidePointerEvents | boolean | undefined | — | When `true`, hover/focus/click interactions will be disabled on elements outside the `DismissableLayer`. Users will need to click twice on outside elements to interact with them: once to close the `DismissableLayer`, and again to trigger the element. |
class | ClassValue | — | 根元素之自訂 class |
showCloseButton | boolean | undefined | true | 設為 `false` 時隱藏右上角關閉 X 按鈕;admin 預設內嵌 `<DialogClose>` 與 `IconX` |
Events
| 名稱 | Payload | 說明 |
|---|---|---|
escapeKeyDown | KeyboardEvent | — |
pointerDownOutside | PointerDownOutsideEvent | — |
focusOutside | FocusOutsideEvent | — |
interactOutside | PointerDownOutsideEvent | FocusOutsideEvent | — |
openAutoFocus | Event | — |
closeAutoFocus | Event | — |
Slots
| 名稱 | Bindings | 說明 |
|---|---|---|
default | {} | — |
admin-dialog-scroll-content
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
forceMount | boolean | undefined | — | Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries. |
as | globalThis.Component | AsTag | undefined | "div" | The element or component this component should render as. Can be overwritten by `asChild`. |
asChild | boolean | undefined | — | Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
disableOutsidePointerEvents | boolean | undefined | — | When `true`, hover/focus/click interactions will be disabled on elements outside the `DismissableLayer`. Users will need to click twice on outside elements to interact with them: once to close the `DismissableLayer`, and again to trigger the element. |
class | ClassValue | — | 根元素之自訂 class |
showCloseButton | boolean | undefined | true | 設為 `false` 時隱藏右上角關閉 X 按鈕;admin 預設內嵌 `<DialogClose>` 與 `IconX` |
Events
| 名稱 | Payload | 說明 |
|---|---|---|
escapeKeyDown | KeyboardEvent | — |
pointerDownOutside | PointerDownOutsideEvent | — |
focusOutside | FocusOutsideEvent | — |
interactOutside | PointerDownOutsideEvent | FocusOutsideEvent | — |
openAutoFocus | Event | — |
closeAutoFocus | Event | — |
Slots
| 名稱 | Bindings | 說明 |
|---|---|---|
default | {} | — |
admin-dialog-close
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
asChild | boolean | undefined | — | Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
as | globalThis.Component | AsTag | undefined | "div" | The element or component this component should render as. Can be overwritten by `asChild`. |
class | unknown | — | — |
Slots
| 名稱 | Bindings | 說明 |
|---|---|---|
default | {} | — |
admin-dialog-description
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
asChild | boolean | undefined | — | Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
as | globalThis.Component | AsTag | undefined | "div" | The element or component this component should render as. Can be overwritten by `asChild`. |
class | ClassValue | — | 根元素之自訂 class |
Slots
| 名稱 | Bindings | 說明 |
|---|---|---|
default | {} | — |
admin-dialog-footer
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
class | ClassValue | — | 根元素之自訂 class |
Slots
| 名稱 | Bindings | 說明 |
|---|---|---|
default | {} | — |
admin-dialog-header
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
class | ClassValue | — | 根元素之自訂 class |
Slots
| 名稱 | Bindings | 說明 |
|---|---|---|
default | {} | — |
admin-dialog-overlay
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
forceMount | boolean | undefined | — | Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries. |
asChild | boolean | undefined | — | Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
as | globalThis.Component | AsTag | undefined | "div" | The element or component this component should render as. Can be overwritten by `asChild`. |
class | ClassValue | — | 根元素之自訂 class |
Slots
| 名稱 | Bindings | 說明 |
|---|---|---|
default | {} | — |
admin-dialog-title
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
asChild | boolean | undefined | — | Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
as | globalThis.Component | AsTag | undefined | "div" | The element or component this component should render as. Can be overwritten by `asChild`. |
class | ClassValue | — | 根元素之自訂 class |
Slots
| 名稱 | Bindings | 說明 |
|---|---|---|
default | {} | — |
admin-dialog-trigger
Props
| 名稱 | 型別 | 預設值 | 說明 |
|---|---|---|---|
asChild | boolean | undefined | — | Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
as | globalThis.Component | AsTag | undefined | "div" | The element or component this component should render as. Can be overwritten by `asChild`. |
class | unknown | — | — |
Slots
| 名稱 | Bindings | 說明 |
|---|---|---|
default | {} | — |
更新紀錄
- feat: 新增 admin-dialog-scroll-content 並統一 description token1d86dd8