Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions apps/dokploy/components/ui/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ import * as React from "react";

import { cn } from "@/lib/utils";

/** Outer row for service detail pages (application, compose, DB services): no horizontal scroll; pairs with {@link serviceDetailTabsListClassName}. */
export const serviceDetailTabsBarClassName =
"flex flex-row items-center w-full gap-4";
Comment on lines +6 to +8
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Page-specific constants in a generic component

serviceDetailTabsBarClassName and serviceDetailTabsListClassName are semantically tied to service detail pages, not to the tabs component itself. Exporting layout presets from tabs.tsx couples the generic UI primitive to a specific page pattern. Consider moving them to a shared styles/constants file (e.g. lib/service-detail-styles.ts) or defining them inline in each page — the JSDoc comments already acknowledge they target a specific set of pages.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!


/** Tabs wrap on narrow viewports instead of forcing a single scrollable row. */
export const serviceDetailTabsListClassName =
"flex flex-wrap h-auto min-h-10 gap-x-8 gap-y-2 max-md:gap-x-4 max-md:gap-y-2 justify-start";
Comment on lines +11 to +12
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Redundant responsive class

max-md:gap-y-2 is the same value as the already-applied gap-y-2 (the base class covers all breakpoints in Tailwind's mobile-first system), so the responsive modifier does nothing. Only max-md:gap-x-4 is meaningful here.

Suggested change
export const serviceDetailTabsListClassName =
"flex flex-wrap h-auto min-h-10 gap-x-8 gap-y-2 max-md:gap-x-4 max-md:gap-y-2 justify-start";
"flex flex-wrap h-auto min-h-10 gap-x-8 gap-y-2 max-md:gap-x-4 justify-start";


const Tabs = TabsPrimitive.Root;

const TabsList = React.forwardRef<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,14 @@ import {
CardTitle,
} from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
serviceDetailTabsBarClassName,
serviceDetailTabsListClassName,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/tabs";
import {
Tooltip,
TooltipContent,
Expand Down Expand Up @@ -229,8 +236,8 @@ const Service = (
router.push(newPath);
}}
>
<div className="flex flex-row items-center justify-between w-full overflow-auto">
<TabsList className="flex gap-8 max-md:gap-4 justify-start">
<div className={serviceDetailTabsBarClassName}>
<TabsList className={serviceDetailTabsListClassName}>
<TabsTrigger value="general">General</TabsTrigger>
{permissions?.envVars.read && (
<TabsTrigger value="environment">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,14 @@ import {
CardTitle,
} from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
serviceDetailTabsBarClassName,
serviceDetailTabsListClassName,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/tabs";
import {
Tooltip,
TooltipContent,
Expand Down Expand Up @@ -217,8 +224,8 @@ const Service = (
router.push(newPath);
}}
>
<div className="flex flex-row items-center w-full overflow-auto">
<TabsList className="flex gap-8 max-md:gap-4 justify-start">
<div className={serviceDetailTabsBarClassName}>
<TabsList className={serviceDetailTabsListClassName}>
<TabsTrigger value="general">General</TabsTrigger>
{permissions?.envVars.read && (
<TabsTrigger value="environment">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,21 @@ import {
CardTitle,
} from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
serviceDetailTabsBarClassName,
serviceDetailTabsListClassName,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/tabs";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { cn } from "@/lib/utils";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";

Expand Down Expand Up @@ -174,17 +180,8 @@ const Libsql = (
router.push(newPath, undefined, { shallow: true });
}}
>
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
<TabsList
className={cn(
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
isCloud && data?.serverId
? "md:grid-cols-6"
: data?.serverId
? "md:grid-cols-5"
: "md:grid-cols-6",
)}
>
<div className={serviceDetailTabsBarClassName}>
<TabsList className={serviceDetailTabsListClassName}>
<TabsTrigger value="general">General</TabsTrigger>
<TabsTrigger value="environment">Environment</TabsTrigger>
<TabsTrigger value="logs">Logs</TabsTrigger>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,21 @@ import {
CardTitle,
} from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
serviceDetailTabsBarClassName,
serviceDetailTabsListClassName,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/tabs";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { cn } from "@/lib/utils";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";
import { useWhitelabeling } from "@/utils/hooks/use-whitelabeling";
Expand Down Expand Up @@ -188,17 +194,8 @@ const Mariadb = (
router.push(newPath, undefined, { shallow: true });
}}
>
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
<TabsList
className={cn(
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
isCloud && data?.serverId
? "md:grid-cols-6"
: data?.serverId
? "md:grid-cols-5"
: "md:grid-cols-6",
)}
>
<div className={serviceDetailTabsBarClassName}>
<TabsList className={serviceDetailTabsListClassName}>
<TabsTrigger value="general">General</TabsTrigger>
{permissions?.envVars.read && (
<TabsTrigger value="environment">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,21 @@ import {
CardTitle,
} from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
serviceDetailTabsBarClassName,
serviceDetailTabsListClassName,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/tabs";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { cn } from "@/lib/utils";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";
import { useWhitelabeling } from "@/utils/hooks/use-whitelabeling";
Expand Down Expand Up @@ -188,17 +194,8 @@ const Mongo = (
router.push(newPath, undefined, { shallow: true });
}}
>
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
<TabsList
className={cn(
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
isCloud && data?.serverId
? "md:grid-cols-6"
: data?.serverId
? "md:grid-cols-5"
: "md:grid-cols-6",
)}
>
<div className={serviceDetailTabsBarClassName}>
<TabsList className={serviceDetailTabsListClassName}>
<TabsTrigger value="general">General</TabsTrigger>
{permissions?.envVars.read && (
<TabsTrigger value="environment">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,21 @@ import {
CardTitle,
} from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
serviceDetailTabsBarClassName,
serviceDetailTabsListClassName,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/tabs";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { cn } from "@/lib/utils";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";
import { useWhitelabeling } from "@/utils/hooks/use-whitelabeling";
Expand Down Expand Up @@ -188,17 +194,8 @@ const MySql = (
router.push(newPath, undefined, { shallow: true });
}}
>
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
<TabsList
className={cn(
"md:grid md:w-fit max-md:overflow-y-scroll justify-start ",
isCloud && data?.serverId
? "md:grid-cols-6"
: data?.serverId
? "md:grid-cols-5"
: "md:grid-cols-6",
)}
>
<div className={serviceDetailTabsBarClassName}>
<TabsList className={serviceDetailTabsListClassName}>
<TabsTrigger value="general">General</TabsTrigger>
{permissions?.envVars.read && (
<TabsTrigger value="environment">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,21 @@ import {
CardTitle,
} from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
serviceDetailTabsBarClassName,
serviceDetailTabsListClassName,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/tabs";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { cn } from "@/lib/utils";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";
import { useWhitelabeling } from "@/utils/hooks/use-whitelabeling";
Expand Down Expand Up @@ -189,17 +195,8 @@ const Postgresql = (
});
}}
>
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
<TabsList
className={cn(
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
isCloud && data?.serverId
? "md:grid-cols-6"
: data?.serverId
? "md:grid-cols-5"
: "md:grid-cols-6",
)}
>
<div className={serviceDetailTabsBarClassName}>
<TabsList className={serviceDetailTabsListClassName}>
<TabsTrigger value="general">General</TabsTrigger>
{permissions?.envVars.read && (
<TabsTrigger value="environment">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,21 @@ import {
CardTitle,
} from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
serviceDetailTabsBarClassName,
serviceDetailTabsListClassName,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/tabs";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { UseKeyboardNav } from "@/hooks/use-keyboard-nav";
import { cn } from "@/lib/utils";
import { appRouter } from "@/server/api/root";
import { api } from "@/utils/api";
import { useWhitelabeling } from "@/utils/hooks/use-whitelabeling";
Expand Down Expand Up @@ -187,17 +193,8 @@ const Redis = (
router.push(newPath, undefined, { shallow: true });
}}
>
<div className="flex flex-row items-center justify-between w-full gap-4 overflow-x-scroll">
<TabsList
className={cn(
"md:grid md:w-fit max-md:overflow-y-scroll justify-start",
isCloud && data?.serverId
? "md:grid-cols-5"
: data?.serverId
? "md:grid-cols-4"
: "md:grid-cols-5",
)}
>
<div className={serviceDetailTabsBarClassName}>
<TabsList className={serviceDetailTabsListClassName}>
<TabsTrigger value="general">General</TabsTrigger>
{permissions?.envVars.read && (
<TabsTrigger value="environment">
Expand Down
Loading