mirror of
https://github.com/Yidadaa/ChatGPT-Next-Web.git
synced 2025-09-07 16:47:03 +08:00
feat: redesign settings page
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import useRelativePosition from "@/app/hooks/useRelativePosition";
|
||||
import { getCSSVar } from "@/app/utils";
|
||||
import { useMemo, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
|
||||
const ArrowIcon = ({ color }: { color: string }) => {
|
||||
return (
|
||||
@@ -19,6 +21,20 @@ const ArrowIcon = ({ color }: { color: string }) => {
|
||||
};
|
||||
|
||||
const baseZIndex = 100;
|
||||
const popoverRootName = "popoverRoot";
|
||||
let popoverRoot = document.querySelector(
|
||||
`#${popoverRootName}`,
|
||||
) as HTMLDivElement;
|
||||
if (!popoverRoot) {
|
||||
popoverRoot = document.createElement("div");
|
||||
document.body.appendChild(popoverRoot);
|
||||
popoverRoot.style.height = "0px";
|
||||
popoverRoot.style.width = "100%";
|
||||
popoverRoot.style.position = "fixed";
|
||||
popoverRoot.style.bottom = "0";
|
||||
popoverRoot.style.zIndex = "100";
|
||||
popoverRoot.id = "popoverRootName";
|
||||
}
|
||||
|
||||
export default function Popover(props: {
|
||||
content?: JSX.Element | string;
|
||||
@@ -46,6 +62,21 @@ export default function Popover(props: {
|
||||
} = props;
|
||||
|
||||
const [internalShow, setShow] = useState(false);
|
||||
const { position, getRelativePosition } = useRelativePosition({
|
||||
delay: 0,
|
||||
});
|
||||
|
||||
const {
|
||||
distanceToBottomBoundary = 0,
|
||||
distanceToLeftBoundary = 0,
|
||||
distanceToRightBoundary = -10000,
|
||||
distanceToTopBoundary = 0,
|
||||
targetH = 0,
|
||||
targetW = 0,
|
||||
} = position?.poi || {};
|
||||
|
||||
let placementStyle: React.CSSProperties = {};
|
||||
const popoverCommonClass = `absolute p-2 box-border`;
|
||||
|
||||
const mergedShow = show ?? internalShow;
|
||||
|
||||
@@ -56,6 +87,13 @@ export default function Popover(props: {
|
||||
|
||||
switch (placement) {
|
||||
case "b":
|
||||
placementStyle = {
|
||||
top: `calc(-${distanceToBottomBoundary}px + 0.5rem)`,
|
||||
left: `calc(${distanceToLeftBoundary + targetW}px - ${
|
||||
targetW * 0.02
|
||||
}px)`,
|
||||
transform: "translateX(-50%)",
|
||||
};
|
||||
placementClassName =
|
||||
"top-[calc(100%+0.5rem)] left-[50%] translate-x-[calc(-50%)]";
|
||||
arrowClassName += "top-[calc(100%+0.5rem)] translate-y-[calc(-100%)]";
|
||||
@@ -67,32 +105,51 @@ export default function Popover(props: {
|
||||
// placementClassName = '';
|
||||
// break;
|
||||
case "rb":
|
||||
placementClassName = "top-[calc(100%+0.5rem)] translate-x-[calc(-2%)]";
|
||||
arrowClassName += "top-[calc(100%+0.5rem)] translate-y-[calc(-100%)]";
|
||||
break;
|
||||
case "lt":
|
||||
placementClassName =
|
||||
"bottom-[calc(100%+0.5rem)] left-[100%] translate-x-[calc(-98%)]";
|
||||
arrowClassName += "bottom-[calc(100%+0.5rem)] translate-y-[calc(100%)]";
|
||||
break;
|
||||
case "lb":
|
||||
placementClassName =
|
||||
"top-[calc(100%+0.5rem)] left-[100%] translate-x-[calc(-98%)]";
|
||||
placementStyle = {
|
||||
top: `calc(-${distanceToBottomBoundary}px + 0.5rem)`,
|
||||
right: `calc(${distanceToRightBoundary}px - ${targetW * 0.02}px)`,
|
||||
};
|
||||
placementClassName = "top-[calc(100%+0.5rem)] right-[calc(-2%)]";
|
||||
arrowClassName += "top-[calc(100%+0.5rem)] translate-y-[calc(-100%)]";
|
||||
break;
|
||||
case "rt":
|
||||
placementClassName = "bottom-[calc(100%+0.5rem)] translate-x-[calc(-2%)]";
|
||||
placementStyle = {
|
||||
bottom: `calc(${distanceToBottomBoundary + targetH}px + 0.5rem)`,
|
||||
right: `calc(${distanceToRightBoundary}px - ${targetW * 0.02}px)`,
|
||||
};
|
||||
placementClassName = "bottom-[calc(100%+0.5rem)] right-[calc(-2%)]";
|
||||
arrowClassName += "bottom-[calc(100%+0.5rem)] translate-y-[calc(100%)]";
|
||||
break;
|
||||
case "lt":
|
||||
placementStyle = {
|
||||
bottom: `calc(${distanceToBottomBoundary + targetH}px + 0.5rem)`,
|
||||
left: `calc(${distanceToLeftBoundary}px - ${targetW * 0.02}px)`,
|
||||
};
|
||||
placementClassName = "bottom-[calc(100%+0.5rem)] left-[calc(-2%)]";
|
||||
arrowClassName += "bottom-[calc(100%+0.5rem)] translate-y-[calc(100%)]";
|
||||
break;
|
||||
case "lb":
|
||||
placementStyle = {
|
||||
top: `calc(-${distanceToBottomBoundary}px + 0.5rem)`,
|
||||
left: `calc(${distanceToLeftBoundary}px - ${targetW * 0.02}px)`,
|
||||
};
|
||||
placementClassName = "top-[calc(100%+0.5rem)] left-[calc(-2%)]";
|
||||
arrowClassName += "top-[calc(100%+0.5rem)] translate-y-[calc(-100%)]";
|
||||
break;
|
||||
case "t":
|
||||
default:
|
||||
placementStyle = {
|
||||
bottom: `calc(${distanceToBottomBoundary + targetH}px + 0.5rem)`,
|
||||
left: `calc(${distanceToLeftBoundary + targetW}px - ${
|
||||
targetW * 0.02
|
||||
}px)`,
|
||||
transform: "translateX(-50%)",
|
||||
};
|
||||
placementClassName =
|
||||
"bottom-[calc(100%+0.5rem)] left-[50%] translate-x-[calc(-50%)]";
|
||||
arrowClassName += "bottom-[calc(100%+0.5rem)] translate-y-[calc(100%)]";
|
||||
}
|
||||
|
||||
const popoverCommonClass = "absolute p-2 box-border";
|
||||
|
||||
if (noArrow) {
|
||||
arrowClassName = "hidden";
|
||||
}
|
||||
@@ -109,6 +166,12 @@ export default function Popover(props: {
|
||||
e.preventDefault();
|
||||
onShow?.(!mergedShow);
|
||||
setShow(!mergedShow);
|
||||
if (!mergedShow) {
|
||||
getRelativePosition(e.currentTarget, "");
|
||||
window.document.documentElement.style.overflow = "hidden";
|
||||
} else {
|
||||
window.document.documentElement.style.overflow = "auto";
|
||||
}
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
@@ -119,12 +182,15 @@ export default function Popover(props: {
|
||||
<ArrowIcon color={internalBgColor} />
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={`${popoverCommonClass} ${placementClassName} ${popoverClassName}`}
|
||||
style={{ zIndex: baseZIndex + 1 }}
|
||||
>
|
||||
{content}
|
||||
</div>
|
||||
{createPortal(
|
||||
<div
|
||||
className={`${popoverCommonClass} ${popoverClassName}`}
|
||||
style={{ zIndex: baseZIndex + 1, ...placementStyle }}
|
||||
>
|
||||
{content}
|
||||
</div>,
|
||||
popoverRoot,
|
||||
)}
|
||||
<div
|
||||
className=" fixed w-[100%] h-[100%] top-0 left-0 right-0 bottom-0"
|
||||
style={{ zIndex: baseZIndex }}
|
||||
|
Reference in New Issue
Block a user