Files
supabase/apps/studio/components/interfaces/ConnectSheet/ConnectSheetStep.tsx
Danny White 6cff728742 feat(studio): polish Connect sheet mode selector and steps (#48266)
## What kind of change does this PR introduce?

UI polish for the Connect sheet: clearer mode selection, wider sheet
layout, and step/content chrome across Direct, Server, MCP, and shadcn
flows.

## What is the current behavior?

- Connect modes use a weak selected state and an awkward grid layout.
- The sheet can jump width below the `lg` breakpoint when switching
modes.
- Direct connection chrome is noisy (reset in a footer, Title Case /
mono pooler labels, mismatched copy-button sizes).
- Several steps use admonitions or extra tips that repeat footer
guidance.
- Case-sensitive import of `InlineLink` breaks Linux/Vercel builds.

## What is the new behavior?

### Mode selector and sheet
- Stronger selected/hover treatment; comfortable single row that wraps
via `@container`.
- Empty odd slots use a sunk placeholder cell.
- Sheet uses `size="lg"` with `max-w-4xl` and `w-full min-w-0` so width
stays stable when switching modes.

### Steps chrome
- “Follow these steps” header with a copy-prompt action for coding
agents.
- Optional steps labelled `(optional)`.
- Shared `CodeBlock` for install snippets; MCP feature groups preselect
all except Storage.
- Server / shadcn tips folded into footers; IPv4 add-on admonition is
responsive with an inline Learn more link and a single Enable action.

### Direct connection
- Connection string and connection parameters stay one step (same
credentials, two formats).
- Reset database password lives in the string card title row beside
Shared/Dedicated pooler.
- Card titles use sans + sentence case (`Shared pooler`, `Connection
parameters`); `.env` stays mono.
- Icon-only copy buttons match CodeBlock square sizing; row actions sit
slightly closer to the right edge (`pr-2`).
- Shared pooler toggle copy clarified.

| Before | After |
| --- | --- |
| <img width="390" height="763" alt="API Keys Settings Chisel Toolshed
Supabase"
src="https://github.com/user-attachments/assets/adca3cc5-94f8-47e5-a4a2-2831790f430a"
/> | <img width="390" height="763" alt="API Keys Settings Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/f03afe58-e654-435e-a821-835f6243ca95"
/> |
| <img width="1718" height="1323" alt="API Keys Settings Chisel Toolshed
Supabase"
src="https://github.com/user-attachments/assets/79f08620-7e1e-4246-a70f-801606c0f499"
/> | <img width="1718" height="1323" alt="API Keys Settings Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/fb45e851-955e-46c2-90f1-afecb93d6ac4"
/> |
| <img width="1718" height="1323" alt="API Keys Settings Chisel Toolshed
Supabase"
src="https://github.com/user-attachments/assets/eda36d21-bba7-46ab-ad48-134acf93b471"
/> | <img width="1718" height="1323" alt="API Keys Settings Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/b7b728c6-fc92-46a7-8e3f-2f182c56ece7"
/> |

### Test plan

- [ ] Open **Connect** and confirm mode cells select/hover clearly;
narrow the sheet and confirm wrap + stable width.
- [ ] Direct: switch Direct / Transaction / Session; confirm pooler
title, reset in title row, parameters table, and percent-encode note.
- [ ] Toggle IPv4 shared pooler on Transaction; confirm string updates
and admonition/Learn more behaviour when on IPv4-only paths.
- [ ] Server: `.env` Copy all / row copy sizing; install command copy.
- [ ] MCP / shadcn / Framework: steps still resolve and copy prompt
still builds a useful agent prompt.
- [ ] Spot-check light/dark and a Linux/Vercel build (InlineLink import
casing).
2026-07-25 00:13:54 +10:00

68 lines
2.2 KiB
TypeScript

import { PropsWithChildren } from 'react'
import { cn } from 'ui'
interface ConnectSheetStepProps {
number: number
title: string
description: string
optional?: boolean
className?: string
}
export const ConnectSheetStep = ({
number,
title,
description,
optional = false,
className,
children,
}: PropsWithChildren<ConnectSheetStepProps>) => {
const displayTitle = optional ? `${title} (optional)` : title
return (
<div
className={cn('group', className)}
data-connect-step
data-step-title={displayTitle}
data-step-description={description}
>
<div className="flex items-start gap-5 self-stretch">
<div className="relative self-stretch shrink-0 w-6">
<div className="absolute inset-0 flex items-start justify-center">
<div
aria-hidden="true"
className={cn(
'absolute left-[calc(50%-1px)] w-px bg-border opacity-60 h-full',
'group-last:bg-transparent'
)}
/>
<div className="relative z-10 flex font-mono text-xs items-center justify-center min-w-6 w-6 h-6 border border-default rounded-md bg-surface-100 text-foreground-light">
{number}
</div>
</div>
</div>
{/* Container query: side-by-side title | content when the step row is wide enough.
Viewport 2xl never applied inside max-w-4xl sheets. */}
<div className="@container w-full min-w-0">
<div className="grid grid-cols-1 @[36rem]:grid-cols-5 gap-x-6 gap-y-3 pb-8 w-full">
<div className="flex flex-col @[36rem]:col-span-2 gap-y-0.5">
<p className="text-sm font-medium text-foreground">
{title}
{optional && <span className="font-normal text-foreground-muted"> (optional)</span>}
</p>
<p className="text-sm text-foreground-light">{description}</p>
</div>
<div
className="@[36rem]:col-span-3 [&_pre.code-block]:bg-surface-75!"
data-step-content
>
{children}
</div>
</div>
</div>
</div>
</div>
)
}