update: better picker component

This commit is contained in:
alikia2x 2024-07-13 20:21:56 +08:00
parent 8d39e2833c
commit f4b9257dc9
3 changed files with 65 additions and 35 deletions

View File

@ -27,10 +27,27 @@ export default function Picker(props: PickerProps) {
return;
}
const buttonRect = buttonRef.current.getBoundingClientRect();
const listWidth = itemListRef.current.getBoundingClientRect().width;
const listRect = itemListRef.current.getBoundingClientRect();
// Align to center
itemListRef.current.style.left = buttonRect.x + buttonRect.width / 2 - listWidth / 2 + "px";
itemListRef.current.style.top = buttonRect.y + buttonRect.height + 16 + "px";
itemListRef.current.style.left =
Math.max(
Math.min(
buttonRect.x + buttonRect.width / 2 - listRect.width / 2,
window.screen.width - listRect.width - 16
),
0
) + "px";
if (window.screen.height - buttonRect.top < 192) {
itemListRef.current.style.transformOrigin = "bottom center";
itemListRef.current.style.top = buttonRect.top - listRect.height - 16 + "px";
} else {
itemListRef.current.style.top = buttonRect.y + buttonRect.height + 16 + "px";
}
if (listRect.top + listRect.height > window.screen.height - 16) {
itemListRef.current.style.height = window.screen.height - listRect.top - 12 + "px";
} else {
itemListRef.current.style.height = "fit-content";
}
};
useEffect(() => {
@ -50,8 +67,8 @@ export default function Picker(props: PickerProps) {
function toggleDisplay(targetState?: boolean) {
function hideList() {
if (itemListRef.current) {
itemListRef.current.style.transitionDuration = "200ms";
itemListRef.current.style.opacity = "0%";
itemListRef.current.style.transform = "scaleX(.85) scaleY(.85)";
}
setTimeout(() => {
setDisplayList(false);
@ -60,10 +77,20 @@ export default function Picker(props: PickerProps) {
function showList() {
setDisplayList(true);
setTimeout(() => {
if (!itemListRef.current || !buttonRef.current) {
return;
}
updatePosition();
if (itemListRef.current) {
itemListRef.current.style.opacity = "100%";
itemListRef.current.style.transform = "scaleX(1) scaleY(1)";
if (window.screen.height - buttonRef.current.getBoundingClientRect().top < 128) {
itemListRef.current.style.transformOrigin = "bottom center";
}
itemListRef.current.style.transitionDuration = "100ms";
itemListRef.current.style.opacity = "100%";
updatePosition();
const listRect = itemListRef.current.getBoundingClientRect();
if (listRect.top < 8) {
itemListRef.current.style.height = window.screen.height - 8 + "px";
itemListRef.current.style.top = "8px";
}
}, 20);
}
@ -112,34 +139,37 @@ interface PickerListProps {
}
const PickerList = React.forwardRef<HTMLDivElement, PickerListProps>((props, ref) => {
const { selected, selectionOnChange, selectionItems } = props;
const { selected, selectionOnChange, selectionItems, toggleDisplay } = props;
return createPortal(
<div
ref={ref}
className="absolute w-fit text-black dark:text-white opacity-0 duration-200
bg-zinc-50 shadow-lg border-1 border-zinc-200 dark:border-zinc-600 dark:bg-zinc-700 px-2 py-2 rounded-xl text-align-left scale-[.85]"
style={{ transformOrigin: "top center" }}
>
{Object.keys(selectionItems).map((key: string, index) => {
return (
<div
key={index}
className="relative py-2 w-full min-w-32 pl-2 cursor-pointer rounded-lg
hover:bg-zinc-200 dark:hover:bg-zinc-600 flex justify-between items-center"
onClick={() => {
selectionOnChange(key);
props.toggleDisplay();
}}
>
<span>{selectionItems[key]}</span>
<div className="relative w-16"></div>
{key === selected && (
<Icon className="relative right-2" icon="carbon:checkmark" />
)}
</div>
);
})}
<div className="absolute w-screen h-screen" onClick={()=>{toggleDisplay(false)}}>
<div
ref={ref}
className="overflow-y-auto fixed w-fit text-black dark:text-white opacity-0 duration-200
bg-zinc-50 shadow-lg border-1 border-zinc-200 dark:border-zinc-600
dark:bg-zinc-800 px-2 py-2 rounded-xl text-align-left"
style={{ transformOrigin: "top center" }}
>
{Object.keys(selectionItems).map((key: string, index) => {
return (
<div
key={index}
className="relative py-2 w-full min-w-32 pl-2 cursor-pointer rounded-lg
hover:bg-zinc-200 dark:hover:bg-zinc-700 flex justify-between items-center"
onClick={() => {
selectionOnChange(key);
toggleDisplay(false);
}}
>
<span>{selectionItems[key]}</span>
<div className="relative w-16"></div>
{key === selected && (
<Icon className="relative right-2" icon="carbon:checkmark" />
)}
</div>
);
})}
</div>
</div>,
document.body
);

View File

@ -1,7 +1,7 @@
{
"name": "sparkhome",
"private": false,
"version": "5.2.2",
"version": "5.2.3",
"type": "module",
"scripts": {
"dev": "bun server.ts",

View File

@ -12,7 +12,7 @@ export default function Homepage() {
const setBgFocus = useSetAtom(bgFocusAtom);
return (
<div className="h-full fixed overflow-hidden w-full bg-black">
<div className="h-screen fixed overflow-hidden w-screen bg-black">
<Background />
<EngineSelector
className="absolute top-20 lg:top-44 short:top-0 translate-x-[-50%] translate-y-[-0.2rem]