For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/v/0.6.0/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/v/0.6.0/llms-full.txt, and this page is available as Markdown at https://ifhover.github.io/leaf-ui/v/0.6.0/components/modal.md.
  • 简体中文
  • Modal 弹窗

    在弹窗中展示内容或完成操作。

    编辑内容

    basic.tsx
    import { Button, Form, FormField, Input, Modal, Select } from '@ifhover/leaf-ui';
    
    import { useRef, useState } from 'react';
    
    export function ModalBasic() {
      const [open, setOpen] = useState(false);
      const formRef = useRef<HTMLFormElement>(null);
      return (
        <>
          <Button onClick={() => setOpen(true)}>编辑项目</Button>
          <Modal
            open={open}
            title="项目设置"
            confirmText="保存"
            onClose={() => setOpen(false)}
            onConfirm={() => formRef.current?.requestSubmit()}
          >
            <Form
              ref={formRef}
              layout="vertical"
              onSubmit={(event) => {
                event.preventDefault();
                setOpen(false);
              }}
            >
              <FormField label="项目名称" required>
                <Input name="name" defaultValue="Leaf UI" />
              </FormField>
              <FormField label="负责人">
                <Select
                  name="owner"
                  options={[
                    { value: 'design', label: '设计团队' },
                    { value: 'engineering', label: '工程团队' },
                  ]}
                />
              </FormField>
            </Form>
          </Modal>
        </>
      );
    }
    

    自定义底部

    footer.tsx
    import { Button, Modal } from '@ifhover/leaf-ui';
    
    import { useState } from 'react';
    
    export function ModalFooter() {
      const [open, setOpen] = useState(false);
      const [extra, setExtra] = useState(false);
      return (
        <>
          <Button variant="outline" onClick={() => setOpen(true)}>
            自定义底部
          </Button>
          <Modal
            open={open}
            title="扩展操作"
            onClose={() => setOpen(false)}
            footer={({ cancelButton, confirmButton }) => (
              <>
                <Button
                  variant="ghost"
                  style={{ marginRight: 'auto' }}
                  onClick={() => setExtra(!extra)}
                >
                  查看详情
                </Button>
                {cancelButton}
                {confirmButton}
              </>
            )}
          >
            <p>通过底部函数增加操作,保留默认取消与确定按钮。</p>
            {extra && <p>这里展示额外的信息。</p>}
          </Modal>
        </>
      );
    }
    

    状态销毁与初始焦点

    capabilities.tsx
    import { Button, Input, Modal } from '@ifhover/leaf-ui';
    
    import { useRef, useState } from 'react';
    
    export function Capabilities() {
      const [open, setOpen] = useState(false);
      const focus = useRef<HTMLInputElement>(null);
      return (
        <>
          <Button onClick={() => setOpen(true)}>{'打开编辑器'}</Button>
          <Modal
            open={open}
            onClose={() => setOpen(false)}
            title={'临时草稿'}
            destroyOnClose
            initialFocus={focus}
            footer={({ cancelButton, confirmButton }) => (
              <>
                {cancelButton}
                {confirmButton}
              </>
            )}
          >
            <Input
              ref={focus}
              aria-label={'草稿标题'}
              placeholder={'关闭后不保留草稿'}
            />
          </Modal>
        </>
      );
    }
    

    图标与说明

    使用 icon 和 description 为操作补充上下文。

    description.tsx
    import { Button, Modal } from '@ifhover/leaf-ui';
    
    import { Save } from 'lucide-react';
    
    import { useState } from 'react';
    
    export function ModalDescription() {
      const [open, setOpen] = useState(false);
      return (
        <>
          <Button variant="outline" onClick={() => setOpen(true)}>
            带图标与说明
          </Button>
          <Modal
            open={open}
            title="保存设置"
            description="保存后,新设置将立即生效。"
            icon={<Save />}
            confirmText="保存"
            onClose={() => setOpen(false)}
            onConfirm={() => setOpen(false)}
          >
            确认保存当前设置?
          </Modal>
        </>
      );
    }
    

    正文使用 Scrollbar,内容较长时内部滚动,标题和操作按钮始终可见。没有副标题时头部更紧凑,底部使用较小的纵向留白。

    属性类型默认值说明
    initialFocusRefObject<HTMLElement | null> | (() => HTMLElement | null)—指定打开后的初始焦点。
    returnFocusboolean | RefObject<HTMLElement | null> | (() => HTMLElement | null)—关闭后返回原焦点;也可指定目标或设为 false。
    openboolean必填必需。是否显示弹窗
    titleReactNode—标题 / 内容
    descriptionReactNode—补充说明。
    iconReactNode—标题左侧的装饰图标。
    dividedbooleantrue用浅分隔线划分标题、内容和底部操作区。
    footerReactNode | ((actions: ModalFooterActions) => ReactNode)取消 + 确定自定义底部;null 隐藏;函数接收默认按钮
    confirmTextReactNode语言默认值按钮文字
    cancelTextReactNode语言默认值按钮文字
    confirmLoadingbooleanfalse确认加载状态
    confirmButtonPropsButtonProps—定制默认按钮属性
    cancelButtonPropsButtonProps—定制默认按钮属性
    onConfirm() => void | Promise<void>—由应用控制 open;Promise 拒绝时显示错误
    onCancel() => void—取消或关闭请求,未指定时使用 onClose
    widthnumber | string480弹窗宽度,数字为像素
    closablebooleantrue关闭按钮 / 点击遮罩关闭 / Escape 关闭
    maskClosablebooleantrue关闭按钮 / 点击遮罩关闭 / Escape 关闭
    keyboardbooleantrue关闭按钮 / 点击遮罩关闭 / Escape 关闭
    onClose() => void—请求关闭,由应用更新 open
    afterClose() => void—关闭动画完成后触发
    forceRenderbooleanfalse打开前也挂载内容,关闭时保持隐藏。
    destroyOnClosebooleanfalse关闭过渡完成后卸载内容;默认保留。
    preserveboolean—显式控制关闭后是否保留内容,优先于 destroyOnClose。
    containerElement | DocumentFragment | (() => Element | DocumentFragment)—自定义挂载或滚动容器。

    ModalFooterActions

    属性类型默认值说明
    confirmButtonReactNode—必需。默认确认按钮,保留加载状态
    cancelButtonReactNode—必需。默认取消按钮

    类型

    定义组件属性或组装变量时可导入相关类型。

    import type { ModalProps, ModalFooterActions } from '@ifhover/leaf-ui';

    使用说明

    弹窗打开后聚焦内部控件,Tab 在弹窗中移动;Escape 关闭后恢复触发前的焦点。maskClosable、keyboard 可分别关闭遮罩、键盘退出。没有 title 时请提供 aria-label。

    footer 可放确认、取消等操作;也可以在内容中使用 Form。弹窗中的选择器浮层沿用区域主题。

    默认底部按取消、确定顺序靠右排列。传入 onConfirm 时,完成操作后自行更新 open;未传入时确定调用 onClose。Promise 执行期间显示加载状态并避免重复操作。提交表单可在 onConfirm 中调用 form.requestSubmit(),或通过 confirmButtonProps 设置 type="submit" 与 form ID,保留表单校验。footer 函数可扩展默认按钮,footer={null} 隐藏底部。

    DialogFocusOptions

    属性类型默认值说明
    initialFocusRefObject<HTMLElement | null> | (() => HTMLElement | null)—指定打开后的初始焦点。
    returnFocusboolean | RefObject<HTMLElement | null> | (() => HTMLElement | null)—关闭后返回原焦点;也可指定目标或设为 false。

    外观与丰富内容

    description 为标题提供补充说明,icon 放在标题左侧。默认 divided 使用浅分隔线和淡灰操作区;divided={false} 使用留白分区。footer 函数可在左侧加入状态文字,使用 Space 把按钮放在同一组,窄屏时整组换行并靠右排列。