feat(AuditLog): Filter the organisation audit log by scope

TA
3h ago
+1249-329

Thanks for submitting a PR! Please check the boxes below:

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Contributes to #8889

Stacked on #8940.

Filter the organisation audit log by scope. A Scope control beside the search opens a card:

  • Everything, Organisation (members, roles and groups) or Project.
  • Project lists the organisation's projects, then that project's environments as toggles.
  • The control shows the choice and clears it with its own button. The scope lives in the URL beside the search.

Base components, used here first:

  • Popover rebuilt on Floating UI: outside click, Escape and focus handled in one place. The old Popover and FocusMonitor are removed, and the PanelSearch sort menu moves to the new one.
  • useOutsideClick accepts the nullable refs React 19 creates.
  • Chip gets a toggle mode: a checkbox chip that turns accent and shows a tick when checked.
  • SegmentedControl: one choice from a few, as a radio group with arrow keys.
  • Radio rebuilt around a native input: keyboard and screen readers now work, a click never unselects, and the dot uses tokens. The scope card's project list uses it.

Two changes here are outside the flag: the PanelSearch sort menu, and the merge strategy radios on the feature import page.

Why Floating UI for the Popover:

  • The old one rendered inline and hid with d-none, so parents with overflow: hidden clipped it, and it never flipped near the edge of the window. The new one renders in a portal, flips and shifts to stay on screen, and caps its height to the space left.
  • It handles Escape, focus return to the trigger and the ARIA attributes, which the old one had none of. Its outside click relied on jQuery and @ts-ignore.
  • @floating-ui/react was already installed through react-datepicker; it is now a direct dependency. It only positions and handles interactions, so it sits under our own components, unlike react-aria or Radix.

Next: the stories, then the RTL tests for these components.

How did you test this code?

  • Unit tests for scope parsing, URL round trip, the scope label and environment colours.
  • By hand against a local API: picking Organisation filters the list and adds scope=organisation to the URL; the Audit Log tab resets search and scope.
  • By hand on the Projects page: the PanelSearch sort menu opens, sorts, and closes on picking an option, outside click and Escape, with focus back on the trigger.