From 75ef137b7dc6d989ead8055054c39ccc3e21f1bb Mon Sep 17 00:00:00 2001 From: Paul Nothaft Date: Sat, 5 Sep 2026 22:49:21 +0200 Subject: [PATCH] fix(usage): drop the tinted block and stop the modal opening with a focus ring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two things reported on the reformatted consent modal. The green box is gone. Setting "what is never included" apart as a tinted panel broke the rhythm of the sections and read as an arbitrary highlight rather than emphasis. All six sections are uniform now; the icon and heading are enough to tell them apart. The green bars across the disclosure were a focus ring, not a border. showModal() focuses the first focusable descendant, which since the reformat was the scrollable region I had given tabIndex={0} — so its inset ring was drawn for every user the moment the dialog opened, and because the dialog clips its sides a full-width inset ring appears as two coloured bars. Focus now goes to the dialog itself, which is also the better screen-reader behaviour: the title is announced on open, and the region's ring appears only when someone deliberately tabs to it. It is a thinner, softer ring for that case. The dialog suppresses its own ring, since that focus is programmatic rather than keyboard navigation. The collector shown in the transport sentence was never wrong: it interpolates the configured collector, and the screenshots showing http://127.0.0.1:9 were taken on a rig deliberately pointed at a dead loopback port so they could not reach production. Re-checked with USAGE_COLLECTOR_URL unset: the sentence reads https://usage.picpeak.app and both links resolve there. Refs #1110 --- .../settings/tabs/ProductUsageTab.tsx | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/frontend/src/features/settings/tabs/ProductUsageTab.tsx b/frontend/src/features/settings/tabs/ProductUsageTab.tsx index 28fec5fe..1eeb8a1e 100644 --- a/frontend/src/features/settings/tabs/ProductUsageTab.tsx +++ b/frontend/src/features/settings/tabs/ProductUsageTab.tsx @@ -26,10 +26,9 @@ const DISCLOSURE: { key: string; heading: string; Icon: ComponentType<{ className?: string }>; - tone?: 'positive'; }[] = [ { key: 'fields', heading: 'sectionFields', Icon: ListChecks }, - { key: 'excluded', heading: 'sectionExcluded', Icon: ShieldOff, tone: 'positive' }, + { key: 'excluded', heading: 'sectionExcluded', Icon: ShieldOff }, { key: 'transport', heading: 'sectionTransport', Icon: Send }, { key: 'visibility', heading: 'sectionVisibility', Icon: Globe }, { key: 'deletion', heading: 'sectionDeletion', Icon: Trash2 }, @@ -52,11 +51,19 @@ function ConsentDialog({ const [checked, setChecked] = useState(false); useEffect(() => { ref.current?.showModal(); + // showModal() focuses the first focusable descendant, which is the scroll + // region below — so its focus ring was drawn for everyone the moment the + // dialog opened, and because the dialog clips its sides an inset ring + // reads as two coloured bars across the disclosure rather than a ring. + // Focusing the dialog puts the ring back where it belongs: only when + // someone deliberately tabs to the region. + ref.current?.focus(); }, []); return (
@@ -92,17 +99,10 @@ function ConsentDialog({ tabIndex={0} role="group" aria-label={t('productUsage.consentTitle') as string} - className="flex-1 overflow-y-auto border-y border-neutral-200 dark:border-neutral-700 px-6 py-4 space-y-4 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-500" + className="flex-1 overflow-y-auto border-y border-neutral-200 dark:border-neutral-700 px-6 py-4 space-y-4 focus:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-primary-400" > - {DISCLOSURE.map(({ key, heading, Icon, tone }) => ( -
+ {DISCLOSURE.map(({ key, heading, Icon }) => ( +

{t(`productUsage.${heading}`)}