跳至正文

Modal

基于原生dialog元素的模态对话框。

浏览器
Chrome 123+Firefox 121+Safari 17.5+
层级
0
压缩后大小
944 B
强制布局预算
0 ms
axe 预算
0
支持 SSR
是
基于
elements/dialog
公开契约
测试环境

交互示例

Modal

关闭

受控

水合后,此模态对话框由父级状态控制。

变更次数:0,状态: 关闭

示例

Sizes

size writes data-size: sm 24rem, md (default) 28rem, lg 40rem, full fills the viewport. On a phone every size except full is a bottom sheet.

Small

24rem wide.

Large

40rem wide.

import { Modal } from "@gunkin/uiify";

export default function Example() {
  return (
    <>
      <Modal id="size-sm" size="sm" title="Small" trigger="Small">
        <p>24rem wide.</p>
      </Modal>
      <Modal id="size-lg" size="lg" title="Large" trigger="Large">
        <p>40rem wide.</p>
      </Modal>
    </>
  );
}

Long content

The title, content and footer share one scroll area. Compose the parts inside ModalBody for a document-style dialog.

Terms of service

The whole document scrolls together.

Clause 1: text that makes the document taller than the screen.

Clause 2: text that makes the document taller than the screen.

Clause 3: text that makes the document taller than the screen.

Clause 4: text that makes the document taller than the screen.

Clause 5: text that makes the document taller than the screen.

Clause 6: text that makes the document taller than the screen.

Clause 7: text that makes the document taller than the screen.

Clause 8: text that makes the document taller than the screen.

Clause 9: text that makes the document taller than the screen.

Clause 10: text that makes the document taller than the screen.

Clause 11: text that makes the document taller than the screen.

Clause 12: text that makes the document taller than the screen.

Clause 13: text that makes the document taller than the screen.

Clause 14: text that makes the document taller than the screen.

Clause 15: text that makes the document taller than the screen.

Clause 16: text that makes the document taller than the screen.

Clause 17: text that makes the document taller than the screen.

Clause 18: text that makes the document taller than the screen.

Clause 19: text that makes the document taller than the screen.

Clause 20: text that makes the document taller than the screen.

Clause 21: text that makes the document taller than the screen.

Clause 22: text that makes the document taller than the screen.

Clause 23: text that makes the document taller than the screen.

Clause 24: text that makes the document taller than the screen.

Clause 25: text that makes the document taller than the screen.

Clause 26: text that makes the document taller than the screen.

Clause 27: text that makes the document taller than the screen.

Clause 28: text that makes the document taller than the screen.

Clause 29: text that makes the document taller than the screen.

Clause 30: text that makes the document taller than the screen.

import { ModalTrigger, ModalContent, ModalBody, ModalHeader, ModalTitle, ModalClose, ModalFooter } from "@gunkin/uiify";
export default function Example() {
  return <>
    <ModalTrigger target="terms">Read terms</ModalTrigger>
    <ModalContent id="terms" aria-labelledby="terms-title">
      <ModalBody>
        <ModalHeader><ModalTitle id="terms-title">Terms of service</ModalTitle><ModalClose aria-label="Close" target="terms">×</ModalClose></ModalHeader>
        {Array.from({ length: 30 }, (_, index) => <p key={index}>Clause {index + 1}: text that makes the document taller than the screen.</p>)}
        <ModalFooter><ModalClose target="terms">Done</ModalClose></ModalFooter>
      </ModalBody>
    </ModalContent>
  </>;
}

Opening a modal from a modal

Render the child Modal inside the parent. It opens on top, Escape closes only the child, focus returns to the button that opened it, and the page is dimmed once.

Edit profile

Unsaved changes are lost when you close.

Discard changes?

This cannot be undone.

import { Modal, ModalClose } from "@gunkin/uiify";

export default function Example() {
  return (
    <Modal
      id="editor"
      trigger="Edit profile"
      title="Edit profile"
      description="Unsaved changes are lost when you close."
    >
      <Modal
        id="discard"
        trigger="Discard changes"
        title="Discard changes?"
        description="This cannot be undone."
        footer={<ModalClose target="discard">Keep editing</ModalClose>}
      />
    </Modal>
  );
}

API

Modal

ModalTrigger

