Files
supabase/.github/instructions/studio-shortcuts.instructions.md
T
Danny WhiteandClaude Sonnet 4.6 a27487fe58 feat(studio): add keyboard shortcuts for platform webhooks (#46198)
## What kind of change does this PR introduce?

Feature. Resolves FE-3418

## What is the current behaviour?

Platform webhooks (org and project) have no keyboard shortcut coverage.
Every action requires a mouse click.

## What is the new behaviour?

Adds seven shortcuts across the four UI states of the platform webhooks
pages:

**List page**

| Shortcut | Action |
|---|---|
| `Shift+F` | Focus search input |
| `Shift+N` | Open "New endpoint" sheet |

**Endpoint detail page** (when viewing a specific endpoint)

| Shortcut | Action |
|---|---|
| `Shift+E` | Open the edit sheet |
| `Shift+U` | Copy the endpoint URL |

**Create / edit form sheet**

| Shortcut | Action |
|---|---|
| `Mod+Enter` | Submit the form (create or save) |

**Delivery details sheet** (when a delivery row is open)

| Shortcut | Action |
|---|---|
| `Shift+R` | Retry the delivery (only active for non-success
deliveries) |
| `Shift+C` | Copy the active tab's payload (switches label between
"Copy event payload" / "Copy response payload") |

All shortcuts:

- Are surfaced via `ShortcutTooltip` / `Shortcut` tooltips on their
buttons
- Appear in the keyboard shortcuts reference sheet (`Mod+/`) under a new
**Platform Webhooks** group
- Are gated so they only fire in the appropriate UI state (e.g.
`Shift+E` is disabled while the edit sheet is already open)
- Apply to both the org-level (`/org/[slug]/webhooks`) and project-level
(`/project/[ref]/settings/webhooks`) pages as both use the same
`PlatformWebhooksPage` component

**Shared shortcuts reused** (no new IDs): `LIST_PAGE_FOCUS_SEARCH`,
`LIST_PAGE_NEW_ITEM`, `ACTION_BAR_SAVE`.

## To test

The platform webhooks UI is behind a feature flag for internal folks.
Enable it in Studio via **Account → Feature Previews → Platform
Webhooks**. The backend is not yet integrated, so you can test all the
shortcuts on the 1–2 mock endpoints (and their deliveries) that appear.

**List page** (`/org/[slug]/webhooks` or
`/project/[ref]/settings/webhooks`):
- [ ] `Shift+F` moves focus to the search input
- [ ] `Shift+N` opens the "New endpoint" sheet (tooltip visible on hover
of the button)

**New endpoint sheet**:
- [ ] Fill in a name and a valid URL, select at least one event type
- [ ] `Mod+Enter` submits and creates the endpoint

**Endpoint detail page**:
- [ ] `Shift+E` opens the edit sheet (tooltip visible on the Edit
button)
- [ ] `Shift+U` copies the endpoint URL and shows a toast (tooltip
visible on the copy icon next to the URL)

**Edit sheet**:
- [ ] `Mod+Enter` saves changes

**Delivery details sheet** (click a delivery row to open):
- [ ] `Shift+R` retries a failed/pending delivery (button and shortcut
absent for successful deliveries)
- [ ] On the **Event** tab: `Shift+C` copies the event payload, toast
reads "Copied event payload"
- [ ] On the **Response** tab: `Shift+C` copies the response payload,
toast reads "Copied response payload"
- [ ] Tooltip on both Copy buttons reflects the active tab label

**Shortcuts reference sheet** (`Mod+/`):
- [ ] A **Platform Webhooks** group appears when on an endpoint detail
page or with the delivery sheet open with the relevant shortcuts listed
- [ ] The basic shortcuts are shown under **List pages** when on the
root Webhooks page

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 02:37:12 +00:00

3.0 KiB

applyTo
applyTo
apps/studio/**

Studio Shortcut Review Rules

All comments are advisory.

Core Principle

When Studio UI changes introduce or materially alter repeated user actions, consider whether keyboard shortcut coverage should be added or updated. Shortcuts should use the shared Studio shortcut system and be discoverable from the visible UI.

When to Flag

  • PR adds a primary repeated action, toolbar action, list/table operation, or sub-page navigation without considering shortcut coverage.
  • PR adds a one-off keydown listener for a normal Studio action instead of using the shortcut registry and useShortcut.
  • PR registers a shortcut but does not expose it via ShortcutTooltip, ShortcutBadge, or command-menu badge where the action is visible.
  • PR uses G then ... for a non-navigation action.
  • PR adds a broad Mod+letter shortcut that overlaps common browser, editor, system, copy/save/search, or devtools behaviour.
  • PR adds a shortcut without checking existing registry and non-registry listeners for collisions.
  • PR adds a search/filter <Input> without onKeyDown={onSearchInputEscape(...)} — see Search Inputs below.

Preferred Pattern

  • Add definitions in apps/studio/state/shortcuts/registry.ts or apps/studio/state/shortcuts/registry/*.
  • Register with useShortcut.
  • Gate availability with enabled.
  • Surface visible actions with ShortcutTooltip or ShortcutBadge.
  • Prefer scoped, mnemonic sequential chords over global modifier chords.
  • Set showInSettings: false on contextual shortcuts (scoped to a specific page state, sheet, or panel).
  • When a shortcut group should appear in the reference sheet (Mod+/), add the group key to SHORTCUT_REFERENCE_GROUP_ORDER in apps/studio/state/shortcuts/referenceGroups.ts and a human label to GROUP_LABELS in ShortcutsReferenceSheet.tsx.
  • For sheet-scoped shortcuts (active only while a <Sheet> is open), mount useShortcut inside the sheet component gated by the open prop — see apps/studio/components/interfaces/ConnectSheet/useConnectSheetShortcut.ts as the canonical example.

Search Inputs

Every <Input> used as a search or filter field must include the staged-Escape handler from apps/studio/lib/keyboard.ts:

import { onSearchInputEscape } from '@/lib/keyboard'

;<Input
  value={query}
  onChange={(e) => setQuery(e.target.value)}
  onKeyDown={onSearchInputEscape(query, setQuery)}
/>

Behaviour:

  • Escape while the input has a value → clears the value, keeps focus (so a second Escape then blurs)
  • Escape while the input is empty → blurs the input
  • Stops propagation on Escape so the keystroke does not accidentally close a parent dialog or sheet

When pairing with useShortcut(LIST_PAGE_FOCUS_SEARCH, ...) to focus a search input via keyboard, always also add onSearchInputEscape on the same input — focus and escape-to-blur are always a pair.

Canonical implementation context: apps/studio/state/shortcuts/registry.ts, apps/studio/state/shortcuts/useShortcut.tsx, and apps/studio/components/ui/Shortcut*.tsx