109e74db41
Web UI rework. Shared-components slice (drift prevention): - Migrate SectionCard, SelectionRailCard, TabbedCard, MetricCard, DiskSpaceCard, HoverEditButton, DialogFooter, ConfirmDialog, LibraryOverview, NowPlaying, SessionActivityPanel off @mui - HoverEditButton: MUI IconButton + EditOutlined -> Button + lucide Pencil - Status mapping uses the success Badge variant (chart-2) for healthy - Exported APIs preserved so consuming pages still compile (no page edits) - 11 behavioral Vitest component tests added Gate: build + lint + test green.
40 lines
1.1 KiB
TypeScript
40 lines
1.1 KiB
TypeScript
import type { ReactElement, ReactNode } from "react";
|
|
import { Card } from "@/components/ui/card";
|
|
import { Tabs, TabsList } from "@/components/ui/tabs";
|
|
|
|
interface TabbedCardProps {
|
|
value: string;
|
|
onChange: (value: string) => void;
|
|
tabs: ReactElement[];
|
|
children: ReactNode;
|
|
/** Legacy MUI `sx` passthroughs; retained for API compatibility (no-op). */
|
|
contentSx?: object;
|
|
/** Legacy MUI `sx` passthroughs; retained for API compatibility (no-op). */
|
|
tabsSx?: object;
|
|
}
|
|
|
|
/**
|
|
* Card surface with a line-style tab bar on top and a content area below.
|
|
*
|
|
* `value`/`onChange` stay string-typed (controlled) and the `tabs` prop stays
|
|
* `ReactElement[]`, so consuming pages compile unchanged. The page owns the
|
|
* rendered content from `children` keyed off `value`, exactly as before.
|
|
*/
|
|
export function TabbedCard({
|
|
value,
|
|
onChange,
|
|
tabs,
|
|
children,
|
|
}: TabbedCardProps) {
|
|
return (
|
|
<Card className="gap-0 py-0">
|
|
<Tabs value={value} onValueChange={(next) => onChange(String(next))}>
|
|
<div className="border-b px-2">
|
|
<TabsList variant="line">{tabs}</TabsList>
|
|
</div>
|
|
<div className="p-4">{children}</div>
|
|
</Tabs>
|
|
</Card>
|
|
);
|
|
}
|