属性类型默认值说明
target*string—此按钮打开的ModalContent id;浏览器在点击时解析,无须运行库的JavaScript。
childrenReactNode—触发器按钮的内容。
asTAs & NativeButtonAs<TAs>"button"将props和ref转发给原生按钮的组件;拒绝其他标签,因为调用命令需要真实按钮。

ModalContent

属性类型默认值说明
id*string—使用方提供的唯一id,由触发器和关闭目标引用。
size"sm" | "md" | "lg" | "full""md"宽度档位(24、28、40rem)。full填满视口。写入data-size;自定义宽度可覆盖--uiify-modal-inline-size。
align"center" | "start""center"平板和桌面上的垂直位置。手机上显示为底部面板,除非size为full。
dismiss"any" | "closerequest" | "none""any"closedby:any允许点击遮罩,closerequest只允许Escape,none只允许自有控件。Safari缺少closedby,因此Escape始终关闭;UIEnhance处理遮罩点击(any)和面板滑动(非none)。
backdrop"opaque" | "blur" | "none""opaque"遮罩处理方式。写入data-backdrop。
childrenReactNode—对话框内容。

ModalClose

属性类型默认值说明
target*string—此按钮关闭的ModalContent id。
childrenReactNode—关闭按钮的内容。
asTAs & NativeButtonAs<TAs>"button"将props和ref转发给原生按钮的组件;拒绝其他标签,因为调用命令需要真实按钮。

ModalHeader

属性类型默认值说明
childrenReactNode—固定在顶部的行,包含标题、描述和关闭控件。

ModalTitle

属性类型默认值说明
childrenReactNode—对话框的无障碍名称;通过aria-labelledby引用其id。

ModalDescription

属性类型默认值说明
childrenReactNode—辅助文本;通过aria-describedby引用其id。

ModalBody

属性类型默认值说明
childrenReactNode—页头与页脚之间的滚动区域。

ModalFooter

属性类型默认值说明
childrenReactNode—固定在主体下方的操作行。

ModalGrabber

属性类型默认值说明
childrenReactNode—移动端底部面板的装饰性拖动手柄;滑动从此处开始。

ModalClientContent (@gunkin/uiify/components/modal/client)

属性类型默认值说明
id*string—使用方提供的唯一id,由触发器和Close引用。
openboolean—受控打开状态,水合后以此为准。
defaultOpenboolean—非受控初始状态,水合后通过showModal()应用;服务端标记保持关闭。
onOpenChange(open: boolean) => void—每次原生或程序化变更时使用新状态触发一次;若浏览器在水合前已打开,挂载时也触发一次。
onOpenChangeComplete(open: boolean) => void—每次打开或关闭变更的CSS过渡完成后触发一次;没有过渡时立即触发,包括水合后的defaultOpen变更;对话框状态不变时绝不触发。
size"sm" | "md" | "lg" | "full""md"宽度档位(24、28、40rem)。full填满视口。写入data-size;自定义宽度可覆盖--uiify-modal-inline-size。
align"center" | "start""center"平板和桌面上的垂直位置。手机上显示为底部面板,除非size为full。
dismiss"any" | "closerequest" | "none""any"closedby:any允许点击遮罩,closerequest只允许Escape,none只允许自有控件。Safari缺少closedby,因此Escape始终关闭;UIEnhance处理遮罩点击(any)和面板滑动(非none)。
backdrop"opaque" | "blur" | "none""opaque"遮罩处理方式。写入data-backdrop。
childrenReactNode—对话框内容。

键盘

按键操作
Escape关闭(嵌套时仅关闭最上层模态对话框)
Tab在模态对话框内循环移动焦点
Shift+Tab反向Tab顺序

无障碍

原生<dialog>在任何JavaScript运行前即可由command="show-modal"调用按钮打开。浏览器管理模态性、焦点限制、Escape和焦点返回;关闭使用request-close,因此onCancel可以阻止。页头关闭图标始终存在。在手机上,模态对话框为底部面板;向下滑动和点击遮罩是快捷关闭方式,绝非唯一出口。

样式钩子

data-uiify-modaldata-part="trigger|content|header|title|description|body|footer|grabber|close"data-size="sm|lg|full"data-align="start"data-backdrop="blur|none"--uiify-trigger-open (inside [data-uiify-modal][data-part="root"])--uiify-modal-inline-size (dialog width)
本页由机器翻译,尚未经人工审核。