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:
Developer
2026-06-17 12:33:47 +00:00
parent dd778d8850
commit 109e74db41
23 changed files with 830 additions and 469 deletions
+15 -35
View File
@@ -1,4 +1,4 @@
import { Card, CardContent, Typography } from "@mui/material";
import { Card, CardContent } from "@/components/ui/card";
interface Props {
label: string;
@@ -6,44 +6,24 @@ interface Props {
subtext?: string;
}
/**
* Compact metric tile: label / value / optional subtext on the comfortable
* density ramp (label `text-sm`, value `text-lg font-semibold`, subtext
* `text-xs text-muted-foreground`). Same exported props as the MUI version.
*/
export function MetricCard({ label, value, subtext }: Props) {
return (
<Card variant="outlined" sx={{ height: "100%" }}>
<CardContent
sx={{
p: { xs: 1.5, sm: 2 },
display: "flex",
flexDirection: "column",
gap: 0.5,
height: "100%",
}}
>
<Typography
variant="caption"
color="text.secondary"
sx={{ textTransform: "uppercase", lineHeight: 1.2 }}
>
<Card className="h-full">
<CardContent className="flex h-full flex-col gap-1.5">
<span className="text-sm uppercase leading-tight tracking-wide text-muted-foreground">
{label}
</Typography>
<Typography
variant="h5"
sx={{
fontWeight: 700,
fontSize: { xs: "1.05rem", sm: "1.5rem" },
lineHeight: 1.15,
}}
>
{value}
</Typography>
{subtext && (
<Typography
variant="caption"
color="text.secondary"
sx={{ whiteSpace: "pre-line", display: "block", lineHeight: 1.35 }}
>
</span>
<span className="text-lg font-semibold leading-tight">{value}</span>
{subtext ? (
<span className="whitespace-pre-line text-xs leading-relaxed text-muted-foreground">
{subtext}
</Typography>
)}
</span>
) : null}
</CardContent>
</Card>
);