跳转正文

YModal ​

中心聚焦的任务容器。用于编辑、确认和选择;业务草稿、保存和权威回读仍由Feature拥有。

Usage ​

Import / Basic ​

vue
<script setup lang="ts">
import { ref } from 'vue'
import { YModal } from '@yoyoboot/ui-patterns/modal'
const open = ref(false), name = ref(''), saving = ref(false)
</script>
<template>
  <UButton @click="open = true">编辑</UButton>
  <YModal v-model:open="open" title="编辑" size="lg" expandable
    :guard="{ dirty: () => !!name, busy: () => saving }">
    <UInput v-model="name" aria-label="名称" />
    <template #footer="{ close }"><UButton @click="close()">取消</UButton></template>
  </YModal>
</template>

Programmatic task ​

应用沿现有 createModalHelper/modalHelperKey 接线,在setup中connect(useOverlay())。useModalHelper().open(Component, params, options)获得ModalRef,其result直接沿Nuxt UI实例通道,不再创建结果Promise。任务组件接收modal并传给YModal;after:leave转发供上游释放。

modal.notifySaved(value, true)表示保存继续;完成、取消、失效由原ModalRef合同区分。保存成功不自动代表列表刷新成功。parent/replace保留原保护规则,不扩为通用OverlayHelper。

Size / fullscreen / stable ​

size为sm/md/lg,分别使用max-w-md/max-w-2xl/max-w-4xl;fullscreen、expandable控制全屏,stable使用稳定任务高度。body独立滚动,footer保留safe-area。组件属性优先于ModalRef options。

标题栏与拖动 ​

标题与说明在左侧可收缩区域,fullscreen/restore 与 close 固定在右侧工具区;长标题和窄屏不会把按钮挤走,Feature 不需要用 margin 或私有 CSS 修正位置。

draggable 默认 true,只在桌面非全屏、fine pointer 且 viewport ≥768px 时生效:

  • 从标题栏非交互区域开始拖动;关闭、全屏、链接、按钮和输入上的指针操作不启动拖动;
  • 拖动只改当前实例的临时位置:位置限制在视口内,标题栏和关闭始终可达;窗口尺寸变化后重新限制;
  • fullscreen 忽略临时偏移,restore 恢复进入全屏前的位置并按当前视口重新限制;fullscreen 中不启动拖动;
  • 关闭或新建实例回标准位置,不写 localStorage/sessionStorage。

不需要拖动时显式 :draggable="false"。明确不做:边缘 resize、跨会话位置记忆、窗口管理器、记录上一条/下一条。

Task guard / dirty / busy ​

guard 可省略;只读详情不需要草稿或保存按钮。guard读取业务状态,不复制它:

ts
const guard = { dirty: () => draft.value !== baseline.value, busy: () => saving.value }

关闭按钮、Escape、允许的outside dismiss和slot/exposed close()共享关闭策略:busy拒绝;dirty显示放弃确认;确认返回后再次检查busy。业务保存成功或身份/页面失效时,父组件直接令open=false是权威终止,不再询问放弃;普通取消必须调用安全close,而不是直接写open=false。

Responsive / long content ​

组件类型不会随viewport改变。通过ui.content选择宽度,body滚动,footer保留safe-area。页面自己的提交、验证和回读继续由Feature负责。

Nested / focus ​

子任务应渲染在父任务的body/content插槽内,使用现有YModal或选择组件。上游负责portal/focus trap;父任务guard可把子任务open纳入busy,防止操作绕过。关闭子任务后焦点回到父触发器。focusFirstField()定位首个可编辑输入,focusFirstError()定位aria-invalid字段并滚到可见位置;自定义输入控件需要提供正确的可聚焦节点与aria-invalid标记。

API ​

Props ​

属性合同
title必填标题
description可选说明
open声明式v-model,默认false;传modal时由ModalRef拥有
modal可选ModalRef
guard可选ModalGuard,兼容TaskSurfaceGuard;声明式任务使用
sizesm/md/lg,默认沿modal.options或md
fullscreen / expandable默认沿modal.options或false
closeOnOutside默认沿modal.options或false
draggable默认沿modal.options或true;桌面非全屏、fine pointer 且 viewport ≥768px 才生效
stable默认false

Models / Events ​

声明式update:open;after:leave;close(ModalResult)用于声明式结果。ModalRef结果status包括completed/saved/cancelled/invalidated。直接open=false/finish失效由Owner负责,普通取消使用safe close。

Slots / Exposed methods ​

default/body为任务内容;footer得到close、complete。暴露close、complete(value)、focusFirstField、focusFirstError。ModalGuard旧import路径继续有效;没有Drawer/SlideoverHelper。

Theme / Visual ​

安装 @yoyoboot/ui-patterns/visual/management.css 和 visual/motion.css。header/footer/body由management foundation持有,不要求Feature复制背景色。组件仅显式标记自己的Task Surface,不要求安装Starter外壳;ui可以覆盖具体布局。支持light/dark、既有density和reduced-motion,无Skin runtime。

Accessibility ​

提供有意义的title/description;无障碍关联、遮罩、焦点限制与恢复沿Nuxt UI。busy禁止正常取消但不替业务取消服务端写入;字段错误由Feature标记。Esc在dismissible=false时由上游阻止;close按钮和显式close()仍可在guard许可时取消。

何时不用 YModal ​

以下继续使用上游 UModal,它们不拥有业务草稿、关闭保护或结果合同,也不建立第二套 ModalHelper:

  • YModal 自身的放弃修改确认,避免递归;
  • 公共 TaskSurfaceConfirmation 的内部确认;
  • YTreePicker 的响应式选择原语(桌面 Popover、移动 Modal);
  • Host 的路由离开未保存确认与身份返回阻塞。

普通新增、编辑、选择、导入导出任务用 YModal。仍直接用上游 UModal 的业务任务由 govern-yoyo-admin-umodal-adoption-v1 跟踪。

Underlying primitive ​

基于Nuxt UI UModal,保留原生焦点陷阱、portal与过渡机制。

Source / Verification ​

源码 packages/ui-patterns/src/modal/YModal.vue、contracts.ts、modal-helper.ts、drag.ts。拖动几何、fullscreen 位置与并发实例的不变量由 packages/ui-patterns/tests/modal-drag.spec.ts 覆盖。示例使用正式入口;可运行嵌套实例在 packages/ui-patterns/tests/fixtures/task-surfaces/App.vue。本页是该组件的 canonical 文档;是否进入 VitePress、公开 URL 与导航由 docs/site.manifest.json 决定。

源码入口 · 共享关闭策略

YoyoBoot · 从真实项目走向可复用能力