From e0ffda82e482c583f002eef869d9dd276609ee32 Mon Sep 17 00:00:00 2001 From: Shivam Gupta <9.shivamgupta.6@gmail.com> Date: Sat, 8 Aug 2026 23:35:30 +0530 Subject: [PATCH] fix: extend scroll-fade treatment to provider tabs and data tables Apply the same hidden-scrollbar + edge-fade fix to two more overflow spots found by a repo-wide scan: - Application/Compose "General" tab source-provider picker (GitHub/GitLab/Bitbucket/Gitea/Git/Raw/Docker/Drop) had the same bare overflow-auto tab row as the service detail pages. - The shared ui/table.tsx container wraps nearly every data table in the app with overflow-x-auto and no scroll affordance at all. Refactor ScrollFadeContainer to expose the underlying scroll-fade logic as a reusable useScrollFade hook + ScrollFadeEdges overlay, since Table needs the fade attached to its own existing container div rather than an extra wrapping div. ScrollFadeContainer's own behavior and API are unchanged. --- .../application/general/generic/show.tsx | 5 +- .../compose/general/generic/show.tsx | 5 +- .../shared/scroll-fade-container.tsx | 65 +++++++++++++------ apps/dokploy/components/ui/table.tsx | 14 +++- 4 files changed, 64 insertions(+), 25 deletions(-) diff --git a/apps/dokploy/components/dashboard/application/general/generic/show.tsx b/apps/dokploy/components/dashboard/application/general/generic/show.tsx index 6cf4022c1..5f1940b0b 100644 --- a/apps/dokploy/components/dashboard/application/general/generic/show.tsx +++ b/apps/dokploy/components/dashboard/application/general/generic/show.tsx @@ -14,6 +14,7 @@ import { GitIcon, GitlabIcon, } from "@/components/icons/data-tools-icons"; +import { ScrollFadeContainer } from "@/components/shared/scroll-fade-container"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { api } from "@/utils/api"; @@ -153,7 +154,7 @@ export const ShowProviderForm = ({ applicationId }: Props) => { setSab(e as TabState); }} > -
+ { Drop -
+ {githubProviders && githubProviders?.length > 0 ? ( diff --git a/apps/dokploy/components/dashboard/compose/general/generic/show.tsx b/apps/dokploy/components/dashboard/compose/general/generic/show.tsx index c2b6f4d0e..b47c9d359 100644 --- a/apps/dokploy/components/dashboard/compose/general/generic/show.tsx +++ b/apps/dokploy/components/dashboard/compose/general/generic/show.tsx @@ -10,6 +10,7 @@ import { GitIcon, GitlabIcon, } from "@/components/icons/data-tools-icons"; +import { ScrollFadeContainer } from "@/components/shared/scroll-fade-container"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { api } from "@/utils/api"; @@ -142,7 +143,7 @@ export const ShowProviderFormCompose = ({ composeId }: Props) => { setSab(e as TabState); }} > -
+ { Raw -
+ {githubProviders && githubProviders?.length > 0 ? ( diff --git a/apps/dokploy/components/shared/scroll-fade-container.tsx b/apps/dokploy/components/shared/scroll-fade-container.tsx index 16112b0bd..885ec8bc7 100644 --- a/apps/dokploy/components/shared/scroll-fade-container.tsx +++ b/apps/dokploy/components/shared/scroll-fade-container.tsx @@ -1,13 +1,10 @@ import { cn } from "@/lib/utils"; -import { useEffect, useRef, useState } from "react"; +import { type RefObject, useEffect, useRef, useState } from "react"; -interface Props { - children: React.ReactNode; - className?: string; -} - -export const ScrollFadeContainer = ({ children, className }: Props) => { - const ref = useRef(null); +export const useScrollFade = ( + deps: unknown[] = [], +): [RefObject, boolean, boolean] => { + const ref = useRef(null); const [canScrollLeft, setCanScrollLeft] = useState(false); const [canScrollRight, setCanScrollRight] = useState(false); @@ -32,7 +29,43 @@ export const ScrollFadeContainer = ({ children, className }: Props) => { el.removeEventListener("scroll", updateFades); resizeObserver.disconnect(); }; - }, [children]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, deps); + + return [ref, canScrollLeft, canScrollRight]; +}; + +export const ScrollFadeEdges = ({ + canScrollLeft, + canScrollRight, +}: { + canScrollLeft: boolean; + canScrollRight: boolean; +}) => ( + <> +
+
+ +); + +interface Props { + children: React.ReactNode; + className?: string; +} + +export const ScrollFadeContainer = ({ children, className }: Props) => { + const [ref, canScrollLeft, canScrollRight] = + useScrollFade([children]); return (
@@ -42,17 +75,9 @@ export const ScrollFadeContainer = ({ children, className }: Props) => { > {children}
-
-
); diff --git a/apps/dokploy/components/ui/table.tsx b/apps/dokploy/components/ui/table.tsx index da95d3590..043d5e222 100644 --- a/apps/dokploy/components/ui/table.tsx +++ b/apps/dokploy/components/ui/table.tsx @@ -2,19 +2,31 @@ import type * as React from "react"; +import { + ScrollFadeEdges, + useScrollFade, +} from "@/components/shared/scroll-fade-container"; import { cn } from "@/lib/utils"; function Table({ className, ...props }: React.ComponentProps<"table">) { + const [ref, canScrollLeft, canScrollRight] = + useScrollFade([props.children]); + return (
+ ); }