mirror of
https://github.com/ClipFusion-org/clipfusion.git
synced 2025-08-05 18:15:08 +00:00
sidebar switcher now always stays on screen
This commit is contained in:
parent
f881b2d7bf
commit
6ad064c9c1
@ -48,7 +48,7 @@ export default async function RootLayout({
|
||||
<ThemeProvider>
|
||||
<SidebarProvider>
|
||||
<Dashboard/>
|
||||
<main className="w-full">
|
||||
<main className="w-full relative">
|
||||
<PersistenceProvider>
|
||||
{children}
|
||||
</PersistenceProvider>
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
@ -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>;
|
||||
}
|
3
src/components/sidebar-trigger-adjustable/index.ts
Normal file
3
src/components/sidebar-trigger-adjustable/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { SidebarTriggerAdjustable } from "./SidebarTriggerAdjustable";
|
||||
|
||||
export default SidebarTriggerAdjustable;
|
@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
3
src/components/static-sidebar-trigger/index.ts
Normal file
3
src/components/static-sidebar-trigger/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { StaticSidebarTrigger } from "./StaticSidebarTrigger";
|
||||
|
||||
export default StaticSidebarTrigger;
|
Loading…
Reference in New Issue
Block a user