Files
Hugo P.Brito e691176612 fix(ui): contain finding drawer horizontal scroll to the tab bar on mobile
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).
2026-05-18 13:57:26 +01:00
..
2025-11-03 09:17:37 +01:00

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 of TabItem objects
  • defaultTabId - Initial active tab ID (defaults to first tab)
  • className - Wrapper class
  • listClassName - TabsList class
  • triggerClassName - TabsTrigger class
  • contentClassName - TabsContent class
  • onTabChange - 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

  1. shadcn base components - Use as-is from shadcn/ui (e.g., card.tsx)
  2. Custom components built on shadcn - Create in subdirectories (e.g., resource-stats-card/)
  3. CVA variants - Use Class Variance Authority for type-safe variants
  4. Theme support - Include dark: classes for dark/light theme compatibility
  5. TypeScript - Always export types and use proper typing

Resources