improved mobile pwa user experience

This commit is contained in:
daniel31x13 2024-01-14 11:16:42 -05:00
parent d4f59d7f32
commit 4e47a6bffb
4 changed files with 148 additions and 100 deletions

View File

@ -0,0 +1,113 @@
import { dropdownTriggerer } from "@/lib/client/utils";
import React from "react";
import { useEffect, useState } from "react";
import NewLinkModal from "./ModalContent/NewLinkModal";
import NewCollectionModal from "./ModalContent/NewCollectionModal";
import UploadFileModal from "./ModalContent/UploadFileModal";
import MobileNavigationButton from "./MobileNavigationButton";
type Props = {};
export default function MobileNavigation({}: Props) {
const [hasScrolled, setHasScrolled] = useState(false);
const [newLinkModal, setNewLinkModal] = useState(false);
const [newCollectionModal, setNewCollectionModal] = useState(false);
const [uploadFileModal, setUploadFileModal] = useState(false);
useEffect(() => {
const handleScroll = () => {
if (window.scrollY > 0) {
setHasScrolled(true);
} else {
setHasScrolled(false);
}
};
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<>
<div
className={`fixed bottom-0 left-0 right-0 z-30 duration-200 sm:hidden ${
hasScrolled ? "opacity-80" : ""
}`}
>
<div className="dropdown dropdown-end dropdown-top absolute -top-20 right-5">
<div
tabIndex={0}
role="button"
onMouseDown={dropdownTriggerer}
className={`flex items-center btn btn-accent dark:border-violet-400 text-white btn-circle btn-lg px-2 relative`}
>
<span>
<i className="bi-plus text-5xl pointer-events-none"></i>
</span>
</div>
<ul className="dropdown-content z-[1] menu shadow bg-base-200 border border-neutral-content rounded-box w-40 mb-1">
<li>
<div
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
setNewLinkModal(true);
}}
tabIndex={0}
role="button"
>
New Link
</div>
</li>
{/* <li>
<div
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
setUploadFileModal(true);
}}
tabIndex={0}
role="button"
>
Upload File
</div>
</li> */}
<li>
<div
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
setNewCollectionModal(true);
}}
tabIndex={0}
role="button"
>
New Collection
</div>
</li>
</ul>
</div>
<div className="w-full flex bg-base-100 pb-5 border-solid border-t-neutral-content border-t">
<MobileNavigationButton href={`/dashboard`} icon={"bi-house"} />
<MobileNavigationButton
href={`/links/pinned`}
icon={"bi-pin-angle"}
/>
<MobileNavigationButton href={`/links`} icon={"bi-link-45deg"} />
<MobileNavigationButton href={`/collections`} icon={"bi-folder"} />
<MobileNavigationButton href={`/tags`} icon={"bi-hash"} />
</div>
</div>
{newLinkModal ? (
<NewLinkModal onClose={() => setNewLinkModal(false)} />
) : undefined}
{newCollectionModal ? (
<NewCollectionModal onClose={() => setNewCollectionModal(false)} />
) : undefined}
{uploadFileModal ? (
<UploadFileModal onClose={() => setUploadFileModal(false)} />
) : undefined}
</>
);
}

View File

@ -0,0 +1,32 @@
import Link from "next/link";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
export default function MobileNavigationButton({
href,
icon,
}: {
href: string;
icon: string;
}) {
const router = useRouter();
const [active, setActive] = useState(false);
useEffect(() => {
setActive(href === router.asPath);
}, [router]);
return (
<Link href={href} className="w-full">
<div
className={`py-2 cursor-pointer gap-2 w-full rounded-full capitalize flex items-center justify-center`}
>
<i
className={`${icon} text-primary text-3xl drop-shadow duration-200 rounded-full w-14 h-14 text-center pt-[0.65rem] ${
active || false ? "bg-primary/20" : ""
}`}
></i>
</div>
</Link>
);
}

View File

@ -14,7 +14,7 @@ import NewCollectionModal from "./ModalContent/NewCollectionModal";
import Link from "next/link";
import UploadFileModal from "./ModalContent/UploadFileModal";
import { dropdownTriggerer } from "@/lib/client/utils";
import NewButtonMobile from "./NewButtonMobile";
import MobileNavigation from "./MobileNavigation";
export default function Navbar() {
const { settings, updateSettings } = useLocalSettingsStore();
@ -56,7 +56,7 @@ export default function Navbar() {
setSidebar(true);
document.body.style.overflow = "hidden";
}}
className="text-neutral btn btn-square btn-sm btn-ghost lg:hidden"
className="text-neutral btn btn-square btn-sm btn-ghost lg:hidden hidden sm:inline-flex"
>
<i className="bi-list text-2xl leading-none"></i>
</div>
@ -171,7 +171,7 @@ export default function Navbar() {
</div>
</div>
<NewButtonMobile />
<MobileNavigation />
{sidebar ? (
<div className="fixed top-0 bottom-0 right-0 left-0 bg-black bg-opacity-10 backdrop-blur-sm flex items-center fade-in z-40">

View File

@ -1,97 +0,0 @@
import { dropdownTriggerer } from "@/lib/client/utils";
import React from "react";
import { useEffect, useState } from "react";
import NewLinkModal from "./ModalContent/NewLinkModal";
import NewCollectionModal from "./ModalContent/NewCollectionModal";
import UploadFileModal from "./ModalContent/UploadFileModal";
type Props = {};
export default function NewButtonMobile({}: Props) {
const [hasScrolled, setHasScrolled] = useState(false);
const [newLinkModal, setNewLinkModal] = useState(false);
const [newCollectionModal, setNewCollectionModal] = useState(false);
const [uploadFileModal, setUploadFileModal] = useState(false);
useEffect(() => {
const handleScroll = () => {
if (window.scrollY > 0) {
setHasScrolled(true);
} else {
setHasScrolled(false);
}
};
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return (
<>
<div className="dropdown dropdown-end dropdown-top sm:hidden fixed bottom-10 right-10 z-30">
<div
tabIndex={0}
role="button"
onMouseDown={dropdownTriggerer}
className={`flex items-center btn btn-accent dark:border-violet-400 text-white btn-circle btn-lg px-2 relative ${
hasScrolled ? "opacity-50" : ""
}`}
>
<span>
<i className="bi-plus text-5xl pointer-events-none"></i>
</span>
</div>
<ul className="dropdown-content z-[1] menu shadow bg-base-200 border border-neutral-content rounded-box w-40 mb-1">
<li>
<div
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
setNewLinkModal(true);
}}
tabIndex={0}
role="button"
>
New Link
</div>
</li>
{/* <li>
<div
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
setUploadFileModal(true);
}}
tabIndex={0}
role="button"
>
Upload File
</div>
</li> */}
<li>
<div
onClick={() => {
(document?.activeElement as HTMLElement)?.blur();
setNewCollectionModal(true);
}}
tabIndex={0}
role="button"
>
New Collection
</div>
</li>
</ul>
</div>
{newLinkModal ? (
<NewLinkModal onClose={() => setNewLinkModal(false)} />
) : undefined}
{newCollectionModal ? (
<NewCollectionModal onClose={() => setNewCollectionModal(false)} />
) : undefined}
{uploadFileModal ? (
<UploadFileModal onClose={() => setUploadFileModal(false)} />
) : undefined}
</>
);
}