admin: live query detail becomes a modal, live/history and period pickers become tabs and radios, client delete confirms in a dialog

the streamed-query detail panel is now a rac modal dialog with focus containment and restore. the live/history switch is rac tabs driven by the url, the overview period picker is a rac radio group, and the clients delete flow uses the shared confirm dialog; an authority turn keeps the dialog open and withdraws only the destructive action.
This commit is contained in:
2026-08-29 11:55:24 +02:00
parent 79578e1d2a
commit 317d5dd4f8
11 changed files with 709 additions and 375 deletions
+27 -13
View File
@@ -10,6 +10,7 @@
import * as stylex from "@stylexjs/stylex";
import { useNavigate, useSearch } from "@tanstack/react-router";
import { Radio, RadioGroup } from "react-aria-components";
import type { Period } from "@/lib/types";
import { styles as shared } from "@/ui/styles";
import { colors } from "@/ui/tokens.stylex";
@@ -38,7 +39,7 @@ const styles = stylex.create({
gap: "0.25rem",
},
period: {
cursor: { default: "pointer", ":disabled": "not-allowed" },
cursor: "pointer",
borderStyle: "none",
borderRadius: "0.25rem",
paddingInline: "0.625rem",
@@ -46,6 +47,13 @@ const styles = stylex.create({
fontSize: "0.875rem",
lineHeight: "1.25rem",
},
/** A Radio is a `label`, so RAC drives the ring rather than `:focus-visible`. */
periodFocusVisible: {
outlineWidth: 2,
outlineStyle: "solid",
outlineColor: colors.focus,
outlineOffset: 2,
},
/** The pressed fill is heavier than `surfaceHover`, so a hover cannot mimic it. */
periodSelected: {
backgroundColor: {
@@ -68,23 +76,29 @@ const styles = stylex.create({
export function PeriodPicker({ period, onChange }: { period: Period; onChange: (period: Period) => void }) {
return (
<div role="group" aria-label="Period" {...stylex.props(styles.periodGroup)}>
<RadioGroup
aria-label="Period"
orientation="horizontal"
value={period}
onChange={(next) => onChange(next as Period)}
className={() => stylex.props(styles.periodGroup).className ?? ""}
>
{PERIODS.map((option) => (
<button
<Radio
key={option}
type="button"
aria-pressed={option === period}
onClick={() => onChange(option)}
{...stylex.props(
styles.period,
option === period ? styles.periodSelected : styles.periodIdle,
shared.focusRing,
)}
value={option}
className={({ isSelected, isFocusVisible }) =>
stylex.props(
styles.period,
isSelected ? styles.periodSelected : styles.periodIdle,
isFocusVisible && styles.periodFocusVisible,
).className ?? ""
}
>
{option}
</button>
</Radio>
))}
</div>
</RadioGroup>
);
}