- Fix dialog scrollability (flex layout + max-h-[90dvh]) and increase L4 dialog to lg width - Add styled enable card to L4 dialog matching proxy host pattern - Unify section colors across proxy host and L4 dialogs (cyan=LB, emerald=DNS, violet=upstream DNS, rose=geo, amber=mTLS) - Improve light mode contrast: muted-foreground oklch 0.552→0.502, remove opacity modifiers on secondary text - Improve dark mode: boost muted-foreground to 0.85, increase border opacity 10%→16%, input 15%→20% - Add bg-card to DataTable wrapper and bg-muted/40 to table headers for surface hierarchy - Add semantic badge variants (success, warning, info, muted) and StatusChip dark mode fix - Add server-side sortable columns to Proxy Hosts and L4 Proxy Hosts (name, upstream, status, protocol, listen) - Add sortKey to DataTable Column type with clickable sort headers (ArrowUp/Down indicators, URL param driven) - Fix E2E test selectors for shadcn UI (label associations, combobox roles, dropdown menus, mobile drawer) - Add htmlFor/id to proxy host form fields and aria-labels to select triggers for accessibility - Add sorting E2E tests for both proxy host pages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
76 lines
1.8 KiB
TypeScript
76 lines
1.8 KiB
TypeScript
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogFooter,
|
|
} from "@/components/ui/dialog";
|
|
import { Button } from "@/components/ui/button";
|
|
import { ReactNode } from "react";
|
|
|
|
type AppDialogProps = {
|
|
open: boolean;
|
|
onClose: () => void;
|
|
title: string;
|
|
children: ReactNode;
|
|
maxWidth?: "xs" | "sm" | "md" | "lg" | "xl";
|
|
actions?: ReactNode;
|
|
submitLabel?: string;
|
|
onSubmit?: () => void;
|
|
isSubmitting?: boolean;
|
|
};
|
|
|
|
const MAX_WIDTH_CLASS: Record<NonNullable<AppDialogProps["maxWidth"]>, string> = {
|
|
xs: "max-w-xs",
|
|
sm: "max-w-sm",
|
|
md: "max-w-md",
|
|
lg: "max-w-2xl",
|
|
xl: "max-w-4xl",
|
|
};
|
|
|
|
export function AppDialog({
|
|
open,
|
|
onClose,
|
|
title,
|
|
children,
|
|
maxWidth = "sm",
|
|
actions,
|
|
submitLabel = "Save",
|
|
onSubmit,
|
|
isSubmitting = false,
|
|
}: AppDialogProps) {
|
|
return (
|
|
<Dialog open={open} onOpenChange={(o) => !o && onClose()}>
|
|
<DialogContent className={MAX_WIDTH_CLASS[maxWidth]}>
|
|
<DialogHeader>
|
|
<DialogTitle>{title}</DialogTitle>
|
|
</DialogHeader>
|
|
|
|
<div className="flex-1 min-h-0 overflow-y-auto py-4 px-1">{children}</div>
|
|
|
|
<DialogFooter>
|
|
{actions ?? (
|
|
<>
|
|
<Button variant="outline" onClick={onClose}>
|
|
Cancel
|
|
</Button>
|
|
{onSubmit && (
|
|
<Button onClick={onSubmit} disabled={isSubmitting}>
|
|
{isSubmitting ? (
|
|
<>
|
|
<span className="h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent mr-2" />
|
|
Saving…
|
|
</>
|
|
) : (
|
|
submitLabel
|
|
)}
|
|
</Button>
|
|
)}
|
|
</>
|
|
)}
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|