mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-30 23:34:27 +00:00
On narrow screens the five section tabs (Finding Overview, Remediation, Findings for this resource, Scans, Events) did not fit, and because they had no dedicated scroll container the overflow leaked up to the resource card (whose overflow-y-auto implicitly resolves overflow-x to auto), scrolling the entire drawer body horizontally. - TabsList is now its own horizontal scroll container: triggers keep their intrinsic size (shrink-0) and stay on one line (whitespace-nowrap) so a partially-visible tab plus a thin scrollbar make it obvious more tabs are reachable by scrolling. - The resource card is pinned to overflow-x-hidden + min-w-0 so no child can force the drawer body to scroll sideways. - minimal-scrollbar now sets a 6px height so the horizontal scrollbar is actually visible on WebKit (it previously only set width).
shadcn Components
This directory contains all shadcn/ui based components for the Prowler application.
Directory Structure
Example of a custom component:
shadcn/
├── card/
│ ├── base-card/
│ │ ├── base-card.tsx
│ ├── card/
│ │ ├── card.tsx
│ └── resource-stats-card/
│ ├── resource-stats-card.tsx
│ ├── resource-stats-card.example.tsx
├── tabs/
│ ├── tabs.tsx # Base tab components
│ ├── generic-tabs.tsx # Generic reusable tabs with lazy loading
├── index.ts # Barrel exports
└── README.md
Usage
All shadcn components can be imported from @/components/shadcn:
import { Card, CardHeader, CardContent } from "@/components/shadcn";
import { ResourceStatsCard } from "@/components/shadcn";
import { GenericTabs, type TabItem } from "@/components/shadcn";
GenericTabs Component
The GenericTabs component provides a flexible, lazy-loaded tabs interface. Content is only rendered when the tab is active, improving performance.
Basic Example:
import { lazy } from "react";
import { GenericTabs, type TabItem } from "@/components/shadcn";
const OverviewContent = lazy(() => import("./OverviewContent"));
const DetailsContent = lazy(() => import("./DetailsContent"));
const tabs: TabItem[] = [
{
id: "overview",
label: "Overview",
content: OverviewContent,
},
{
id: "details",
label: "Details",
content: DetailsContent,
},
];
export function MyComponent() {
return <GenericTabs tabs={tabs} defaultTabId="overview" />;
}
With Icons and Props:
import { Eye, Settings } from "lucide-react";
import { GenericTabs, type TabItem } from "@/components/shadcn";
const tabs: TabItem[] = [
{
id: "view",
label: "View",
icon: <Eye size={16} />,
content: ViewContent,
contentProps: { data: myData },
},
{
id: "config",
label: "Config",
icon: <Settings size={16} />,
content: ConfigContent,
},
];
export function MyComponent() {
return (
<GenericTabs
tabs={tabs}
defaultTabId="view"
onTabChange={(tabId) => console.log("Active tab:", tabId)}
/>
);
}
Props:
tabs- Array ofTabItemobjectsdefaultTabId- Initial active tab ID (defaults to first tab)className- Wrapper classlistClassName- TabsList classtriggerClassName- TabsTrigger classcontentClassName- TabsContent classonTabChange- Callback fired when tab changes
Adding New shadcn Components
When adding new shadcn components using the CLI, pin the reviewed CLI version instead of using @latest:
pnpm dlx shadcn@4.7.0 add [component-name]
The component will be automatically added to this directory due to the configuration in components.json:
{
"aliases": {
"ui": "@/components/shadcn"
}
}
Component Guidelines
- shadcn base components - Use as-is from shadcn/ui (e.g.,
card.tsx) - Custom components built on shadcn - Create in subdirectories (e.g.,
resource-stats-card/) - CVA variants - Use Class Variance Authority for type-safe variants
- Theme support - Include
dark:classes for dark/light theme compatibility - TypeScript - Always export types and use proper typing