From c10d3debb16d4f5ae6494602c532796171d2afa1 Mon Sep 17 00:00:00 2001 From: Danny White <3104761+dnywh@users.noreply.github.com> Date: Tue, 24 Feb 2026 16:14:03 +1100 Subject: [PATCH 1/7] feat(design-system): responsive admonition (#42971) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What kind of change does this PR introduce? Component improvement ## What is the current behavior? [Admonition](https://supabase.com/design-system/docs/fragments/admonition) often passes `actions`, often Button(s). These either are stacked via the `layout` prop `horizontal` or `vertical`. That binary choice often means, given layout flex, awkward text wrapping. ## What is the new behavior? Admonition now has a `"responsive"` value for the `layout` prop. When `layout="responsive"`, the Alert root gets `@container` so the Admonition is the container-query context. The Admonition stays `vertical` when it’s narrow and switches to `horizontal` when its own width reaches the `@md` container breakpoint, independent of page width. ## Additional context See the _Disk Management_ section of Database Settings to see the single in-situ example. Video demo: https://github.com/user-attachments/assets/318a4530-5ae4-43f3-99cf-b75967659ed3 --- apps/design-system/__registry__/index.tsx | 11 +++++++++++ .../content/docs/fragments/admonition.mdx | 12 ++++++++++++ .../default/example/admonition-responsive.tsx | 14 ++++++++++++++ apps/design-system/registry/examples.ts | 6 ++++++ .../DiskManagement/DiskManagementPanelForm.tsx | 11 ++++------- packages/ui-patterns/src/admonition.tsx | 15 ++++++++++----- 6 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 apps/design-system/registry/default/example/admonition-responsive.tsx diff --git a/apps/design-system/__registry__/index.tsx b/apps/design-system/__registry__/index.tsx index fc94395ea85f0..0a14ada3678d7 100644 --- a/apps/design-system/__registry__/index.tsx +++ b/apps/design-system/__registry__/index.tsx @@ -93,6 +93,17 @@ export const Index: Record = { subcategory: "undefined", chunks: [] }, + "admonition-responsive": { + name: "admonition-responsive", + type: "components:example", + registryDependencies: ["admonition"], + component: React.lazy(() => import("@/registry/default/example/admonition-responsive")), + source: "", + files: ["registry/default/example/admonition-responsive.tsx"], + category: "undefined", + subcategory: "undefined", + chunks: [] + }, "admonition-button": { name: "admonition-button", type: "components:example", diff --git a/apps/design-system/content/docs/fragments/admonition.mdx b/apps/design-system/content/docs/fragments/admonition.mdx index 0143008fcd96e..53337a3efb66f 100644 --- a/apps/design-system/content/docs/fragments/admonition.mdx +++ b/apps/design-system/content/docs/fragments/admonition.mdx @@ -49,6 +49,18 @@ Only ever use the `primary` (green) button `type` on a `default` Admonition. Eve className="[&_.preview>[data-orientation=vertical]]:sm:max-w-[70%]" /> +## Responsive + +{' '} + + +Reize your browser to see the button(s) change `layout` based on the Admonition’s width. + +When `layout="responsive"`, the Alert root gets `@container` so the Admonition is the container-query context. The Admonition stays `vertical` when it’s narrow and switches to `horizontal` when its own width reaches the `@md` container breakpoint, independent of page width. + ### Warning Go to Compute and Disk} + /> + ) +} diff --git a/apps/design-system/registry/examples.ts b/apps/design-system/registry/examples.ts index ad110f54fd07c..6085f8a9fa0c1 100644 --- a/apps/design-system/registry/examples.ts +++ b/apps/design-system/registry/examples.ts @@ -13,6 +13,12 @@ export const examples: Registry = [ registryDependencies: ['admonition'], files: ['example/admonition-demo.tsx'], }, + { + name: 'admonition-responsive', + type: 'components:example', + registryDependencies: ['admonition'], + files: ['example/admonition-responsive.tsx'], + }, { name: 'admonition-button', type: 'components:example', diff --git a/apps/studio/components/interfaces/DiskManagement/DiskManagementPanelForm.tsx b/apps/studio/components/interfaces/DiskManagement/DiskManagementPanelForm.tsx index dc491e4902ad9..6cd8e9ae65ada 100644 --- a/apps/studio/components/interfaces/DiskManagement/DiskManagementPanelForm.tsx +++ b/apps/studio/components/interfaces/DiskManagement/DiskManagementPanelForm.tsx @@ -3,7 +3,6 @@ import Link from 'next/link' import { useParams } from 'common' import { DOCS_URL } from 'lib/constants' import { Button } from 'ui' -import { NoticeBar } from './ui/NoticeBar' import { PageSection, PageSectionContent, @@ -12,6 +11,7 @@ import { PageSectionTitle, } from 'ui-patterns' import { DocsButton } from '../../ui/DocsButton' +import { Admonition } from 'ui-patterns/admonition' // [Joshen] Only used for non AWS projects export function DiskManagementPanelForm() { @@ -26,17 +26,14 @@ export function DiskManagementPanelForm() { - - + Go to Compute and Disk diff --git a/packages/ui-patterns/src/admonition.tsx b/packages/ui-patterns/src/admonition.tsx index dc6237cdc63ca..5af083b26d6f3 100644 --- a/packages/ui-patterns/src/admonition.tsx +++ b/packages/ui-patterns/src/admonition.tsx @@ -20,7 +20,7 @@ export interface AdmonitionProps { title?: ComponentProps description?: ComponentProps } - layout?: 'horizontal' | 'vertical' + layout?: 'horizontal' | 'vertical' | 'responsive' actions?: ReactNode icon?: ReactNode className?: string @@ -111,6 +111,8 @@ export const Admonition = forwardRef< className={cn( // Handle occasional background elements 'overflow-hidden', + // Container query context for responsive layout + layout === 'responsive' && '@container', // SVG icon admonitionSVG({ type: typeMapped }), props.className @@ -126,9 +128,10 @@ export const Admonition = forwardRef<
{label || title ? ( @@ -167,7 +170,9 @@ export const Admonition = forwardRef<
{actions} From 2b4036ff7b842a133740b652e2be5599a5d11363 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Tue, 24 Feb 2026 14:48:59 +0800 Subject: [PATCH 2/7] Render email in UserDropdown if username is empty (#43116) ## Context Just a tiny fix - the user dropdown doesn't show any user info if there's no username set, opting to show the email minimally ### Before image ### After image --- apps/studio/components/interfaces/UserDropdown.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/studio/components/interfaces/UserDropdown.tsx b/apps/studio/components/interfaces/UserDropdown.tsx index 2a32c009cb1e0..4e7e7076908b4 100644 --- a/apps/studio/components/interfaces/UserDropdown.tsx +++ b/apps/studio/components/interfaces/UserDropdown.tsx @@ -54,7 +54,7 @@ export function UserDropdown() { {IS_PLATFORM && ( <>
- {!!username && ( + {!!username ? ( <> {username} @@ -68,6 +68,10 @@ export function UserDropdown() { )} + ) : ( + + {primaryEmail} + )}
From 67ed8f18eeca454b78982ab2ba74f76dc34e4ed4 Mon Sep 17 00:00:00 2001 From: Riccardo Busetti Date: Tue, 24 Feb 2026 08:14:23 +0100 Subject: [PATCH 3/7] feat(etl): Add new setting for controlling table copy (#42853) --- .../DestinationForm/AdvancedSettings.tsx | 24 ++++--- .../DestinationForm/DestinationForm.schema.ts | 6 +- .../DestinationForm/index.tsx | 14 ++-- .../create-destination-pipeline-mutation.ts | 12 ++-- .../update-destination-pipeline-mutation.ts | 11 +-- .../replication/validate-pipeline-mutation.ts | 10 ++- packages/api-types/types/api.d.ts | 71 ++++++++++++++++++- packages/api-types/types/platform.d.ts | 49 ++++--------- 8 files changed, 127 insertions(+), 70 deletions(-) diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/AdvancedSettings.tsx b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/AdvancedSettings.tsx index 9b14461e8ac5b..ee640523a6193 100644 --- a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/AdvancedSettings.tsx +++ b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/AdvancedSettings.tsx @@ -74,26 +74,26 @@ export const AdvancedSettings = ({ ( -

Number of rows to send in a batch.

-

Larger batches use more memory, with the risk of running out of memory.

+

Number of tables to copy in parallel during the initial sync.

+

Uses one replication slot per worker (N + 1 total when fully active).

} > - + @@ -103,20 +103,22 @@ export const AdvancedSettings = ({ ( -

Number of tables to copy in parallel during the initial sync.

-

Uses one replication slot per worker (N + 1 total when fully active).

+

+ Number of copy connections each table sync worker can use in parallel when + copying a table. +

} > - + { if (!projectRef) throw new Error('projectRef is required') if (!sourceId) throw new Error('sourceId is required') - const batchConfig = - maxFillMs !== undefined || maxSize !== undefined - ? { max_fill_ms: maxFillMs, max_size: maxSize } - : undefined + const batchConfig = maxFillMs !== undefined ? { max_fill_ms: maxFillMs } : undefined const { data, error } = await post('/platform/replication/{ref}/pipelines/validate', { params: { path: { ref: projectRef } }, @@ -40,6 +37,7 @@ async function validatePipeline( config: { publication_name: publicationName, max_table_sync_workers: maxTableSyncWorkers, + max_copy_connections_per_table: maxCopyConnectionsPerTable, batch: batchConfig, }, }, diff --git a/packages/api-types/types/api.d.ts b/packages/api-types/types/api.d.ts index 32207dabcdbf4..0e5003ce69507 100644 --- a/packages/api-types/types/api.d.ts +++ b/packages/api-types/types/api.d.ts @@ -934,7 +934,8 @@ export interface paths { path?: never cookie?: never } - get?: never + /** Get database disk attributes */ + get: operations['v1-get-database-disk'] put?: never /** Modify database disk */ post: operations['v1-modify-database-disk'] @@ -2806,6 +2807,23 @@ export interface components { type: 'io2' } } + DiskResponse: { + attributes: + | { + iops: number + size_gb: number + throughput_mibps?: number + /** @enum {string} */ + type: 'gp3' + } + | { + iops: number + size_gb: number + /** @enum {string} */ + type: 'io2' + } + last_modified_at?: string + } DiskUtilMetricsResponse: { metrics: { fs_avail_bytes: number @@ -4821,6 +4839,7 @@ export interface components { * @description Deprecated. Use `status` instead. */ healthy: boolean + replication_connected: boolean } | { db_schema: string @@ -8291,6 +8310,56 @@ export interface operations { } } } + 'v1-get-database-disk': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['DiskResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to get database disk attributes */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } 'v1-modify-database-disk': { parameters: { query?: never diff --git a/packages/api-types/types/platform.d.ts b/packages/api-types/types/platform.d.ts index f695cc39e5bc0..9d917f93f37cf 100644 --- a/packages/api-types/types/platform.d.ts +++ b/packages/api-types/types/platform.d.ts @@ -5451,12 +5451,9 @@ export interface components { * @example 200 */ max_fill_ms?: number - /** - * @description Maximum size of the batch - * @example 200 - */ - max_size?: number } + /** @description Maximum number of copy connections per table */ + max_copy_connections_per_table?: number /** @description Maximum number of table sync workers */ max_table_sync_workers?: number /** @@ -5481,12 +5478,9 @@ export interface components { * @example 200 */ max_fill_ms?: number - /** - * @description Maximum size of the batch - * @example 200 - */ - max_size?: number } + /** @description Maximum number of copy connections per table */ + max_copy_connections_per_table?: number /** @description Maximum number of table sync workers */ max_table_sync_workers?: number /** @@ -8766,12 +8760,9 @@ export interface components { * @example 200 */ max_fill_ms?: number - /** - * @description Maximum size of the batch - * @example 200 - */ - max_size?: number } + /** @description Maximum number of copy connections per table */ + max_copy_connections_per_table?: number /** @description Maximum number of table sync workers */ max_table_sync_workers?: number /** @@ -8828,12 +8819,9 @@ export interface components { * @example 200 */ max_fill_ms?: number - /** - * @description Maximum size of the batch - * @example 200 - */ - max_size?: number } + /** @description Maximum number of copy connections per table */ + max_copy_connections_per_table?: number /** @description Maximum number of table sync workers */ max_table_sync_workers?: number /** @@ -10365,12 +10353,9 @@ export interface components { * @example 200 */ max_fill_ms?: number - /** - * @description Maximum size of the batch - * @example 200 - */ - max_size?: number } + /** @description Maximum number of copy connections per table */ + max_copy_connections_per_table?: number /** @description Maximum number of table sync workers */ max_table_sync_workers?: number /** @@ -10395,12 +10380,9 @@ export interface components { * @example 200 */ max_fill_ms?: number - /** - * @description Maximum size of the batch - * @example 200 - */ - max_size?: number } + /** @description Maximum number of copy connections per table */ + max_copy_connections_per_table?: number /** @description Maximum number of table sync workers */ max_table_sync_workers?: number /** @@ -10806,12 +10788,9 @@ export interface components { * @example 200 */ max_fill_ms?: number - /** - * @description Maximum size of the batch - * @example 200 - */ - max_size?: number } + /** @description Maximum number of copy connections per table */ + max_copy_connections_per_table?: number /** @description Maximum number of table sync workers */ max_table_sync_workers?: number /** From b2d20011c13c593120a0cfe1a6bfe5fbf54a1db7 Mon Sep 17 00:00:00 2001 From: Sreyas Udayavarman <129928023+sudayavarman@users.noreply.github.com> Date: Tue, 24 Feb 2026 13:37:56 +0530 Subject: [PATCH 4/7] Update compatibility.mdx (#43121) Removing "Public Alpha" status from the documentation to reflect current status. * [S3 Compatibility](https://supabase.com/features/s3-compatibility) ## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Docs update ## What is the current behavior? Please link any relevant issues here. ## What is the new behavior? ## Additional context --- apps/docs/content/guides/storage/s3/compatibility.mdx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/docs/content/guides/storage/s3/compatibility.mdx b/apps/docs/content/guides/storage/s3/compatibility.mdx index e06d9c860c5f1..1e69c541a76bb 100644 --- a/apps/docs/content/guides/storage/s3/compatibility.mdx +++ b/apps/docs/content/guides/storage/s3/compatibility.mdx @@ -12,12 +12,6 @@ Storage supports [standard](/docs/guides/storage/uploads/standard-uploads), [res Storage supports presigning a URL using query parameters. Specifically, Supabase Storage expects requests to be made using [AWS Signature Version 4](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html). To enable this feature, enable the S3 connection via S3 protocol in the Settings page for Supabase Storage. - - -The S3 protocol is currently in Public Alpha. If you encounter any issues or have feature requests, [contact us](/dashboard/support/new). - - - **S3 versioning is not supported.** Supabase Storage does not enable S3's versioning capabilities for buckets. Deleted objects are permanently removed and cannot be restored. From d6637aaf8b2f4e35074b4522b464c06ebf94c7a5 Mon Sep 17 00:00:00 2001 From: Riccardo Busetti Date: Tue, 24 Feb 2026 09:25:58 +0100 Subject: [PATCH 5/7] feat(etl): Improve copy for advanced settings (#43123) --- .../DestinationForm/AdvancedSettings.tsx | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/AdvancedSettings.tsx b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/AdvancedSettings.tsx index ee640523a6193..3971a14d673ce 100644 --- a/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/AdvancedSettings.tsx +++ b/apps/studio/components/interfaces/Database/Replication/DestinationPanel/DestinationForm/AdvancedSettings.tsx @@ -52,8 +52,14 @@ export const AdvancedSettings = ({ label="Batch wait time" description={ <> -

Time to wait for additional changes before sending.

-

Shorter times imply faster updates, but higher overhead.

+

+ Maximum time the pipeline waits to collect additional changes before + flushing a batch. +

+

+ Lower values reduce replication latency; higher values improve batching + efficiency. +

} > @@ -81,8 +87,10 @@ export const AdvancedSettings = ({ layout="horizontal" description={ <> -

Number of tables to copy in parallel during the initial sync.

-

Uses one replication slot per worker (N + 1 total when fully active).

+

Number of tables copied in parallel during the initial snapshot phase.

+

+ Each worker uses one replication slot (up to N + 1 total while syncing). +

} > @@ -111,8 +119,11 @@ export const AdvancedSettings = ({ description={ <>

- Number of copy connections each table sync worker can use in parallel when - copying a table. + Number of parallel connections each table copy can use during initial sync. +

+

+ Higher values can copy large tables faster, but consume more database + connections.

} @@ -124,7 +135,7 @@ export const AdvancedSettings = ({ type="number" value={field.value ?? ''} onChange={handleNumberChange(field)} - placeholder="Default: 4" + placeholder="Default: 2" />
@@ -149,10 +160,13 @@ export const AdvancedSettings = ({ description={ <>

- Maximum age of cached data before BigQuery reads from base tables at query - time. + Maximum allowed age for BigQuery cached metadata before reading base + tables. +

+

+ Lower values improve freshness; higher values can reduce query cost and + latency.

-

Lower values return fresher results, but may increase query costs.

} > From 1d46515edb9a731b2e80f3b1c9465d9e3d3aaaad Mon Sep 17 00:00:00 2001 From: Danny White <3104761+dnywh@users.noreply.github.com> Date: Tue, 24 Feb 2026 19:54:14 +1100 Subject: [PATCH 6/7] chore(studio): misc design polish (#42966) ## What kind of change does this PR introduce? UI polish ## What is the current behavior? Various UI rough edges that are tiny but add up. ## What is the new behavior? - Empty state for Data API: Replaced `Link` that had overly-specific styles with `InlineLink` - Copywriting improvements on Account | Before | After | | --- | --- | | Integrations
Supabase-CDDA8DBC-57D8-4D43-A1BD-0D935D9F2442 | Integrations
Supabase-E8CE34C7-D2AB-4842-93AB-04BD42D94CAC | | Account Settings Supabase | Account Settings Supabase | --------- Co-authored-by: Joshen Lim --- .../Account/Preferences/ProfileInformation.tsx | 8 ++++---- .../Integrations/DataApi/DataApiDisabledState.tsx | 9 +++------ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/apps/studio/components/interfaces/Account/Preferences/ProfileInformation.tsx b/apps/studio/components/interfaces/Account/Preferences/ProfileInformation.tsx index b5b3b9c7520b3..71494dec66457 100644 --- a/apps/studio/components/interfaces/Account/Preferences/ProfileInformation.tsx +++ b/apps/studio/components/interfaces/Account/Preferences/ProfileInformation.tsx @@ -134,8 +134,8 @@ export const ProfileInformation = () => { label="Primary email" description={ profile?.is_sso_user - ? 'Primary email is managed by your SSO provider and cannot be changed here.' - : 'Primary email is used for account notifications.' + ? 'Managed by your SSO provider and cannot be changed here' + : 'Used for account notifications' } layout="flex-row-reverse" > @@ -173,8 +173,8 @@ export const ProfileInformation = () => { label="Username" description={ profile?.is_sso_user - ? 'Username is managed by your SSO provider and cannot be changed here.' - : 'Username appears as a display name throughout the dashboard.' + ? 'Managed by your SSO provider and cannot be changed here' + : 'Display name used across dashboard' } layout="flex-row-reverse" > diff --git a/apps/studio/components/interfaces/Integrations/DataApi/DataApiDisabledState.tsx b/apps/studio/components/interfaces/Integrations/DataApi/DataApiDisabledState.tsx index ba316e61e4e9b..031d96407333e 100644 --- a/apps/studio/components/interfaces/Integrations/DataApi/DataApiDisabledState.tsx +++ b/apps/studio/components/interfaces/Integrations/DataApi/DataApiDisabledState.tsx @@ -1,6 +1,6 @@ import { useParams } from 'common' +import { InlineLink } from 'components/ui/InlineLink' import { AlertCircle } from 'lucide-react' -import Link from 'next/link' import { Alert_Shadcn_, AlertDescription_Shadcn_, AlertTitle_Shadcn_ } from 'ui' interface DataApiDisabledStateProps { @@ -17,12 +17,9 @@ export const DataApiDisabledState = ({ description }: DataApiDisabledStateProps) Data API is disabled Enable the Data API in the{' '} - + Overview - {' '} + {' '} tab to {description}. From d31534f8be8c0ca50e939cdd83a830fd227c3525 Mon Sep 17 00:00:00 2001 From: Timothy Lim Date: Tue, 24 Feb 2026 17:38:27 +0800 Subject: [PATCH 7/7] chore(docs): Update download backup guide with more clarity and links (#43124) --- .../docs/content/troubleshooting/download-logical-backups.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/docs/content/troubleshooting/download-logical-backups.mdx b/apps/docs/content/troubleshooting/download-logical-backups.mdx index 326478529e1b4..a2de237d67a30 100644 --- a/apps/docs/content/troubleshooting/download-logical-backups.mdx +++ b/apps/docs/content/troubleshooting/download-logical-backups.mdx @@ -6,8 +6,8 @@ github_url = "https://github.com/orgs/supabase/discussions/33045" database_id = "91ae4c49-bf22-4b8c-b96b-cd11f1c38158" --- -When Point-in-Time Recovery (PITR) or physical backups are enabled, Supabase no longer generates the downloadable logical backup file (backup.gz). This is expected, as the backup pipeline switches entirely to physical backups. You can still download backups via the Supabase CLI command `pgdump`. +When Point-in-Time Recovery (PITR) or physical backups are enabled, Supabase no longer generates the downloadable logical backup file (backup.gz). This is expected, as the backup pipeline switches entirely to physical backups. You can still download backups via the [Supabase CLI `db dump` command](/docs/reference/cli/supabase-db-dump) or using [`pg_dump`](https://www.postgresql.org/docs/current/app-pgdump.html). -For step-by-step instructions, check out our guide: [Backup & Restore](/docs/guides/platform/migrating-within-supabase/backup-restore). +For step-by-step instructions using the Supabase CLI, check out the [Backup database using the CLI](/docs/guides/platform/migrating-within-supabase/backup-restore#backup-database-using-the-cli) guide. You can also learn more about how backups work in Supabase here: [Database Backups](/docs/guides/platform/backups).