Files
supabase/apps/studio/components/ui/BannerStack/Banners/BannerDatabaseConnections.tsx
Joshen Lim 8e3e14f198 Joshen/fe 4064 add a toast callout for feature preview (#48645)
## Context

Adds a banner toast for the database connections feature preview

<img width="315" height="322" alt="image"
src="https://github.com/user-attachments/assets/8caaab88-10a0-4a06-b678-25fc9c44dd81"
/>

## Other changes

As the observability page currently has a number of banner toasts
(metrics API, unified logs, index advisor for query performance), am
opting to REMOVE the metrics API's banner toast by virtue of how long
its been around for. Mainly to prevent over stacking of banner toasts as
it can be annoying.


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

* **New Features**
* Added a dismissible Database Connections banner with SQL examples and
a link to its feature preview.
  * Banner dismissal and CTA interactions are now tracked.
  * Dismissed banners can reappear when reintroduced.

* **Bug Fixes**
  * Banners are hidden after the feature is enabled or dismissed.
  * Improved banner handling to prevent duplicate active banners.

* **Changes**
* Replaced the Metrics API banner with the Database Connections banner.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 21:02:19 +07:00

90 lines
3.7 KiB
TypeScript

import { LOCAL_STORAGE_KEYS } from 'common'
import { useParams } from 'common/hooks'
import { Badge, Button, WarningIcon } from 'ui'
import { BannerCard } from '../BannerCard'
import { useBannerStack } from '../BannerStackProvider'
import { useFeaturePreviewModal } from '@/components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import { useLocalStorageQuery } from '@/hooks/misc/useLocalStorage'
import { useTrack } from '@/lib/telemetry/track'
export const BannerDatabaseConnections = () => {
const track = useTrack()
const { ref } = useParams()
const { dismissBanner } = useBannerStack()
const { selectFeaturePreview } = useFeaturePreviewModal()
const [, setIsDismissed] = useLocalStorageQuery(
LOCAL_STORAGE_KEYS.DATABASE_CONNECTIONS_BANNER_DISMISSED(ref ?? ''),
false
)
return (
<BannerCard
onDismiss={() => {
setIsDismissed(true)
dismissBanner('database-connections-banner')
track('database_connections_banner_dismiss_button_clicked')
}}
>
<div className="flex flex-col gap-y-4">
<div className="flex flex-col gap-y-2 items-start w-full">
<Badge variant="success" className="-ml-0.5 uppercase inline-flex items-center">
Preview
</Badge>
<div className="-mx-6 w-[calc(100%+3rem)] bg-linear-to-t from-background to-transparent px-6 py-2 border-b">
<div className="flex items-center gap-x-2">
<div>
<WarningIcon />
</div>
<p className="text-xs font-mono uppercase tracking-tigher text-warning">Blocking</p>
<p className="truncate text-xs font-mono tracking-tighter">
update orders set status = $1 where id = $2;
</p>
</div>
<div className="pl-[7.5px]">
<div className="relative flex items-center gap-x-2 pl-4 pt-2 pb-1">
<div className="absolute left-0 top-0 h-full border-l border-stronger" />
<div className="absolute left-0 top-1/2 w-3 border-b border-stronger" />
<p className="text-xs font-mono uppercase tracking-tigher text-foreground-light">
Waiting
</p>
<p className="truncate text-xs font-mono tracking-tighter text-foreground-lighter">
select * from orders where id = $1 for update
</p>
</div>
<div className="relative flex items-center gap-x-2 pl-4 py-1">
<div className="absolute left-0 top-0 h-1/2 w-3 border-l border-b border-stronger rounded-bl-md" />
<p className="text-xs font-mono uppercase tracking-tigher text-foreground-light">
Waiting
</p>
<p className="truncate text-xs font-mono tracking-tighter text-foreground-lighter">
update orders set status = $1 where id = $2;
</p>
</div>
</div>
</div>
</div>
<div className="flex flex-col gap-y-1 mb-2">
<p className="text-sm font-medium">Diagnose blocked queries</p>
<p className="text-xs text-foreground-lighter text-balance">
See what's blocking your database and terminate the session causing it.
</p>
</div>
<div className="flex gap-2">
<Button
variant="default"
size="tiny"
onClick={() => {
track('database_connections_banner_cta_button_clicked', { isEnabled: false })
selectFeaturePreview(LOCAL_STORAGE_KEYS.UI_PREVIEW_DATABASE_CONNECTIONS)
}}
>
Enable Database Connections
</Button>
</div>
</div>
</BannerCard>
)
}