Files
supabase/apps/studio/components/layouts/RealtimeLayout/RealtimeLayout.tsx
Ali WaseemandDanny White 3d9fb2f98d feat(realtime): shortcuts for realtime (#46001)
## What kind of change does this PR introduce?

Feature — adds keyboard shortcuts for the Realtime section in Studio.

## What is the current behavior?

No keyboard shortcuts exist for Realtime navigation or inspector
actions.

## What is the new behavior?

### Navigation chords (layout-scoped, active on any Realtime page)

| Shortcut | Action |
|---|---|
| `R I` | Go to Inspector |
| `R P` | Go to Policies |
| `R S` | Go to Settings |

### Inspector actions (active on the Inspector page)

| Shortcut | Action | Gating |
|---|---|---|
| `Shift+J` | Join a channel | Only when no channel is joined |
| `Shift+L` | Start/Stop listening | Only when a channel is joined |
| `Shift+F` | Open filter popover | Only when a channel is joined |
| `Shift+B` | Broadcast a message | Only when listening |
| `Mod+Shift+C` | Copy selected message | Only when a message is
selected |


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Realtime Inspector: new keyboard shortcuts (join channel, toggle
listening, toggle filters, broadcast) and a copy-message shortcut with
toast feedback.
* Channel & Filter popovers support controlled/uncontrolled open state;
header now wires popover state through props.
* Shortcut tooltips added to copy and broadcast actions; realtime page
navigation shortcuts and menu shortcuts added.
* **Tests**
* Shortcut reference sheet tests updated to include realtime navigation
and inspector groups.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46001?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
2026-05-19 11:12:54 -06:00

48 lines
1.6 KiB
TypeScript

import { useRouter } from 'next/router'
import type { PropsWithChildren } from 'react'
import { ProjectLayout } from '../ProjectLayout'
import { generateRealtimeMenu } from './RealtimeMenu.utils'
import { ProductMenu } from '@/components/ui/ProductMenu'
import { ProductMenuShortcuts } from '@/components/ui/ProductMenu/ProductMenuShortcuts'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { withAuth } from '@/hooks/misc/withAuth'
/**
* Menu-only component for the Realtime section. Used by the desktop sidebar and by the
* mobile sheet submenu. Must not wrap ProjectLayout so that opening the realtime submenu
* in the mobile sheet does not overwrite registerOpenMenu and break the menu button.
*/
export const RealtimeProductMenu = () => {
const router = useRouter()
const { data: project } = useSelectedProjectQuery()
const page = router.pathname.split('/')[4]
return <ProductMenu page={page} menu={generateRealtimeMenu(project ?? undefined)} />
}
export interface RealtimeLayoutProps {
title: string
}
export const RealtimeLayout = ({ title, children }: PropsWithChildren<RealtimeLayoutProps>) => {
const { data: project } = useSelectedProjectQuery()
const router = useRouter()
const page = router.pathname.split('/')[4]
const menu = generateRealtimeMenu(project)
return (
<ProjectLayout
product="Realtime"
browserTitle={{ section: title }}
productMenu={<ProductMenu page={page} menu={menu} />}
isBlocking={false}
>
<ProductMenuShortcuts menu={menu} />
{children}
</ProjectLayout>
)
}
export default withAuth(RealtimeLayout)