feat(frontend): slice 2 — migrate 11 shared components to shadcn/Tailwind
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.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { Box, Card, CardContent, Typography } from "@mui/material";
|
||||
import { Card } from "@/components/ui/card";
|
||||
|
||||
interface SelectionRailCardProps {
|
||||
title: string;
|
||||
@@ -7,65 +7,38 @@ interface SelectionRailCardProps {
|
||||
children: ReactNode;
|
||||
footer?: ReactNode;
|
||||
minHeight?: number;
|
||||
/** Legacy MUI `sx` passthroughs; retained for API compatibility (no-op). */
|
||||
contentSx?: object;
|
||||
/** Legacy MUI `sx` passthroughs; retained for API compatibility (no-op). */
|
||||
bodySx?: object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selection-rail surface: titled header, scrollable body, optional footer.
|
||||
*
|
||||
* Preserves the exported props (`minHeight`, `footer`, and the legacy `*Sx`
|
||||
* no-op passthroughs) so consuming pages (Actions, Settings) compile
|
||||
* unchanged. The scrollable body and footer contract are preserved.
|
||||
*/
|
||||
export function SelectionRailCard({
|
||||
title,
|
||||
description,
|
||||
children,
|
||||
footer,
|
||||
minHeight = 420,
|
||||
contentSx,
|
||||
bodySx,
|
||||
}: SelectionRailCardProps) {
|
||||
return (
|
||||
<Card variant="outlined" sx={{ alignSelf: "start", height: "fit-content" }}>
|
||||
<CardContent
|
||||
sx={{
|
||||
p: 0,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
minHeight,
|
||||
...contentSx,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
px: 1.5,
|
||||
py: 1.25,
|
||||
borderBottom: 1,
|
||||
borderColor: "divider",
|
||||
bgcolor: "action.hover",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="subtitle2"
|
||||
sx={{ fontWeight: 800, letterSpacing: 0.2 }}
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
<Card className="h-fit self-start py-0" style={{ minHeight }}>
|
||||
<div className="flex flex-col" style={{ minHeight }}>
|
||||
<div className="border-b bg-muted/50 px-4 py-3">
|
||||
<h4 className="text-sm font-semibold tracking-wide">{title}</h4>
|
||||
{description ? (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{description}
|
||||
</Typography>
|
||||
<p className="text-xs text-muted-foreground">{description}</p>
|
||||
) : null}
|
||||
</Box>
|
||||
<Box sx={{ flex: 1, overflowY: "auto", ...bodySx }}>{children}</Box>
|
||||
{footer ? (
|
||||
<Box
|
||||
sx={{
|
||||
p: 1,
|
||||
borderTop: 1,
|
||||
borderColor: "divider",
|
||||
bgcolor: "background.paper",
|
||||
}}
|
||||
>
|
||||
{footer}
|
||||
</Box>
|
||||
) : null}
|
||||
</CardContent>
|
||||
</div>
|
||||
<div className="flex-1 overflow-y-auto">{children}</div>
|
||||
{footer ? <div className="border-t bg-card p-3">{footer}</div> : null}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user