Four correctness/accessibility defects and the destructive-action flow. - Button: the loading spinner carried xmlns="http://www.w3.instance/2000/svg", a find/replace of "org" that landed inside a URL. Button also grows an href form, because <Link><Button> nested a button inside an anchor at nineteen call sites: invalid markup, two tab stops, and Enter firing only the anchor. - Fleet status was four meanings carried by hue with the distinction living in a title attribute, which touch never shows and screen readers need not announce. It now carries a text label and an accessible name, which is the one rule the design system states outright. - Modal had no focus management at all: no trap, no initial focus, no restore, no scroll lock, no aria-labelledby. Dialogs nest (a confirm over an edit), so a stack decides which panel owns Escape and Tab. - Seven destructive actions went through window.confirm(). ConfirmDialog replaces them and can say what is about to happen; deleting a secret group, a shared base step or a workflow now requires typing the name, since those have no undo and a wide blast radius. adminsite keeps its own inline idiom rather than importing a dialog system it does not have. Adds Toast, AsyncBoundary/EmptyState/ErrorState/TableSkeleton and friendlyMessage, replacing per-page loading ternaries and raw (error as Error).message text. Wired here only where a call site was already being edited; the remaining pages follow.
14 lines
395 B
TypeScript
14 lines
395 B
TypeScript
"use client";
|
|
|
|
import { QueryClientProvider } from "@tanstack/react-query";
|
|
import { queryClient } from "@/lib/query-client";
|
|
import { ToastProvider } from "@/components/ui/Toast";
|
|
|
|
export function Providers({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<QueryClientProvider client={queryClient}>
|
|
<ToastProvider>{children}</ToastProvider>
|
|
</QueryClientProvider>
|
|
);
|
|
}
|