秋名山最速传说,2分钟,模态框

最土最简单的模态框。

最土最简单的模态框

这个模态框的名字叫起来特别古怪,其实就是高亮显示一个东西(比如图中的搜索框),
根据不同需要:

  1. 只有被高亮显示的那个东东可以进行交互,半透明的黑色背景上鼠标点击是无效的
  2. 被高亮显示的东东可以交互,但是半透明的黑色背景上鼠标点击是有效,效果一般就是让高亮显示的那个东东消失掉。

下面一段程序文本就是一个最简单的模态框背景,他是一个react function component,
html模板是一个fixed定位的、高度为100vh、宽度为100vw、opacity为0.8的div,
他有三个参数,state、setstate、zIndex。state是必选参数,控制modal背景是否出现,setstate可选参数,若传入这个参数,黑色背景对点击是有反馈的(也就是点了会切换state),不传入,那么黑色背景对点击没有反馈。zIndex默认是10,可以根据需要来调整,不过建议你调整你需要高亮显示的模态框卡片的zIndex,这样更好。

import React, { ReactElement } from "react";
import cs from "classnames";

import ButtonCustomized from "../../../../lib/Button/ButtonCustomized/ButtonCutomized";
interface Props {}
/**
 *a custom hook ,can make your input auto focus
 * @param inputRef  the ref of the input elment which u wanna focus on
 * @param state the state that decides whether your input is visible
 */
function useFocusInputDependOnState(
  inputRef: React.MutableRefObject<null>,
  state: any
) {
  // 注意, 即使是useLayoutEffect ,自动focus也失效.
  //用setTimeout做个更慢的延迟。。
  React.useEffect(() => {
    setTimeout(() => {
      (inputRef.current as any).focus();
    }, 100);
    (inputRef.current as any).focus();
    return () => {
      // can this clear operation work? will it cause any trouble?
      inputRef = null as unknown as React.MutableRefObject<null>;
    };
  }, [state]);
}

export default function RollingInput({}: Props): ReactElement {
  // 开合状态的state
  const [state, setstate] = React.useState(false);
  //input value的状态
  const [val, setval] = React.useState("");

  let inputRef = React.useRef(null);

  useFocusInputDependOnState(inputRef, state);

  return (
    <div className="tw-relative">
      <div
        className={cs("tw-absolute  tw-w-4/5 tw-transition-all ", {
          "tw-pt-0": state === false,
          "tw-pt-4": state,
          "tw-h-0": state === false,
          "tw-duration-300": state,
        })}
      >
        <div
          //z-index 仅在有定位属性的元素上生效,所以下面的tw-relative 就是为了让tw-z-50生效
          className={cs(
            "-tw-mt-4 tw-flex tw-duration-100 tw-relative tw-z-50 ",
            {
              "tw-invisible": !state,
            }
          )}
        >
          <input
            className="tw-caret-purple-800 tw-rounded-l-md tw-outline-none tw-leading-[3.5rem] tw-text-4xl tw-pl-3 tw-align-middle tw-h-14 tw-text-black tw-w-4/5 "
            type="text"
            value={val}
            ref={inputRef}
            onChange={(e) => {
              e.preventDefault();
              setval(e.target.value);
            }}
            autoFocus
          />

          <div className="">
            <ButtonCustomized
              color="primary"
              onClick={(e) => {
                e.preventDefault();
                setstate(!state);
              }}
              height={3.5}
              width={6}
            >
              提交
            </ButtonCustomized>
          </div>
        </div>
      </div>

      <div
        className="tw-h-16 tw-w-4/5 tw-bg-orange-500"
        onClick={(e) => {
          e.preventDefault();
          setstate(!state);
        }}
      >
        在这里添加任务
      </div>

      <ModalBackground state={state} setstate={setstate}></ModalBackground>
    </div>
  );
}
/**
 * a violent overlay 
 * 
 *two params:
 state,decide whether it's show,
 setstate, change the state.
 it's a controlled component;

 attention,if u want a modal mask(which means background overlay doesn't respond to click), 
 pass in the setstate,
 if u want a non-modal one,don't pass in the setstate.
 the overlay's default zIndex is 10,make  sure your dialog or some other modal card's index is higher.
 */
export function ModalBackground({
  state,
  setstate,
  zIndex = 10,
}: {
  state: boolean;
  setstate?: React.Dispatch<React.SetStateAction<boolean>>;
  zIndex?: number;
}): ReactElement {
  return (
    <div
      onClick={() => {
        if (setstate !== undefined) {
          if (state === true) {
            setstate(!state);
          }
        } else {
          if (process.env.NODE_ENV === "development")
            console.log("seems you want a non-modal mask");
        }
      }}
      className={cs(
        "tw-fixed tw-w-screen tw-h-screen tw-bg-black tw-opacity-80 tw-top-0 tw-left-0",
        {
          "tw-invisible": !state,
        }
      )}
      style={{ zIndex: `${zIndex}` }}
    ></div>
  );
}

posted @ 2023-02-04 23:53  刘老六  阅读(22)  评论(0编辑  收藏  举报