模态框

模态框是一种对话框,通过覆盖在主要内容上的窗口将用户的注意力专门集中在信息上。

导入

import {
  Modal,
  ModalOverlay,
  ModalContent,
  ModalHeader,
  ModalTitle,
  ModalCloseButton,
  ModalBody,
  ModalFooter,
} from "@resolid/react-ui";
  • Modal: 为其子级提供上下文的包装器。
  • ModalOverlay: 模态框后面的灰度叠加层。
  • ModalContent: 模态框内容的容器。
  • ModalHeader: 模态框的头部。
  • ModalTitle: 模态框的标题。
  • ModalCloseButton: 关闭模态框的按钮。
  • ModalBody: 包含模态框主要内容的包装器。
  • ModalFooter: 模态框的页脚。

基础

const [opened, setOpened] = useState(false);

return (
  <>
    <Button onClick={() => setOpened(true)}>打开模态框</Button>
    <Modal opened={opened} onClose={() => setOpened(false)}>
      <ModalOverlay />
      <ModalContent className={'w-11/12 md:w-3/5 lg:w-1/3'}>
        <ModalHeader className={"p-4"}>
          <ModalTitle>模态框标题</ModalTitle>
          <ModalCloseButton />
        </ModalHeader>
        <ModalBody className={'p-1 px-4'}>模态框内容</ModalBody>
        <ModalFooter className={'p-4 flex items-center justify-center gap-5'}>
          <Button onClick={() => setOpened(false)}>关闭</Button>
        </ModalFooter>
      </ModalContent>
    </Modal>
  </>
);

居中

const [opened, setOpened] = useState(false);

return (
  <>
    <Button onClick={() => setOpened(true)}>打开模态框</Button>
    <Modal centered opened={opened} onClose={() => setOpened(false)}>
      <ModalOverlay />
      <ModalContent className={'w-11/12 md:w-3/5 lg:w-1/3'}>
        <ModalHeader className={"p-4"}>
          <ModalTitle>模态框标题</ModalTitle>
          <ModalCloseButton />
        </ModalHeader>
        <ModalBody className={'p-1 px-4'}>模态框内容</ModalBody>
        <ModalFooter className={'p-4 flex items-center justify-center gap-5'}>
          <Button onClick={() => setOpened(false)}>关闭</Button>
        </ModalFooter>
      </ModalContent>
    </Modal>
  </>
);

嵌套

const [opened, setOpened] = useState(false);

return (
  <>
    <Button onClick={() => setOpened(true)}>打开模态框</Button>
    <Modal opened={opened} onClose={() => setOpened(false)}>
      <ModalOverlay />
      <ModalContent className={'w-11/12 md:w-3/5 lg:w-1/3'}>
        <ModalHeader className={"p-4"}>
          <ModalTitle>模态框标题</ModalTitle>
          <ModalCloseButton />
        </ModalHeader>
        <ModalBody className={'p-1 px-4'}>
          <Button onClick={() => setNestOpened(true)}>打开嵌套模态框</Button>
          <Modal opened={nestOpened} onClose={() => setNestOpened(false)}>
            <ModalOverlay />
            <ModalContent className={'w-60'}>
              <ModalHeader className={"p-4"}>
                <ModalTitle>嵌套模态框标题</ModalTitle>
                <ModalCloseButton />
              </ModalHeader>
              <ModalBody className={'p-1 px-4'}>
                嵌套模态框内容
              </ModalBody>
              <ModalFooter className={'p-4 flex items-center justify-center gap-5'}>
                <Button onClick={() => setNestOpened(false)}>关闭</Button>
              </ModalFooter>
            </ModalContent>
          </Modal>
        </ModalBody>
        <ModalFooter className={'p-4 flex items-center justify-center gap-5'}>
          <Button onClick={() => setOpened(false)}>关闭</Button>
        </ModalFooter>
      </ModalContent>
    </Modal>
  </>
);

解锁页面滚动条

const [opened, setOpened] = useState(false);

return (
  <>
    <Button onClick={() => setOpened(true)}>打开模态框</Button>
    <Modal lockScroll={false} opened={opened} onClose={() => setOpened(false)}>
      <ModalOverlay />
      <ModalContent className={'w-11/12 md:w-3/5 lg:w-1/3'}>
        <ModalHeader className={"p-4"}>
          <ModalTitle>模态框标题</ModalTitle>
          <ModalCloseButton />
        </ModalHeader>
        <ModalBody className={'p-1 px-4'}>模态框内容</ModalBody>
        <ModalFooter className={'p-4 flex items-center justify-center gap-5'}>
          <Button onClick={() => setOpened(false)}>关闭</Button>
        </ModalFooter>
      </ModalContent>
    </Modal>
  </>
);

滚动行为

