Files
supabase/apps/studio/components/interfaces/ProjectHome/Home.utils.ts
T
Pamela ChiaandAli Waseem 578a73f966 feat(studio): connectSection experiment — replace Getting Started with Connect section (#43629)
## Summary

Re-ports PR #43119 against the current `ProjectHome` codebase (the
original PR targeted `HomeNew/` which was removed during the `homeNew`
graduation in #43437). Also unifies the `connectSheet` and
`connectSection` feature flags into a single `connectSection` flag — the
`connectSheet` flag is removed entirely, so both the ConnectSheet
(header) and ConnectSection (homepage row) are controlled by one
experiment.

- Adds `connectSection` PostHog experiment flag that controls two
things:
1. Swaps the Getting Started section for a Connect section on the
project homepage for new projects (< 10 days old)
2. Swaps the legacy Connect dialog for the new ConnectSheet panel in the
header
- **Control** (`getting-started`): existing Getting Started section +
legacy Connect dialog in header
- **Treatment** (`connect`): new 4-tile Connect section + ConnectSheet
in header
- `undefined` (loading): neither section renders, avoiding flash
- Tiles filtered by the same `useIsFeatureEnabled` flags as ConnectSheet
(`show_app_frameworks`, `show_mobile_frameworks`, `show_orms`)
- Connect tile clicks tracked via `home_connect_action_clicked`; section
render tracked via `home_connect_section_exposed`; sheet opens tracked
via `connect_sheet_opened` with source attribution (`header_button` or
`connect_section`)

## Changes

- `packages/common/telemetry-constants.ts` — new
`home_connect_section_exposed`, `home_connect_action_clicked`, and
`connect_sheet_opened` event types
- `ConnectSheet/ConnectSheet.tsx` — read `connectTab` query param and
sync to active mode on open; `handleModeChange` keeps param in sync on
tab switch; fire `connect_sheet_opened` event with source attribution on
open
- `ConnectButton/ConnectButton.tsx` — set `connectSource=header_button`
query param on click
- `ProjectHome/ConnectSection.tsx` — new component (4-tile connect
card); set `connectSource=connect_section` on tile click
- `ProjectHome/Home.tsx` — experiment flag wiring
- `LayoutHeader/LayoutHeader.tsx` — read `connectSection` flag instead
of `connectSheet` to toggle ConnectSheet vs legacy Connect dialog

## Test plan

To test on the Vercel preview, set `connectSection=connect` to 100% in
PostHog (or override via cookie `ph_override_connectSection=connect`).
No separate `connectSheet` flag is needed — `connectSection` controls
both features.
- [x] Treatment (`connect` variant) — "Get connected" section renders on
new project, Getting Started hidden
- [x] Control (`getting-started`) — Getting Started renders, Connect
section hidden
- [x] Mature project (> 10 days) — neither section regardless of flag
- [x] Clicking each tile opens ConnectSheet on the correct tab
(Framework / Direct / ORM / MCP)
- [x] Switching tabs inside sheet updates `connectTab` URL param
- [x] Closing sheet clears `connectTab` param
- [x] Direct URL deep-link (`?showConnect=true&connectTab=orm`) opens
sheet on correct tab
- [x] Dark mode — background gradient renders correctly
- [x] Light mode — background switches to light gradient
- [x] Responsive layout — 4 cols (xl), 2×2 (md), stacked (mobile)
- [x] Telemetry — `home_connect_section_exposed` fires once on load;
`home_connect_action_clicked` fires with correct `mode`
- [x] Treatment — header Connect button opens ConnectSheet (not legacy
Connect dialog)
- [x] Control — header Connect button opens legacy Connect dialog (not
ConnectSheet)
- [x] Telemetry — clicking a ConnectSection tile fires
`connect_sheet_opened` with `source: 'connect_section'`
- [x] Telemetry — clicking header Connect button fires
`connect_sheet_opened` with `source: 'header_button'`

---------

Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-03-13 11:50:07 +09:00

56 lines
1.9 KiB
TypeScript

import type { GettingStartedState } from './GettingStarted/GettingStarted.types'
import type { ConnectSectionVariant } from './ConnectSection.config'
export const DEFAULT_SECTION_ORDER = [
'connect',
'getting-started',
'usage',
'advisor',
'custom-report',
]
/**
* Reconciles a stored section order with the canonical list.
* Preserves user ordering for known sections, inserts missing
* sections at their default-relative position.
*/
export function mergeSectionOrder(stored: string[]): string[] {
const known = stored.filter((id) => DEFAULT_SECTION_ORDER.includes(id))
const missing = DEFAULT_SECTION_ORDER.filter((id) => !known.includes(id))
if (missing.length === 0 && known.length === stored.length) return stored
const merged = [...known]
for (const id of missing) {
const defaultIndex = DEFAULT_SECTION_ORDER.indexOf(id)
const nextKnown = DEFAULT_SECTION_ORDER.slice(defaultIndex + 1).find((c) => merged.includes(c))
if (!nextKnown) {
merged.push(id)
} else {
merged.splice(merged.indexOf(nextKnown), 0, id)
}
}
return merged
}
// Temporary: getSectionVisibility and related types support the connectSection
// experiment (connect vs getting-started). Remove after the experiment concludes.
interface SectionVisibilityInput {
connectSectionVariant: ConnectSectionVariant | false | undefined
isMatureProject: boolean
hasProject: boolean
gettingStartedState: GettingStartedState
}
export function getSectionVisibility(input: SectionVisibilityInput) {
const { connectSectionVariant, isMatureProject, hasProject, gettingStartedState } = input
const canShowEither = connectSectionVariant !== undefined && !isMatureProject && hasProject
return {
showConnectSection: canShowEither && connectSectionVariant === 'connect',
showGettingStarted:
canShowEither && connectSectionVariant !== 'connect' && gettingStartedState !== 'hidden',
}
}