"use client"; import React, { useEffect, useState } from "react"; import { cn } from "~/lib/utils"; import { Card, CardContent } from "~/components/ui/card"; interface FloatingActionBarProps { /** Content to display on the left side */ leftContent?: React.ReactNode; /** Action buttons to display on the right */ children: React.ReactNode; /** Additional className for styling */ className?: string; } import { useSidebar } from "~/components/layout/sidebar-provider"; export function FloatingActionBar({ leftContent, children, className, }: FloatingActionBarProps) { const [isDocked, setIsDocked] = useState(false); const { isCollapsed } = useSidebar(); useEffect(() => { const handleScroll = () => { // Check if we're truly at the bottom of the page const scrollHeight = document.documentElement.scrollHeight; const scrollTop = document.documentElement.scrollTop; const clientHeight = document.documentElement.clientHeight; const distanceFromBottom = scrollHeight - (scrollTop + clientHeight); // Only dock when we're within 50px of the actual bottom AND there's content to scroll const hasScrollableContent = scrollHeight > clientHeight; const shouldDock = hasScrollableContent && distanceFromBottom <= 50; // If content is too small, keep it at bottom of viewport const contentTooSmall = scrollHeight <= clientHeight + 200; setIsDocked(shouldDock && !contentTooSmall); }; window.addEventListener("scroll", handleScroll, { passive: true }); handleScroll(); // Check initial state return () => window.removeEventListener("scroll", handleScroll); }, []); return (
{/* Content container - full width when floating, content width when docked */}
{/* Left content */} {leftContent && (
{leftContent}
)} {/* Right actions */}
{children}
); }