sidebar switcher now always stays on screen

This commit is contained in:
corgifist 2025-07-27 18:39:15 +03:00
parent f881b2d7bf
commit 6ad064c9c1
7 changed files with 104 additions and 41 deletions

View File

@ -48,7 +48,7 @@ export default async function RootLayout({
<ThemeProvider>
<SidebarProvider>
<Dashboard/>
<main className="w-full">
<main className="w-full relative">
<PersistenceProvider>
{children}
</PersistenceProvider>

View File

@ -30,6 +30,8 @@ import { Tooltip, TooltipContent } from "@/components/ui/tooltip";
import { TooltipTrigger } from "@radix-ui/react-tooltip";
import { Sheet, SheetClose, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ui/sheet";
import { Separator } from "@/components/ui/separator";
import StaticSidebarTrigger from "@/components/static-sidebar-trigger";
import SidebarTriggerAdjustable from "@/components/sidebar-trigger-adjustable";
type SortingType = "byCreationDate"
| "byEditDate"
@ -488,11 +490,12 @@ export default function Home(): ReactNode {
<SelectContext.Provider value={context}>
<div className="p-5">
<div className="flex flex-row items-center gap-2">
<SidebarTrigger size="lg" />
<StaticSidebarTrigger />
<h2 className="font-bold break-keep text-xl sm:text-2xl md:text-3xl lg:text-4xl leading-none">Project Library</h2>
{projects && <Label className="text-muted-foreground text-sm">(Found {projects.length} projects)</Label>}
</div>
<div className="flex flex-col sticky top-safe bg-background gap-2 mt-3 pb-2 pt-2 p-5 w-[100% + 5 * var(--spacing)] z-10 -mx-5">
<div className="flex flex-col sticky top-safe bg-background gap-2 mt-2 pb-2 pt-2 p-5 w-[100% + 5 * var(--spacing)] z-10 -mx-5">
<SidebarTriggerAdjustable>
<div className={cn("flex flex-row gap-2 items-center w-full", !isMobile && "justify-between")}>
<Dialog>
<DialogTrigger asChild>
@ -526,6 +529,7 @@ export default function Home(): ReactNode {
</Dialog>
<Search placeholder="Search Projects" value={search} onChange={(e) => setSearch(e.target.value)} className={isMobile ? "w-full" : "w-60"} />
</div>
</SidebarTriggerAdjustable>
<div className="flex flex-row justify-between items-center w-full">
<div className="flex flex-row items-center gap-1">
<DropdownMenu>

View File

@ -6,6 +6,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip
import { InfoIcon } from "lucide-react";
import { ReactNode, useEffect, useState } from "react";
import { usePersistenceContext } from "../persistence-provider";
import StaticSidebarTrigger from "@/components/static-sidebar-trigger";
function PersistentStorageControl({
status
@ -29,7 +30,7 @@ export default function Settings(): ReactNode {
return (
<div className="p-5 w-full">
<div className="flex flex-row items-center gap-2">
<SidebarTrigger/>
<StaticSidebarTrigger/>
<h2 className="font-bold break-keep text-xl sm:text-2xl md:text-3xl lg:text-4xl leading-none">Settings</h2>
</div>
<div className="flex flex-col gap-1 md:lg:gap-2 mt-2 md:mt-4 lg:mt-5">

View File

@ -0,0 +1,37 @@
"use client";
import { useIsMobile } from "@/hooks/use-mobile";
import { cn } from "@/lib/utils";
import { ComponentProps, useEffect, useState } from "react";
const easeSlide = (x: number) => (
1 - Math.pow(1 - x, 2)
);
export const SidebarTriggerAdjustable = (props: ComponentProps<"div">) => {
const [scrollY, setScrollY] = useState(0);
const [windowHeight, setWindowHeight] = useState(1);
const isMobile = useIsMobile();
useEffect(() => {
const handleScroll = () => setScrollY(window.scrollY);
const handleResize = () => setWindowHeight(window.innerHeight);
setWindowHeight(window.innerHeight);
window.addEventListener('scroll', handleScroll);
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('scroll', handleScroll);
window.removeEventListener('resize', handleResize);
};
}, []);
let slideAmount = Math.max(0, Math.min(1, scrollY / (windowHeight / 20)));
slideAmount = easeSlide(slideAmount);
return <div {...props} style={{
paddingLeft: `calc(var(--spacing) * 12 * ${slideAmount})`,
paddingTop: `calc(var(--spacing) * ${isMobile ? 1 : 3} * ${slideAmount})`
}}></div>;
}

View File

@ -0,0 +1,3 @@
import { SidebarTriggerAdjustable } from "./SidebarTriggerAdjustable";
export default SidebarTriggerAdjustable;

View File

@ -0,0 +1,15 @@
"use client";
import { useEffect, useState } from "react";
import { SidebarTrigger, useSidebar } from "../ui/sidebar";
export const StaticSidebarTrigger = () => {
return (
<>
<div className="ml-10"/>
<div className="absolute top-0 left-0 pl-6 pt-4 md:p-6 overscroll-auto">
<SidebarTrigger className={`fixed mr-2 z-40 transition-colors will-change-[transform, scroll-position]`} size="lg" tabIndex={0}/>
</div>
</>
);
};

View File

@ -0,0 +1,3 @@
import { StaticSidebarTrigger } from "./StaticSidebarTrigger";
export default StaticSidebarTrigger;