Tailwind CSS v4 & Shadcn UI in Dokploy#
Dokploy's frontend migrated from Tailwind CSS v3 to v4, alongside a shadcn component library update, in PR #4706 (merged ~June 30, 2026). The upgrade touched 160+ files and introduced a new build pipeline, CSS configuration format, and color system — and also introduced several CSS regressions, each requiring follow-up fixes.
Configuration Changes (v3 → v4)#
The key structural shifts introduced by the upgrade :
- PostCSS:
tailwindcss+autoprefixerreplaced by@tailwindcss/postcss. - Entry point (
globals.css): The three@tailwinddirectives (base,components,utilities) are replaced by@importstatements —@import "tailwindcss",@import "tw-animate-css", and@import "shadcn/tailwind.css". - Plugin declarations: Plugins (
tailwindcss-animate,@tailwindcss/typography,fancy-ansi) are now declared with@plugininside CSS instead of in a JS config file. @themeblock: Design tokens (fonts, breakpoints, colors, animations) live in a@themeblock inglobals.css. Thetailwind.config.tsfile was removed entirely.- Color system: Colors migrated to the
oklchcolor space with explicit CSS variables and an@theme inlineblock for shadcn compatibility . - Custom utilities:
.no-scrollbarand.custom-logs-scrollbarare declared using@utilitywithin@layer utilities. - Contextual variants: Tailwind v4's
in-*variants (e.g.,in-data-[slot=dialog-content]) replace brittle parent-selector CSS patterns used in v3.
CSS Regressions & Fixes#
Four regressions followed the v4 upgrade merge. Each is documented below with the root cause and fix.
Sidebar Vertical Scroll (v0.29.10)#
Regression: The SidebarContent component received group-data-[collapsible=icon]:overflow-hidden during the upgrade, which disabled all overflow — including vertical scroll — when the sidebar is in its collapsed (icon) state. Users with many sidebar items could not reach lower menu entries .
Fix (PR #4755): Changed to overflow-y-auto overflow-x-hidden, restoring vertical scrolling while preventing horizontal overflow. This also eliminated a pre-existing horizontal scroll bug from v0.29.8 .
Command Palette Crash (Issue #4756)#
Regression: The CommandDialog component was restructured incorrectly — <DialogHeader> was placed outside <DialogContent>, breaking Radix UI's portal rendering, and the root <Command> wrapper (the cmdk context provider) was accidentally removed. Opening the search palette (⌘J / Ctrl+J) triggered a TypeError and a 400 error page.
Fix (PR #4761): Moved <DialogHeader> back inside <DialogContent>, restored the root <Command> wrapper, and migrated dialog-specific styles from brittle parent-injected selectors to Tailwind v4's in-data-[slot=dialog-content] contextual variants. See the current CommandDialog and CommandList implementations for the corrected structure; CommandList now uses no-scrollbar max-h-[300px] overflow-x-hidden overflow-y-auto .
Badge Pointer Events (Issue #4780)#
Regression: The updated Badge component included [&>svg]:pointer-events-none, disabling pointer events on all child SVG elements. This broke interactive SVG icons such as the "×" delete button in watch-path badges, making watch paths undeletable across all Git provider forms (GitHub, GitLab, Gitea, Bitbucket) for both Applications and Compose services.
Fix approach (PR #4827): Scope the selector to non-interactive icons only — [&>svg:not(.cursor-pointer)]:pointer-events-none — so that SVGs marked .cursor-pointer remain clickable. See badge.tsx for the component definition.
Other Regressions#
| Issue | Root Cause | Fix |
|---|---|---|
| Requests chart invisible | New ChartContainer already wraps ResponsiveContainer internally; old code double-wrapped it, collapsing chart to −1px size | Remove outer ResponsiveContainer; use ChartContainer className="aspect-auto h-[200px] w-full" directly |
| Rebuild database dialog crash | AlertDialogAction now wraps children in <Button asChild> internally; passing a nested <Button> caused a Radix Slot arity error | Replace asChild + nested <Button> with plain AlertDialogAction using variant="destructive" |
Key Files Reference#
| File | Purpose |
|---|---|
apps/dokploy/styles/globals.css | Tailwind v4 entry point: @import, @plugin, @theme, color variables |
apps/dokploy/components/ui/sidebar.tsx | Sidebar layout; SidebarContent at lines 365–377 controls scroll overflow |
apps/dokploy/components/ui/command.tsx | Command palette; CommandDialog (lines 32–62) and CommandList (lines 87–101) |
apps/dokploy/components/ui/badge.tsx | Badge variants; [&>svg]:pointer-events-none at line 8 |
apps/dokploy/hooks/use-mobile.ts | New hook added during upgrade for responsive sidebar behavior |
packages/server/src/emails/tailwind-config.ts | Server-side Tailwind config for email rendering, added during upgrade |