Files
supabase/apps/studio/components/interfaces/ConnectButton/ConnectButton.tsx
Danny White 25c8194579 feat(studio): add Connect sheet shortcut guidance (#46185)
## What kind of change does this PR introduce?

Feature, docs update.

- Resolves FE-3419
- First pass for DEPR-578

## What is the current behaviour?

The Connect sheet can be opened from visible UI and command-menu
actions, but it does not have a direct keyboard shortcut. Studio also
has shortcut conventions in code, but limited agent-facing review
guidance for contributors adding or touching Studio UI.

## What is the new behaviour?

FE-3419:

- Adds `O then C` to open the Connect sheet for active healthy projects.
- Mounts the shortcut from the always-rendered Connect sheet, so it
works without first opening the lazy command menu.
- Surfaces the shortcut on the Connect button tooltip, in the shortcuts
reference sheet, and on the Connect command-menu action.
- Forces the tooltip closed while the sheet is open so Escape closes the
sheet without also driving tooltip state.
- Tracks keyboard shortcut opens with the existing Connect sheet
telemetry event.
- Moves single-item AI Assistant and Inline Editor shortcuts to the
_Global Actions_ section in the cheatsheet.

DEPR-578:

- Adds a short Studio shortcut convention to `.claude/CLAUDE.md`.
- Adds scoped Copilot review guidance for Studio shortcut coverage,
discovery, and collision checks.
- Points the guidance back to the existing shortcut registry,
`useShortcut`, `Shortcut`, and `ShortcutTooltip` implementation context.

| After |
| --- |
| <img width="1576" height="188" alt="CleanShot 2026-05-21 at 11 30
40@2x"
src="https://github.com/user-attachments/assets/ba9d68c8-27ea-4c89-8016-d95d5bcea3ea"
/> |
| <img width="830" height="364" alt="CleanShot 2026-05-21 at 11 48
51@2x-FC627CB5-4A1C-49E2-B748-8AF0A3EBD7BC"
src="https://github.com/user-attachments/assets/d6aa52c1-56b2-4731-8e6b-088e29da43ed"
/> |

Validation:

- `pnpm --dir apps/studio exec vitest --run
components/ui/GlobalShortcuts/ShortcutsReferenceSheet.test.tsx
components/interfaces/ConnectButton/Connect.Commands.test.tsx
components/interfaces/ConnectSheet/useConnectSheetShortcut.test.ts`
- `git diff --check`

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

* **New Features**
* Keyboard shortcut to open the Connect sheet from anywhere; Connect
button displays the shortcut and is enabled only for eligible projects.
* New "Global Actions" group in the shortcuts reference including AI
Assistant, Inline Editor, and Connect.

* **Documentation**
* Added Studio keyboard-shortcuts guidance and linked it in project
instructions.

* **Tests**
* Added tests covering connect shortcut behavior and command
registration.

* **Telemetry**
  * Connect-sheet open events now record keyboard shortcut as a source.

<!-- 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/46185?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: Ali Waseem <waseema393@gmail.com>
2026-05-21 09:32:22 -06:00

81 lines
2.4 KiB
TypeScript

import { Plug } from 'lucide-react'
import { parseAsBoolean, useQueryState } from 'nuqs'
import { ComponentProps } from 'react'
import { Button, cn } from 'ui'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { ShortcutTooltip } from '@/components/ui/ShortcutTooltip'
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
import { PROJECT_STATUS } from '@/lib/constants'
import { useTrack } from '@/lib/telemetry/track'
import { useAppStateSnapshot } from '@/state/app-state'
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
interface ConnectButtonProps {
buttonType?: ComponentProps<typeof Button>['type']
className?: string
iconOnly?: boolean
}
export const ConnectButton = ({
buttonType = 'default',
className,
iconOnly = false,
}: ConnectButtonProps) => {
const { data: selectedProject } = useSelectedProjectQuery()
const { setConnectSheetSource } = useAppStateSnapshot()
const isActiveHealthy = selectedProject?.status === PROJECT_STATUS.ACTIVE_HEALTHY
const track = useTrack()
const [showConnect, setShowConnect] = useQueryState(
'showConnect',
parseAsBoolean.withDefault(false)
)
if (isActiveHealthy) {
return (
<ShortcutTooltip
shortcutId={SHORTCUT_IDS.CONNECT_OPEN_SHEET}
side="bottom"
open={showConnect ? false : undefined}
>
<Button
type={buttonType}
disabled={!isActiveHealthy}
className={cn('rounded-full', className)}
icon={<Plug className="rotate-90" />}
onClick={() => {
track('header_connect_button_clicked')
setConnectSheetSource('header_button')
setShowConnect(true)
}}
>
<span className={cn({ 'sr-only': iconOnly })}>Connect</span>
</Button>
</ShortcutTooltip>
)
}
return (
<ButtonTooltip
type={buttonType}
disabled
className={cn('rounded-full', className)}
icon={<Plug className="rotate-90" />}
onClick={() => {
track('header_connect_button_clicked')
setConnectSheetSource('header_button')
setShowConnect(true)
}}
tooltip={{
content: {
side: 'bottom',
text: 'Project is currently not active and cannot be connected',
},
}}
>
<span className={cn({ 'sr-only': iconOnly })}>Connect</span>
</ButtonTooltip>
)
}