const [opened, setOpened] = useState(false);
const [scrollBehavior, setScrollBehavior] = useState("inside");

return (
  <>
    <RadioGroup value={scrollBehavior} onChange={setScrollBehavior}>
      <div className={"flex flex-row gap-5"}>
        <Radio value="inside">内部</Radio>
        <Radio value="outside">外部</Radio>
      </div>
    </RadioGroup>
    <Button onClick={() => setOpened(true)}>打开模态框</Button>
    <Modal scrollBehavior={scrollBehavior} opened={opened} onClose={() => setOpened(false)}>
      <ModalOverlay />
      <ModalContent className={"w-11/12 md:w-3/5 lg:w-1/3"}>
        <ModalHeader className={"p-4"}>
          <ModalTitle>模态框标题</ModalTitle>
          <ModalCloseButton />
        </ModalHeader>
        <ModalBody className={"p-1 px-4"}>模态框内部大量内容</ModalBody>
        <ModalFooter className={"p-4 flex items-center justify-center gap-5"}>
          <Button onClick={() => setOpened(false)}>关闭</Button>
        </ModalFooter>
      </ModalContent>
    </Modal>
  </>
);

焦点管理

模态框打开会自动将焦点设置在第一个可用的元素上(一般默认是关闭按钮),关闭时会自动返回焦点,你可以通过设置 initialFocusfinalFocus 属性来自定义焦点目标

const [opened, setOpened] = useState(false);
const initialRef = useRef(null);
const finalRef = useRef(null);

return (
  <>
    <Button onClick={() => setOpened(true)}>打开模态框</Button>
    <Button color={"neutral"} ref={finalRef}>
      键盘关闭模态框后获得焦点
    </Button>
    <Modal initialFocus={initialRef} finalFocus={finalRef} opened={opened} onClose={() => setOpened(false)}>
      <ModalOverlay />
      <ModalContent className={"w-fit"}>
        <ModalHeader className={"p-4"}>
          <ModalTitle>模态框标题</ModalTitle>
          <ModalCloseButton />
        </ModalHeader>
        <ModalBody className={"flex flex-col gap-3 p-1 px-4"}>
          <div className={"flex flex-row items-center"}>
            <label htmlFor={"username"} className={"w-28"}>
              用户名 <span className={"text-red-500"}>*</span>
            </label>
            <Input ref={initialRef} placeholder={"用户名"} id={"username"} />
          </div>
          <div className={"flex flex-row items-center"}>
            <label htmlFor={"email"} className={"w-28"}>
              电子邮箱 <span className={"text-red-500"}>*</span>
            </label>
            <Input placeholder={"电子邮箱"} id={"email"} />
          </div>
        </ModalBody>
        <ModalFooter className={"p-4 flex items-center justify-center gap-5"}>
          <Button onClick={() => setOpened(false)}>关闭</Button>
        </ModalFooter>
      </ModalContent>
    </Modal>
  </>
);

自定义背景样式

const OverlayBlur = () => <ModalOverlay className="backdrop-blur-sm" />;
const OverlayHueRotate = () => <ModalOverlay className="backdrop-hue-rotate-30" />;

const [opened, setOpened] = useState(false);
const [overlay, setOverlay] = useState(<OverlayBlur />);

return (
  <>
    <Button
      onClick={() => {
        setOverlay(<OverlayBlur />);
        setOpened(true);
      }}
    >
      模糊样式
    </Button>
    <Button
      onClick={() => {
        setOverlay(<OverlayHueRotate />);
        setOpened(true);
      }}
    >
      色相变换样式
    </Button>
    <Modal opened={opened} onClose={() => setOpened(false)}>
      {overlay}
      <ModalContent className={"w-11/12 md:w-3/5 lg:w-1/3"}>
        <ModalHeader className={"p-4"}>
          <ModalTitle>模态框标题</ModalTitle>
          <ModalCloseButton />
        </ModalHeader>
        <ModalBody className={"p-1 px-4"}>模态框内容</ModalBody>
        <ModalFooter className={"p-4 flex items-center justify-center gap-5"}>
          <Button onClick={() => setOpened(false)}>关闭</Button>
        </ModalFooter>
      </ModalContent>
    </Modal>
  </>
);

属性

属性opened类型boolean默认值-必须true
属性onClose类型() => void默认值-必须true
属性centered类型boolean默认值-必须false
属性lockScroll类型boolean默认值true必须false
属性initialFocus类型number | RefObject<HTMLElement>默认值-必须false
属性finalFocus类型RefObject<HTMLElement>默认值-必须false
属性scrollBehavior类型"inside" | "outside"默认值'outside'必须false
属性onCloseComplete类型() => void默认值-必须false
属性closeOnEsc类型boolean默认值true必须false
属性closeOnBlur类型boolean默认值true必须false
属性duration类型number默认值'250'必须false