Commit Graph
84 Commits
Author SHA1 Message Date
Danny White 68d5011514 fix(studio): hide secret visibility controls in pipeline edit forms (#51010)
## Problem

Pipeline edit forms hide stored credentials but still show visibility
controls beside their placeholders. The controls suggest that the stored
secret can be revealed.

## Solution

- Hide visibility controls in edit mode for ClickHouse, Snowflake,
DuckLake, and Analytics Bucket secret fields.
- Keep the controls available when creating a destination, with
accessible labels for the DuckLake and Analytics Bucket controls.

| Before | After |
| --- | --- |
| <img width="1024" height="196" alt="CleanShot 2026-09-29 at 16 48
56@2x"
src="https://github.com/user-attachments/assets/a9da9a32-ab17-4c07-abf3-dfa88b8c6475"
/> | <img width="1024" height="168" alt="CleanShot 2026-09-29 at 16 47
23@2x"
src="https://github.com/user-attachments/assets/fddeb880-cd23-4752-ae73-8f27348c647f"
/> |

## To test

1. Open **Database → Pipelines** and edit a destination of each type:
ClickHouse, Snowflake, DuckLake with custom parameters, and Analytics
Bucket. Check that the hidden secret fields have no eye button.
2. Start creating each destination and check that its secret fields
still offer a working visibility control.

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

## Summary

* **Improvements**
* Secret fields in replication destination forms remain masked when
editing an existing destination, and their visibility controls are
hidden. When creating a destination, supported secret fields can be
revealed.
* **Accessibility**
* Catalog-token visibility controls now use dynamic, descriptive labels.
DuckLake catalog URL and S3 secret-key reveal controls also have
descriptive labels.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-30 09:55:45 +10:00
Danny White 6b7c91a773 docs(pipelines): clarify ClickHouse setup and form copy (#51009)
## Problem

The ClickHouse destination guide leaves parts of resource setup unclear.
The pipeline form suggests the `default` ClickHouse user and database
even when a dedicated user and database are prepared.

## Solution

- Clarify the ClickHouse setup path, connection details, engine choice,
and query example in the guide.
- Align the pipeline form's labels, examples, and help text with that
setup path.
- Include **Start pipeline** in the BigQuery guide before the cost
confirmation and **Create and start pipeline**.

## Review instructions

1. Open **Database → Pipelines**, add a pipeline, and choose
**ClickHouse**. Check the endpoint label, user and database examples,
and table engine help.
2. Read the [ClickHouse destination
guide](https://supabase.com/docs/guides/database/replication/pipelines/clickhouse),
especially **Prepare ClickHouse resources** and **Configure ClickHouse
as a destination**.

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

* **Documentation**
* Updated the BigQuery guide to explain the pipeline validation, cost
review, and start steps.
* Expanded the ClickHouse guide with destination setup requirements,
engine behavior, and querying guidance for current-state views and
append-only history.
* **User Experience**
* Clarified ClickHouse connection field labels and descriptions,
password visibility controls, and table-engine options in the setup
form.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-30 09:44:06 +10:00
Danny White c415f502ed feat(studio): show publication partition handling (#50773)
## Problem

During pipeline creation, Studio did not show how an existing Postgres
publication handles partitioned tables. The checkbox in the
new-publication sheet also made the two possible modes harder to
compare.

Resolves
[DEPR-675](https://linear.app/supabase/issue/DEPR-675/show-and-edit-postgres-partition-handling-for-publications).

## Solution

Replace the checkbox in the new-publication sheet with a two-option
dropdown. The default remains “Use parent table identity”.

For an existing publication, append its partition-handling mode to the
Publication field description in the pipeline creation sheet. This shows
the current setting without presenting it as an editable pipeline
option. Changing an existing publication’s setting is outside this PR.

| Existing Publication Selection |
| --- |
| <img width="1260" height="224" alt="CleanShot 2026-09-28 at 12 52
10@2x"
src="https://github.com/user-attachments/assets/240d7c23-d226-40b9-8d27-a359c8ae4b75"
/> |
| _Loading_ |
| <img width="1238" height="198" alt="CleanShot 2026-09-28 at 12 52
00@2x"
src="https://github.com/user-attachments/assets/36c8b1de-eb47-4f76-890d-19d0f33a75a1"
/> |
| _One of two values_ |

| New Publication Creation |
| --- |
| <img width="832" height="660" alt="CleanShot 2026-09-28 at 12 52
33@2x"
src="https://github.com/user-attachments/assets/c1108c3a-d65b-4d20-b1a8-7e0b68fe5e87"
/> |
| _One of two values_ |
| <img width="840" height="650" alt="CleanShot 2026-09-28 at 12 52
40@2x"
src="https://github.com/user-attachments/assets/6a2c23d9-12d5-4949-91b1-3867b60ccdd5"
/> |
| _Second of two values_ |

## Review instructions

1. Open the pipeline creation sheet and choose to create a new
publication. Confirm that Postgres partition handling offers “Use parent
table identity” and “Replicate each partition separately”, with the
former selected by default.
2. Select each option in turn and confirm that the new publication is
created with the selected mode.
3. Select an existing publication and confirm that its
partition-handling mode appears in the description beneath Publication.
Switch publications and confirm that the description updates.

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

* **New Features**
* The replication destination form explains whether the selected
publication uses the parent table’s identity or replicates partitions
separately. It also shows when publication details are loading or
unavailable.
* When creating a publication, choose how partitioned tables are
handled: use the parent table’s identity or replicate each partition
separately.
* **Tests**
* Added coverage for publication guidance, loading and unavailable
states, and partition-handling choices.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-29 11:41:21 +10:00
Danny White fd0918833f feat(studio): refine pipeline creation copy (#50751)
## Problem

The pipeline creation sheet uses generic examples, inconsistent
destination terminology, and Advanced settings copy that does not
explain what is being overridden. Its Docs button also sends most
destinations to the general Pipelines guide.

This PR is stacked on #50719 so the shared copy builds on the focused
Snowflake field improvements.

## Solution

Adds destination-specific pipeline-name examples and field descriptions,
clarifies destination summaries and Advanced settings, uses
human-readable ClickHouse engine names, shortens the primary action to
**Start pipeline**, and links the Docs button to the selected
destination guide.

## Review instructions

1. Open **[Database
Replication](https://studio-staging-git-dnywh-studiorefine-pipeline-1eaf59-supabase.vercel.app/dashboard/project/_/database/replication)**
and click **Add pipeline**.
2. Switch between destination types and confirm the pipeline-name
example, destination summary, and field descriptions update
appropriately.
3. Open **Advanced settings** and confirm the batch wait-time default is
shown in the description while the input placeholder is `10000`.
4. Select each supported destination and confirm **Docs** opens its
matching destination guide.
5. Select ClickHouse and confirm the engine choices read
**ReplacingMergeTree** and **MergeTree**.

## Checklist

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [x] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which references
[WORD_LIST](https://github.com/supabase/supabase/blob/master/apps/docs/WORD_LIST.md)
and the docs
[CONTRIBUTING](https://github.com/supabase/supabase/blob/master/apps/docs/CONTRIBUTING.md)
guide


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

## Summary by CodeRabbit

* **Updates**
* Clarified replication settings, destination field descriptions, and
batch wait-time guidance.
* Added destination-specific pipeline name placeholders and updated the
labels for ClickHouse engine options.
  * Clarified ClickHouse password guidance for new destinations.
* Updated new-pipeline buttons to say “Start pipeline” or “Start
pipeline anyway.”
* Added destination-specific documentation links for BigQuery,
ClickHouse, DuckLake, and Snowflake.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-28 10:59:27 +10:00
Danny WhiteandJoshen Lim 9fb173e827 feat(studio): improve Snowflake destination setup (#50719)
## Problem

Snowflake setup makes the public and private key files easy to confuse,
treats the optional SQL role like a primary connection field, and
requires users to paste private-key contents manually. Password managers
can also mistake the Snowflake user field for a sign-in field.

This PR is based on #50708 so its later Docs-button follow-up can use
the nested destination-guide URLs.

## Solution

Clarifies the Snowflake field copy and example values, moves **Role**
into Advanced settings, opts the service-user field out of
password-manager overlays, and adds drag-and-drop or button upload for
P8 and PEM private-key files. Public key files are rejected without
replacing the current field value.

| Before | After |
| --- | --- |
| <img width="1280" height="1323" alt="Pipelines Database Agua Basket
Supabase"
src="https://github.com/user-attachments/assets/83d91b03-34f0-479f-ba65-ad9275b28431"
/> | <img width="1280" height="1323" alt="Replication Database Agua
Basket Supabase"
src="https://github.com/user-attachments/assets/a722722c-d518-4c60-94b8-e79bab6de2ca"
/> |

## Review instructions

1. Open **[Database >
Replication](https://studio-staging-git-dnywh-studioimprove-snowflake-form-supabase.vercel.app/project/_/database/replication)**,
click **Add pipeline**, and select **Snowflake**.
2. Confirm **Role** appears under **Advanced settings** and explains the
default-role behaviour.
3. Upload or drop a valid P8 or PEM private key and confirm its contents
appear in **Private key**.
4. Select a public key file and confirm the form rejects it without
replacing the existing value.
5. Confirm 1Password (or Bitwarden etc) does _not_ add its widget to
**User**.

## Checklist

- [x] I have read
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
- [x] If I wrote a new docs topic or edited an existing topic, I used
the `/write-the-docs` or `/edit-the-docs` skill, which references
[WORD_LIST](https://github.com/supabase/supabase/blob/master/apps/docs/WORD_LIST.md)
and the docs
[CONTRIBUTING](https://github.com/supabase/supabase/blob/master/apps/docs/CONTRIBUTING.md)
guide


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

- **New Features**
  - Added Snowflake private key upload via file picker or drag-and-drop.
- Supports P8 and PEM private key files, with validation and clear error
messages.
  - Added an optional Snowflake role field in Advanced Settings.
- **Usability Improvements**
  - Preserves manual edits made while a private key file is processing.
- Improved drag-and-drop feedback and updated field guidance and
placeholders.
- Prevents password managers from automatically filling Snowflake
credentials.
- Validates private keys when submitting the Snowflake destination form.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-28 10:38:57 +10:00
Danny White d067e81a69 fix(ui): align primary colours across text, buttons, and controls (#50697)
## Problem

Primary colour serves readable text and selected controls, but those
uses need different shades. Light mode needs darker text, while dark
mode needs a deeper button fill. Fixed brand green on interactive chrome
also prevents a custom primary hue from carrying through the interface.
Some slider tracks and selected text are hard to read.

## Solution

- Keep `--primary` for accessible text and small selected indicators.
Use `--primary-solid` for button fills, which need a deeper shade in
dark mode.
- Add `--primary-bright` for focus rings, selected control chrome, chart
accents, and other interactive highlights. It follows `--primary-hue`;
`brand-*` stays fixed for Supabase identity.
- Make slider troughs clearer and text selection translucent with theme
foreground text.
- Document the split in the design-system colour guide.

| Before | After |
| --- | --- |
| <img width="980" height="244" alt="Before: light mode primary
controls"
src="https://github.com/user-attachments/assets/dfae325d-0dfe-4231-8bcd-3f89c4b9d793"
/> | <img width="982" height="204" alt="After: light mode primary
controls"
src="https://github.com/user-attachments/assets/5fdcb531-a6e3-4549-8a13-9d9a5ebe6e20"
/> |
| <img width="610" height="120" alt="Before: slider track"
src="https://github.com/user-attachments/assets/04f768e0-51e8-4d06-9b97-c52f4a34f122"
/> | <img width="622" height="126" alt="After: slider track"
src="https://github.com/user-attachments/assets/95127f4e-13dc-4f0f-b63c-cf5d70a28b42"
/> |
| <img width="652" height="512" alt="Before: dark mode controls"
src="https://github.com/user-attachments/assets/3f88de66-90cc-40ee-8cf1-b5f4eb87b09a"
/> | <img width="658" height="498" alt="After: dark mode controls"
src="https://github.com/user-attachments/assets/906bec30-6ca1-4614-9fb3-6cf5e5feec22"
/> |

## Review instructions

1. Compare light and dark mode in the [colour usage
guide](https://design-system-git-dnywh-fix-bright-brand-chrome-supabase.vercel.app/design-system/docs/color-usage#primary-and-brand-colors).
Check primary ink, primary-solid, primary-bright, and fixed brand
swatches.
2. In Studio, open the ‘new table’ sheet in [Table
Editor](https://studio-staging-git-dnywh-fix-bright-brand-chrome-supabase.vercel.app/dashboard/project/_/editor).
Tab through the new table sheet's fields and toggles. Check the focus
rings, selected controls, and the sheet's edges in both themes. You do
not need to save a table.
3. Select text in Studio in both themes, including a link or
primary-coloured label. The selection and text should remain legible.
4. Check the
[Field](https://design-system-git-dnywh-fix-bright-brand-chrome-supabase.vercel.app/design-system/docs/components/field)
Price Range slider: the unused track should remain visible in both
themes. The selected field card border should follow primary-bright.
5. Check the
[Button](https://design-system-git-dnywh-fix-bright-brand-chrome-supabase.vercel.app/design-system/docs/components/button)
and [Radio
Group](https://design-system-git-dnywh-fix-bright-brand-chrome-supabase.vercel.app/design-system/docs/components/radio-group)
previews. In dark mode, `primary` button fill should be deeper than
primary
[text](https://design-system-git-dnywh-fix-bright-brand-chrome-supabase.vercel.app/design-system/docs/color-usage#text);
selected radios should remain readable.
2026-09-24 09:56:31 +10:00
Danny White ec53175b8a refactor(ui): rename text-brand to text-primary (#50564)
## What kind of change does this PR introduce?

Refactor. Follow-up to #49871.

## What is the current behavior?

Branded (green) text still uses the `text-brand` classname while the
colour comes from `--primary`.

## What is the new behavior?

**Rename-only:** `text-brand` → `text-primary` across callsites and
docs. Leftover `bg-brand` / `border-brand` alias to `brand-default`. No
intentional colour changes in this PR.

This better matches how we treat our green in other components and
props, like `variant="primary"` for green buttons.

## To test

On light mode: smoke-test that branded text still looks like #49871
(readable green, not the bright fill).

-
[Homepage](https://zone-www-dot-com-git-dnywh-depr-316-text-brand-de2380-supabase.vercel.app/):
“Scale to millions” uses `text-primary`
- [Docs
homepage](https://docs-git-dnywh-depr-316-text-brand-to-primary-supabase.vercel.app/docs):
branded links like “More on self-hosting” are still readable
- [Typography
docs](https://design-system-git-dnywh-depr-316-text-brand-to-primary-supabase.vercel.app/design-system/docs/typography):
documents `text-primary`
- [Colour
usage](https://design-system-git-dnywh-depr-316-text-brand-to-primary-supabase.vercel.app/design-system/docs/color-usage):
`text-primary` is visibly darker than `bg-brand-default` _on light mode_
- [Studio auth
providers](https://studio-staging-git-dnywh-depr-316-text-brand-to-60fa6c-supabase.vercel.app/dashboard/project/_/auth/providers):
enabled provider badge text readable; status dot stays bright green

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

* **Style**
* Updated branded text, link hover states, icons, badges, indicators,
and highlighted content across the Design System, Docs, Studio, Learn,
UI Library, and marketing experiences to use the primary theme color.
* Updated syntax highlighting and table-of-contents styling for
consistent primary-color presentation.
  * Refined brand color fallback behavior for bright fills and borders.

* **Documentation**
* Updated color-usage and typography guidance to recommend the primary
text utility.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-22 16:19:03 +10:00
Danny WhiteandJoshen Lim a31ca2bad0 fix(ui): make brand text readable across themes (#49871)
## What kind of change does this PR introduce?

Bug fix and design-system update. Resolves DEPR-316.

Follow-up rename (`text-brand` → `text-primary`) is in a dedicated PR
(https://github.com/supabase/supabase/pull/50564) stacked on this one.

## What is the current behavior?

`text-brand` resolves to the canonical bright brand green in places that
need readable text, which fails WCAG AA on light surfaces. A separate
`text-brand-display` token adds another green for large type.

## What is the new behavior?

- `text-brand` maps to accessible `--primary` (light mode darkened to
meet ~4.5:1 AA)
- `--hue` / `--primary-hue` aligned to 157.5
- `text-brand-display` removed; former display callsites use
`text-brand`
- Bright fills/borders stay on `brand-default`
- Design-system colour and typography docs updated

| Before | After |
| --- | --- |
| <img width="514" height="112" alt="CleanShot 2026-09-02 at 11 13
09@2x"
src="https://github.com/user-attachments/assets/4e0138a9-a32d-4e4c-a426-90736706e1e7"
/> | <img width="512" height="138" alt="CleanShot 2026-09-21 at 11 42
05@2x"
src="https://github.com/user-attachments/assets/164cc5b1-a0c5-4e93-95f1-80016641a114"
/> |
| <img width="864" height="266" alt="CleanShot 2026-09-02 at 11 13
53@2x"
src="https://github.com/user-attachments/assets/3c1ca53f-bf9e-431e-bc15-816b4a275b8e"
/> | <img width="882" height="248" alt="CleanShot 2026-09-21 at 11 41
37@2x"
src="https://github.com/user-attachments/assets/24828e7b-ed6b-44cb-b9dc-becc3398bdfc"
/> |
| <img width="782" height="692" alt="CleanShot 2026-09-02 at 11 16
30@2x"
src="https://github.com/user-attachments/assets/fc871977-77bc-47fb-9e0e-9284e0ecd5cc"
/> | <img width="730" height="690" alt="CleanShot 2026-09-21 at 11 42
52@2x"
src="https://github.com/user-attachments/assets/bf479515-d5f9-471e-b82d-f097c0f4b56c"
/> |
| <img width="480" height="306" alt="CleanShot 2026-09-02 at 11 18
53@2x"
src="https://github.com/user-attachments/assets/03f341f4-f02e-44f8-a2b2-8c31670d0427"
/> | <img width="470" height="300" alt="CleanShot 2026-09-21 at 11 43
19@2x"
src="https://github.com/user-attachments/assets/9df18217-d5e6-48b8-ba0b-579d2664b94b"
/> |
| <img width="960" height="300" alt="CleanShot 2026-09-02 at 11 32
04@2x"
src="https://github.com/user-attachments/assets/6b1d9373-7a71-4247-81ff-26441604b09d"
/> | <img width="980" height="306" alt="CleanShot 2026-09-21 at 11 44
13@2x"
src="https://github.com/user-attachments/assets/41ad4784-02ec-4b29-b860-32af9fa79aa8"
/> |
| <img width="924" height="214" alt="CleanShot 2026-09-02 at 11 34
44@2x"
src="https://github.com/user-attachments/assets/1de661fe-c7b6-499b-a94f-e4737436ec79"
/> | <img width="752" height="162" alt="CleanShot 2026-09-21 at 11 44
56@2x"
src="https://github.com/user-attachments/assets/1811890f-0660-4445-84e9-447720954fa1"
/> |

## To test

Test each callsite **in light mode** (dark mode is largely unchanged).

### WWW

-
[Homepage](https://zone-www-dot-com-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/):
“Scale to millions” uses readable brand text (display token is gone)
-
[Careers](https://zone-www-dot-com-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/careers):
small “Careers” eyebrow readable; green dividers stay bright
`brand-default`
-
[Contact](https://zone-www-dot-com-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/contact-us):
email / policy links use readable brand text
-
[Regions](https://zone-www-dot-com-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/regions):
“Ask about early access to BYOC” readable

### Docs

- [Docs
homepage](https://docs-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/docs):
“DOCS” wordmark and resource links readable
- [Database
overview](https://docs-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/docs/guides/database/overview):
nav / footer brand links readable
- [JavaScript
reference](https://docs-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/docs/reference/javascript/introduction):
active sidebar treatment readable

### Design system

-
[Typography](https://design-system-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/docs/typography):
documents `text-brand` only (no display)
- [Colour
usage](https://design-system-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/docs/color-usage):
`text-brand` vs `bg-brand-default`
- [Design-system
homepage](https://design-system-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/):
brand text examples across themes

### Studio

- [Auth
providers](https://studio-staging-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/dashboard/project/_/auth/providers):
enabled provider badge text readable; status dot stays bright
- [Database
policies](https://studio-staging-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/dashboard/project/_/database/policies?new=true):
template hover text more legible
- [Database
connections](https://studio-staging-git-dnywh-depr-316-brand-text-tokens-supabase.vercel.app/dashboard/project/_/observability/connections):
“Live” status readable; animated dot stays bright green

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-22 10:07:28 +10:00
Riccardo Busetti ced974e073 docs(pipelines): Align and streamline replication guides (#49252) 2026-09-21 08:27:07 +02:00
edec85d1ca fix(pipelines): Make pipeline actions and status updates reliable (#50085)
## Summary

Make pipeline actions and status feedback reliable while requests are
running or fail. Let the backend coordinate table resets and restarts,
keep stopped pipelines stopped after resets or settings changes, and
refresh the UI from confirmed backend state.

## Pipeline actions and recovery

- Reset one table, all errored tables, or all tables through the
rollback endpoint without separate frontend stop/start requests. Explain
which destination data is deleted, which rows are copied again, initial
sync charges, and the skip-initial-sync setting.
- Keep pending feedback until the action and a fresh status read finish,
including across navigation and polling errors. Prevent overlapping
actions and disable start/stop controls when status is unavailable or
transitioning.
- Close the creation form once the pipeline is created. If its initial
start fails, users can retry Start on the existing pipeline without
creating a duplicate.
- Wait for confirmed shutdown before deletion; a shutdown error or
timeout leaves deletion retryable. Keep failed version updates open and
avoid reporting success.
- Clarify recovery guidance and pending labels, suppress duplicate error
toasts, and hide stale table errors during transitions.

## Status updates and shared UI

- Poll pipeline status and table metrics one second after each response,
share in-flight reads, pause dashboard polling in background tabs, and
respect rate-limit backoff. The shutdown waiter continues in the
background.
- Refresh metadata after mutations even when an older read is in flight,
while preserving shared polling requests. Refresh affected data after
failures that may follow a committed reset or settings change.
- Move pending request state into the shared, project-keyed
`DatabaseLayout` so the list, detail page, and diagram stay consistent.
The surrounding database-page changes update named imports in both
Next.js and TanStack routes.
- Simplify action, status, and form rendering; announce status changes
to assistive technology; and sort table statuses without mutating cached
data.

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
2026-09-18 11:32:48 +08:00
Danny White 2e435986c9 feat(studio): polish the Replication pipelines list (#50252)
## What kind of change does this PR introduce?

Studio UI and interaction polish. This is the second PR in the Pipelines
review stack and depends on #50251.

## What is the current behaviour?

Pipeline rows require a separate view action, cannot be sorted, and
present lifecycle, lag, and destination terminology inconsistently.

## What is the new behaviour?

Makes rows navigable with link-like mouse and keyboard behaviour, adds
Name and Status sorting, reuses cached status queries, and moves row
actions into the overflow menu. It also clarifies pipeline terminology,
adds Docs and feedback actions, and standardises state, error, lag, and
loading presentation with accessible announcements.

| Before | After |
| --- | --- |
| <img width="1280" height="1323" alt="Replication Database ETL BigTable
ETL Team Supabase"
src="https://github.com/user-attachments/assets/53a62283-0e58-4408-8409-2b87a38af159"
/> | <img width="1280" height="1323" alt="Replication Database Agua
Basket Supabase"
src="https://github.com/user-attachments/assets/ba4de1e0-4a84-43b4-8975-ca05a3056bcf"
/> |

## To test

1. Open `/project/<ref>/database/replication`.
2. Sort by Name and Status, then confirm failed and stopped pipelines
surface first when Status is ascending.
3. Click a row, use Enter or Space, and modifier-click or middle-click
to verify link behaviour.
4. Open the row overflow menu and confirm it does not navigate.
5. Check loading, initial sync, caught up, numeric lag, unavailable lag,
and table-error states where available.


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

- **New Features**
- Added sortable pipeline lists with clearer loading, empty, and error
states.
- Pipeline rows now support direct navigation, detail viewing, status
indicators, lag progress, and table error summaries.
- Added initial-sync progress indicators and accessible status
announcements.
  - Added documentation and feedback links.
  - Improved pipeline version update and enable/disable dialogs.

- **Bug Fixes**
  - Prevented right-clicks from triggering navigation.
  - Improved unavailable lag and initial-sync handling.

- **Style**
- Standardized replication terminology and confirmation messaging around
pipelines.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 10:07:49 +10:00
Danny White 476d4a5851 refactor(ui): drop redundant Button variant="default" props (#50161)
## What kind of change does this PR introduce?

Mechanical cleanup on top of the Button default-variant change (#50160).

## What is the current behavior?

Many callsites still pass `variant="default"` even though that is now
the component default.

## What is the new behavior?

Removes redundant static `variant="default"` from legacy `Button` and
`ButtonTooltip` callsites. Keeps explicit defaults where they document
the API:

- `button-default.tsx` and `button-sizes.tsx` demos
- `DocsButton`, which pins neutral styling at the wrapper boundary

## To test

Studio:

- [Auth → Rate
Limits](https://studio-staging-2s957kwc4-supabase.vercel.app/dashboard/project/_/auth/rate-limits):
dirty the form so Cancel appears; Cancel stays neutral, Save stays green
- [Project Settings → API
Keys](https://studio-staging-2s957kwc4-supabase.vercel.app/dashboard/project/_/settings/api-keys):
`DocsButton` in the header actions stays neutral

Design system:

- [Design system →
Button](https://design-system-git-dnywh-dc924ac1-supabase.vercel.app/design-system/docs/components/button):
`button-default` / `button-sizes` still show explicit default styling;
Primary (green) is restricted to the Primary section (and `asChild`)

WWW:

- [www → Brand
assets](https://zone-www-dot-com-git-dnywh-dc924ac1-supabase.vercel.app/brand-assets):
Download logo kit / Download button kit stay neutral
2026-09-11 17:05:26 +10:00
Gildas GarciaandAlaister Young 737b8595f2 Update API types (#50234)
## Problem

platform, v1 and v2 have been already completely migrated and introduced
some changes.

Some types have been renamed, some outputs and inputs updated.

## Solution

- Update the API types
- Fix the TS errors

## Update

Taking this over to unblock #50134, which needs the new scoped token
permission ids from the regenerated types.

- Merged `master`.
- Regenerated `api-v2.d.ts` from the production spec. The previous files
came from a local API that exposed a webhook events endpoint production
doesn't have yet. Production has since added standardized 400 error
responses on the v2 organization endpoints. `api-v1.d.ts` and
`platform.d.ts` already matched production.
- Fixed `verify-production-types`. It formatted the regenerated files in
a temp directory outside the repository, so Prettier fell back to its
defaults and the comparison could never match the committed files. It
now passes the repository config explicitly. `pnpm api:verify-types`
passes on this branch.
- Verified locally: `pnpm typecheck`, `pnpm api:verify-types`, Studio
unit tests.

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

* **Bug Fixes**
* Preserved descriptions when saving, sharing, moving, or unsharing
notebooks, reports, SQL snippets, and saved queries.
* Improved handling of empty or null values across notebook
descriptions, billing usage, pooler settings, and infrastructure fields.
* Improved read-replica connection handling, including read-only
connection strings.
* Updated storage configuration and capability handling to match current
settings.

* **API and Compatibility**
* Updated organization, project, storage, OAuth, billing, and
infrastructure data handling to match current API responses.
  * OAuth app creation and updates now require scopes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-09-11 12:17:49 +08:00
1966209483 chore(deps): upgrade vitest to v5 (#49994)
Upgrades Vitest from 4.1.4 to 5.0.0 across the monorepo, fixes the
handful of things v5 turned into hard errors, and drops the
`vi.clearAllMocks()` boilerplate that v5's `clearMocks` default makes
redundant.

**Changed:**
- `vitest`, `@vitest/ui`, `@vitest/coverage-v8` 4.1.4 → 5.0.0 (catalog)
- `vi.mock` calls that lived inside `beforeAll`/`beforeEach`/test bodies
moved to module scope (v5 throws on nested calls). Affects the Studio
and docs setup files and four Studio tests.
- `detectBrowser` test restores `navigator` via `vi.unstubAllGlobals()`
instead of assigning `global.navigator`, which now reaches jsdom's
getter-only property.
- `RowEditor.utils.test.ts` restores its `JSON.stringify` spy. It used
to leak a throwing mock for the rest of the file, which v5's coverage
provider now trips over. A later test in the same file had been
asserting the leak's side effect (valid JSON reported as invalid) and
now asserts the correct behavior.
- `@testing-library/jest-dom` 6.6 → 7.0.1. Its vitest type augmentation
resolves through a peer now, so it lands on each package's own `vitest`
instead of whichever copy pnpm hoisted. Fixes `toBeInTheDocument` type
errors in dev-tools after the reshuffle.
- `@testing-library/react` 16.0.0 → 16.3.3 for the React 19 peer range.
- `vite: catalog:` added to dev-tools, www, and common. Without it they
resolved a newer vite than the catalog pin, which forked a second vitest
instance in the lockfile. There's now one.
- ai-commands custom matcher types use v5's `Matchers<R, T>` form.
- 110 test files: `vi.clearAllMocks()` removed from
`beforeEach`/`afterEach` hooks, along with hooks that only did that and
the imports they left unused. Calls that also reset/restore mocks are
untouched. Second commit, mechanical.

**Added:**
- `.vitest/` to the root gitignore (v5 writes JSON/JUnit/HTML reporter
output there)

**Removed:**
- `vite-tsconfig-paths` catalog entry and deps. Vitest 5 resolves
tsconfig paths itself.

Release-age note: this sat in draft with a temporary
`minimumReleaseAgeExclude` entry for `vitest` and `@vitest/*` while
5.0.0 was inside the workspace's 3-day `minimumReleaseAge` window. That
window has closed, so the exclusion is gone and nothing bypasses the
release-age gate.

**Perf** (local, medians of 3 runs, same machine):

| Suite | v4.1.4 | v5.0.0 |
|---|---|---|
| studio | 144.1s | 141.7s (-2%) |
| studio `--coverage` | 156.9s | 146.4s (-7%) |
| ui-patterns | 6.27s | 5.07s (-19%) |
| ui `--coverage` | 3.35s | 2.14s (-36%) |
| www | 0.89s | 0.47s (-47%) |

Studio is dominated by jsdom environment setup per file, which v5
doesn't change. `vitest doctor` recommends keeping the current pool
config: the vm pools and `isolate: false` all break tests.

## To test

- `pnpm install --frozen-lockfile` succeeds with no
`minimumReleaseAgeExclude` entry for vitest.
- CI: Studio unit tests, ui, ui-patterns, www, docs, and typecheck/lint
should all be green. The lint ratchet was checked locally: warning
counts on touched Studio files are identical to master.
- `pnpm test:studio` locally passes with coverage (588 files, 6240
tests).
- Open a Studio test that uses `toBeInTheDocument` in your editor and
confirm no type errors on jest-dom matchers, in Studio and in
`packages/dev-tools`.
- Known pre-existing failures unrelated to this PR: one dev-tools test
(`getEventCountBadge` capped pill) fails on master too.


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

## Tests
- Improved test coverage for JSON validation and mobile navigation
behavior.
- Updated test setup, cleanup, environment configuration, and matcher
support across application and shared package suites.
- Removed obsolete coverage for alternate MCP transport selection.

## Chores
- Streamlined TypeScript path resolution and Vitest reporter output
handling.
- Updated testing libraries and Vitest tooling across documentation,
Studio, website, and shared packages.
- Added Vitest reporter output to ignored files.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2026-09-10 16:45:54 +08:00
Danny White 1131e3e2ce fix(ui): default Button variant to default instead of primary (#50160)
## What kind of change does this PR introduce?

Bug fix / design-system alignment for the legacy `Button` from `ui`.

## What is the current behavior?

Omitting `variant` on the legacy `Button` falls back to brand-green
`primary`. That makes accidental greens easy, and it is hard to spot the
real main action on busy pages.

## What is the new behavior?

- Legacy `Button` now defaults to neutral `default`
- Intentional primary CTAs (create, save, submit, marketing CTAs, and
matching `ButtonTooltip` usages) now set `variant="primary"` so their
appearance is unchanged
- Neutral actions that previously relied on the old fallback (cancel,
close, back, dashboard nav, and similar) become grey/white
- Design-system docs updated; regression tests cover the new default

`Button_Shadcn_` is unchanged. It already uses its own CVA default.

This is PR 1 of 2 in a stack. PR 2 drops now-redundant
`variant="default"` props.

## To test

Studio (http://localhost:8082):

- `/sign-in`: Sign in stays green
- Open a project → Database → Tables: New table stays green
- Auth → Users → Invite: Invite user stays green; Cancel / dismiss
controls stay neutral
- Project Settings → General: edit a field so Cancel and Save appear.
Cancel is neutral, Save is green

Design system (http://localhost:3003):

- Components → Button: default demo is neutral; primary demo is green;
featured preview is the default variant

Marketing (optional):

- www header: Start your project stays green; logged-in Dashboard is
neutral

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

- **Style**
- Buttons now default to a neutral style, while primary actions across
Studio, documentation, marketing pages, forms, dialogs, and error states
use prominent primary styling.
- Updated button examples and previews clarify the distinction between
default and primary variants.
  - Event registration now includes a directional arrow icon.

- **Tests**
- Added coverage confirming default button styling and explicit primary
styling behave as expected.
- Updated related test fixtures to use primary styling where
appropriate.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-10 11:23:17 +10:00
dc16371a47 feat(studio): configure BigQuery table layout (#49535)
## What kind of change does this PR introduce?

Feature. The last remaining piece of this PR's original scope, rebased
onto current `master`.

## What is the current behavior?

A BigQuery pipeline replicates every published table into a flat
destination table. There is no way to say how those tables should be
laid out in BigQuery, so partitioning and clustering have to be applied
by hand after the fact, and are lost whenever a destination table is
reset.

The rest of this PR's original scope has since merged separately:
#49841, #49842, #49843, #49844 and #49845. The branch now carries only
the table layout work, and adds nothing to `packages/api-types`. It
consumes the `table_options` contract that #49844 already brought in.

## What is the new behavior?

The BigQuery destination form gains a "Table layout" section under
Advanced settings. Every table in the selected publication appears as a
row, and expanding one reveals optional partitioning and clustering:

- Time-column partitioning, by hour, day, month or year
- Integer-range partitioning, with start, end and interval
- Ingestion-time partitioning
- Clustering, up to four columns

Rows are always present, so nothing implies a table can be excluded
here. A collapsed row summarises what is applied: `Not configured`,
`Daily by created_at`, `Integer range by id`, plus clustering counts.
`Not configured` is dimmed a step further so configured rows are what
the eye lands on in a long publication.

Notes on behavior:

- Partition columns are resolved from the published table's real
columns, filtered to the types BigQuery accepts for each partition mode.
- A row you expand but leave empty is dropped from the payload rather
than saved half-configured. Choosing a partition mode without a column
is a validation error, not a silent drop.
- Clear returns a row to `Not configured` and keeps it in the list.
Remove is reserved for stale configuration whose table has left the
publication.
- Updates send `null` to clear previously stored table options, since
omitting the property leaves the stored value unchanged.
- Layout applies when a destination table is first created or reset,
matching the backend.

Roughly 40% of the diff is tests. The bulk of the rest is four new files
under `DestinationForm/BigQuery`, which are all one feature. The three
commits are readable in order: types and payload builders, then the
columns query, then the UI.

## To test

Open a project's Database > Replication, then create or edit a BigQuery
pipeline.

1. Expand Advanced settings. "Table layout" lists every table in the
selected publication.
2. Expand a row, set Partition by to Time column and pick a column.
Collapse. The row reads `Daily by <column>`. Hit Clear. The row returns
to `Not configured` and stays in the list.
3. Set Partition by to Time column, leave Partition column empty,
collapse, and Save. The row explains "Select a partition column" in red
rather than saving and silently dropping it.
4. Expand a row and add clustering columns. The fifth is refused.
5. Switch publications and watch the loading state. The row list should
not jump size when it resolves.
6. Narrow the sheet. The integer range Start, End and Interval fields
should reflow rather than stay in three columns.


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

* **New Features**
* BigQuery replication destinations now support per-table layout
settings.
* Configure partitioning by time column, integer range, or ingestion
time.
  * Configure up to four clustering columns per table.
* View available columns and validation feedback while editing table
layouts.
* Table settings are preserved when editing destinations and cleaned up
when publications change.

* **Bug Fixes**
* Improved handling of invalid, unavailable, or removed table and column
configurations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-09 16:56:12 +10:00
Danny White 6a4cbefbcf feat(ui): align combobox trigger with select styling (#49665)
## What kind of change does this PR introduce?

Bug fix and shared UI primitive.

## What is the current behaviour?

In **Database > Replication > Add destination**, the searchable
**Publication** field uses a double chevron and button styling. It looks
inconsistent beside the **Initial sync** select, which uses a single
chevron and the standard select surface.

The shared multi-select trigger uses the same inconsistent double
chevron. These differences are easy to repeat because searchable
comboboxes do not have a dedicated trigger that shares the select
styling.

## What is the new behaviour?

- Adds `ComboboxTrigger` with the same shared styling as `SelectTrigger`
- Uses a fixed single down chevron so combobox and select triggers
cannot drift
- Migrates the Studio **Database > Replication > Add destination >
Publication** field to `ComboboxTrigger`
- Updates `MultiSelectorTrigger` to replace `ChevronsUpDown` with the
same fixed `ChevronDown`, including **Connect > MCP > Feature groups**
in Studio
- Updates the canonical design-system combobox examples
- Leaves `Button` unchanged, so adopting combobox styling is explicit

| Before | After |
| --- | --- |
| <img width="1256" height="448" alt="CleanShot 2026-09-09 at 10 21
32@2x"
src="https://github.com/user-attachments/assets/bb7a6056-0b4e-4cb4-8dce-e92fa4f5afe7"
/> | <img width="1256" height="448" alt="CleanShot 2026-09-09 at 10 21
11@2x"
src="https://github.com/user-attachments/assets/860a06b9-617d-4d94-ac98-944316e9fdc3"
/> |
| <img width="1210" height="520" alt="CleanShot 2026-09-09 at 10 58
28@2x"
src="https://github.com/user-attachments/assets/e916d3a2-6a75-40eb-965a-56e0694ba447"
/> | <img width="1210" height="520" alt="CleanShot 2026-09-09 at 10 57
57@2x"
src="https://github.com/user-attachments/assets/c5f1b8ff-8083-47b8-8242-59116d085c00"
/> |

## Left for incremental migration

These existing Studio comboboxes still use bespoke button triggers and
will move to `ComboboxTrigger` in focused follow-up changes:

- **Database > Backups > Point in time > Timezone**
- **Authentication > Third-party auth > AWS region**
- **Account > Preferences > Timezone**
- Shared schema and function selectors

See https://github.com/supabase/supabase/pull/50157.

The organisation and project switchers in the top navigation are
intentionally out of scope. They are context switchers rather than
form-field comboboxes.

## To test

### Studio callsites

On the [Studio
preview](https://studio-staging-git-dnywh-featcombobox-trigger-supabase.vercel.app):

1. Open **Database > Replication > Add destination**.
2. Compare **Publication** with **Initial sync**. Both should use a
single down chevron and the same closed-field surface, border, sizing,
and hover treatment.
3. Open **Publication**, search for an option, and select it. The
popover should close and the selected publication should be shown.
4. Open **Connect** from the project header, select **MCP**, and check
**Feature groups**. Its multi-select trigger should use a single down
chevron.

### Design system

1. Check the [combobox
examples](https://design-system-git-dnywh-featcombobox-trigger-supabase.vercel.app/design-system/docs/components/combobox).
2. Check the [multi-select
examples](https://design-system-git-dnywh-featcombobox-trigger-supabase.vercel.app/design-system/docs/fragments/multi-select).
3. Both trigger types should use a single down chevron.
2026-09-09 13:44:11 +10:00
Danny WhiteandJoshen Lim 4a5db160be feat(studio): extract shared zod number input helpers (#50102)
## What kind of change does this PR introduce?

Refactor. Extracts zod number input preprocessing into a shared Studio
helper and migrates existing call sites.

## What is the current behavior?

Number input clearing logic for controlled `type="number"` fields is
duplicated across Studio forms. The pipeline destination form had local
helpers, while Auth and settings forms inline the same `z.preprocess`
pattern.

## What is the new behavior?

Adds `apps/studio/lib/forms/zod-number-input.ts` with:

- `requiredNumberInputSchema` for required `z.number()` fields (`''` →
`NaN`)
- `optionalNumberInputSchema` for optional number fields (`''`/`null` →
`undefined`)
- `preprocessEmptyNumberInput` for `z.coerce.number()` schemas

Migrates:

- Pipeline destination form
- Connection pooling settings
- Auth provider validation (email and SMS OTP fields)
- SMTP settings
- MFA settings
- Protection settings

## To test

1. Open **Authentication > Providers > Email**, clear **Email OTP
expiration** or **Minimum password length**, and confirm the field stays
empty and shows validation on save.
2. Open **Authentication > Providers > Phone**, select a provider, clear
**SMS OTP Expiry**, and confirm validation still works.
3. Open **Authentication > Emails > SMTP settings**, clear **Port** or
**Rate limit**, and confirm validation on save.
4. Open **Authentication > Multi-factor authentication**, clear **Max
enrolled factors** or **Phone OTP length**, and confirm validation on
save.
5. Open **Database > Replication**, start a new pipeline, select
**BigQuery**, expand **Advanced settings**, clear a required numeric
field, and confirm it stays empty until filled.
6. (Optional, hosted non-HA projects only) Open **Database > Settings**,
scroll to **Connection pooling**, clear **Connection pool size**, and
confirm the value does not snap back before save.

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

* **Bug Fixes**
* Improved handling of empty numeric fields across authentication, SMTP,
database replication, and connection pooling settings.
* Optional numeric settings can now be cleared without triggering
unnecessary validation errors.
* Required numeric fields continue to display appropriate validation
errors when left incomplete.
* Standardized validation behavior for OTP settings, password
requirements, SMTP limits, replication configuration, and pool sizing.
* Refined protection settings to focus on CAPTCHA and leaked-password
options.
* **Tests**
  * Added coverage for empty and optional numeric input behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-08 18:26:41 +08:00
Danny White 66a748cdd1 fix(ui): restore accordion trigger layout (#50114)
## What kind of change does this PR introduce?

Bug fix. Follow-up to #49660.

## What is the current behavior?

`AccordionTrigger` adds horizontal padding at the shared primitive
level. This shifts content at call sites that already own their spacing.
In the Studio Advanced settings sections, padding around the whole
accordion also constrains the trigger and its hit area instead of
letting it fill the row.

## What is the new behavior?

The shared trigger no longer adds horizontal padding and its header
explicitly fills its container. Both Studio Advanced settings sections
now apply their padding inside the full-width trigger and content,
keeping the text aligned while extending the focus outline and hit area
across the row.

The inset focus treatment from #49660 is unchanged.

| Before | After |
| --- | --- |
| <img width="1334" height="286" alt="CleanShot 2026-09-08 at 16 18
57@2x"
src="https://github.com/user-attachments/assets/3a057b45-1eb4-4928-ae69-2d636b0c4678"
/> | <img width="1302" height="278" alt="CleanShot 2026-09-08 at 16 18
12@2x"
src="https://github.com/user-attachments/assets/0454493e-4fbc-4ad2-a9fd-1b9dc1d486dc"
/> |

## To test

### Studio replication destination

1. Open the [Studio staging
preview](https://studio-staging-git-dnywh-fixaccordion-trigger-width-supabase.vercel.app)
and select a project with Pipelines enabled.
2. Go to **Database > Replication**. Under **Destinations**, click **Add
destination**.
3. Tab to **Advanced settings** and press Enter to expand it.
4. Confirm the text aligns with the form content, the focus outline
spans the full row between the sheet edges, and clicking near the far
right of the row toggles it.

### Studio access-token permissions

1. In the [Studio staging
preview](https://studio-staging-git-dnywh-fixaccordion-trigger-width-supabase.vercel.app),
go to **Account > Access Tokens**.
2. Click **Generate new token** and scroll to **Permissions**.
3. Tab to any permission category, then click near the far right of its
row.
4. Confirm the focus outline fills the category row, the label keeps its
existing inset, and the full row toggles the category.

### Pricing FAQs

1. Open the [Pricing
preview](https://zone-www-dot-com-git-dnywh-fixaccordion-trigger-width-supabase.vercel.app/pricing)
and scroll to **Frequently asked questions**.
2. Tab to any question, then click near the far right of its row.
3. Confirm the question has not gained extra horizontal inset and the
full row remains interactive.

### Design-system Accordion

1. Open the [design-system Accordion
preview](https://design-system-git-dnywh-fixaccordion-trigger-width-supabase.vercel.app/docs/components/accordion).
2. Tab through the three accordion triggers and toggle each one.
3. Confirm each focus outline fills its row, with no extra horizontal
padding around the label.
2026-09-08 16:24:49 +10:00
Danny White 3418975b70 feat(studio): configure publication partition handling (#49845)
## What kind of change does this PR introduce?

Small Pipelines feature. Stacked on #49844.

## What is the current behavior?

New publications always publish changes from partitioned tables through
their parent table. The creation sheet does not expose the v2 API option
that controls this behavior.

## What is the new behavior?

Adds a default-on Publish partitions as the parent table checkbox to the
publication sheet. Turning it off submits publish_via_partition_root as
false so each partition can appear as a separate destination table.

## To test

1. Open the pipeline creation sheet and choose to create a publication.
2. Confirm Publish partitions as the parent table is selected by
default.
3. Create a publication and confirm publish_via_partition_root is true.
4. Repeat with the option cleared and confirm publish_via_partition_root
is false.
5. Confirm the selected tables and publication name are unchanged by the
option.

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

## Summary by CodeRabbit

- **New Features**
- Added a “Publish partitions as the parent table” option when creating
publications.
- The option is enabled by default and can be turned off before
submitting the publication.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-08 14:03:18 +10:00
Danny WhiteandJoshen Lim 8dd97d75aa refactor(studio): use v2 replication publication APIs (#49844)
## What kind of change does this PR introduce?

Studio data-layer migration.

## What is the current behavior?

Studio loads complete publication details through the original bulk
endpoint and creates publications by executing SQL against the source
database. Publication and source-table data use names where stable table
IDs are available.

## What is the new behavior?

Uses the v2 publication-name, publication-detail, publication mutation,
and source-table endpoints. The existing creation sheet continues to
behave the same, including publishing partition changes through the
parent table by default. Initial-sync selection and Analytics Bucket
associations now consume the selected publication detail. Generated
platform API types and their required nullability updates are included.

The generated Platform contract accounts for roughly 10,000 changed
lines in this PR.

## Dependency

Depends on the v2 source table, table column, and publication endpoints
from
[supabase/platform#37505](https://github.com/supabase/platform/pull/37505),
which are deployed to production.

## To test

1. Open the pipeline creation sheet and select an existing publication.
2. Create a publication with mixed-case schema and table names, then
confirm the table names are shown while stable IDs are submitted.
3. Exercise all four initial-sync policies, including selecting
individual tables.
4. Reopen the publication and table selectors and confirm they refresh
without replacing populated options.
5. Edit and delete a publication.
6. Open an Analytics Bucket associated with a pipeline and confirm its
publication tables resolve correctly.
7. Confirm unlimited WAL retention renders as Unlimited on pipeline
status.


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

- **New Features**
- Improved replication publication setup with on-demand table loading,
refresh controls, clearer table labels, and streamlined publication
selection.
- Publication creation and updates now use the latest replication API
and table-based configurations.
- Added clearer handling for tables removed from publications, including
stale-selection warnings.

- **Bug Fixes**
- Prevented table selections from carrying over when switching
publications.
- Improved replication status displays when lag or WAL metrics are
unavailable.
- Updated replication deletion and table management for the latest API
behavior.

- **Tests**
- Expanded coverage for publication creation, table selection, stale
tables, loading states, and replication metrics.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-08 11:37:59 +10:00
Danny WhiteandJoshen Lim 282a2a22cf fix(studio): allow pipeline number inputs to be cleared (#50078)
## What kind of change does this PR introduce?

Bug fix for the pipeline destination form.

## What is the current behavior?

Clearing a numeric field under Advanced settings restores its previous
value immediately, so users cannot replace the value normally.

## What is the new behavior?

Numeric fields use an empty string as their controlled blank value while
editing, so users can clear an existing value before entering its
replacement. Existing field-specific validation messages are preserved
for invalid or empty required values. Maximum staleness remains optional
and can be left blank.
Adds component and schema coverage for all five numeric Advanced
settings fields, including the BigQuery-only fields.

## To test

1. Open Database > Replication and start a new pipeline.
2. Select BigQuery and expand Advanced settings.
3. Clear each numeric field and confirm it can be edited without
reverting to its previous value. Required fields may show their existing
validation message while empty.
4. Enter a replacement value such as `5` and confirm the field accepts
it.
5. Leave a required numeric field blank and confirm the existing
field-specific validation message appears.

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

- **Bug Fixes**
- Improved validation for replication destination settings, with clearer
errors when required numeric fields are left empty.
- Validation now updates immediately when numeric values are cleared or
corrected.
  - BigQuery connection pool size must be greater than zero.
  - Empty maximum staleness values are accepted and handled correctly.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-08 11:32:46 +10:00
Danny WhiteandJoshen Lim a351a36e9b refactor(studio): centralise replication payload builders (#49842)
## What kind of change does this PR introduce?

Studio data-layer refactor.

## What is the current behavior?

Pipeline creation, editing, and validation build similar destination and
pipeline payloads separately. The duplicated mappings rely on type
assertions and can drift between actions.

## What is the new behavior?

Uses shared typed builders for create, update, and validation payloads
across the existing destinations. Update payloads continue to omit blank
secrets, while create payloads preserve their current values. This PR
does not add table partitioning configuration.

## To test

This is a data-layer refactor. No visible behaviour should change.

1. Open **Database > Replication** and click **Start a new pipeline**.
2. Select **BigQuery**, or any other enabled destination.
3. Edit a few non-secret fields and expand **Advanced settings**.
4. Confirm the form remains usable and no runtime errors appear.

Create, update, validation, and secret-handling behaviour is covered by
the focused tests and CI. Deploy previews and fresh local projects do
not have the existing destinations or credentials needed to exercise
those paths manually.

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

* **Bug Fixes**
* Improved replication destination configuration handling during
creation, updates, and validation.
* Applied consistent configuration mapping across supported destination
types.
* Ensured blank secret values are omitted during updates while retained
when creating destinations.
* Standardized table synchronization defaults when no specific setting
is provided.
* **Tests**
* Added coverage for BigQuery configuration mapping and secret handling.
  * Updated DuckLake tests for destination updates.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-07 15:02:09 +08:00
Gildas Garcia 6e8b43d7b4 fix: improve useRefreshOnOpen hook (#49886)
## Problem
The `useRefreshOnOpen` returns a new object each time it runs, making
the `useCallback` useless.

## Solution
Wrap the function content in `useMemo` instead

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

* **Refactor**
* Improved refresh handling for the replication destination form when it
is opened.
  * Existing refresh behavior remains consistent and reliable.
* No user-visible changes to functionality, controls, or configuration
options.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-03 11:36:40 +10:00
Danny White 442e40a30b refactor(studio): simplify pipeline advanced settings (#49841)
## What kind of change does this PR introduce?

Small Studio UI refactor.

## What is the current behavior?

BigQuery-only fields are already conditionally rendered, but repeat that
scope in badges. Number inputs also convert non-empty invalid values
directly with Number().

## What is the new behavior?

Removes the redundant badges, keeps number fields empty instead of
storing NaN, and gives the invalidated-slot menu consistent viewport
collision spacing.

| Before | After |
| --- | --- |
| <img width="1238" height="364" alt="CleanShot 2026-09-02 at 14 40
02@2x"
src="https://github.com/user-attachments/assets/8c9b0c30-250e-422f-af3b-70f84e439459"
/> | <img width="1252" height="358" alt="CleanShot 2026-09-02 at 14 40
22@2x"
src="https://github.com/user-attachments/assets/8b3c6837-2c84-4c0d-ae07-b6b8b7a50cfe"
/> |

## To test

1. Open the pipeline creation sheet and expand Advanced settings.
2. Confirm connection pool size and maximum staleness appear only for
BigQuery, without BigQuery-only badges.
3. Clear and re-enter the numeric advanced settings.
4. Open Invalidated slot behavior near the viewport edge and confirm the
menu remains visible.

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved handling of numeric input in advanced replication settings,
including empty and invalid values.
  * Adjusted the invalidated slot menu positioning for better display.

* **UI Improvements**
* Simplified labels for connection pool size and maximum staleness
settings.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-03 10:09:44 +10:00
Danny White 924b3f5793 feat(ui-patterns): add async selection feedback (#49843)
## What kind of change does this PR introduce?

Shared UI pattern and Studio UX improvement.

## What is the current behavior?

Async selectors use bespoke loading and error layouts. Some replace the
entire field while fetching, and opening a selector does not
consistently refresh its options.

## What is the new behavior?

Adds shared loading, error, and empty states for Select, command, and
MultiSelector lists, including a persistent polite live region and
reduced-motion support. Analytics Bucket and DuckLake selectors keep
their controls in place, retain populated options during background
refreshes, and refresh when reopened.

## To test

Open the [Replication
preview](https://studio-staging-git-dnywh-featasync-selection-feedback-supabase.vercel.app/dashboard/project/_/database/replication?destinationType=Analytics%20Bucket).
The destination sheet should already be open on **Analytics Bucket**.

You do not need to create a bucket, configure a destination, or start a
pipeline. Open **Select a bucket**, then review these outcomes:

1. **The trigger stays put.** Opening the picker must not replace the
form field with a full-width loading placeholder.
2. **Loading belongs inside the menu.** While options are fetched, the
open menu shows a compact skeleton list.
3. **No resources has a clear explanation.** If the project has no
Analytics Buckets, the menu says **No buckets available**. It still
offers **Create a new bucket** beneath that message.
4. **Existing options do not disappear on refresh.** If the project does
have buckets, close and reopen the picker. Its current options remain
visible while the refresh happens in the background, rather than
flashing back to skeletons.
5. **The pattern is consistent.** If convenient, select a bucket and
open the namespace or access-key picker. The same in-menu loading,
empty, and error treatment applies there too.

The deterministic request-error and reduced-motion cases are covered by
focused unit tests because the deploy preview cannot reliably force
those states.
2026-09-02 14:25:03 +10:00
Danny White 19e3844a0e feat(studio): upload BigQuery pipeline credentials (#49668)
## What kind of change does this PR introduce?

Feature improvement for BigQuery pipeline creation and editing.

## What is the current behavior?

Users must paste the complete service-account JSON into a text area.

## What is the new behavior?

Users can paste, upload, or drag and drop a service-account JSON file.
Imported credentials remain editable, and unreadable or oversized files
show an inline form error.

## To test

1. Open a project, then go to Database → Replication and select Add
destination.
2. Select BigQuery.
3. Under Service account key, select Upload JSON file and choose a
service-account `.json` file.
4. Confirm its contents appear in the editable text area.
5. Drag and drop a JSON file onto the same field and confirm it replaces
the contents.
6. Confirm pasting credentials manually still works.

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

* **New Features**
  * Added support for uploading BigQuery service account key JSON files.
  * Added drag-and-drop support for service account key files.
  * Updated guidance to clarify that keys can be pasted or uploaded.
  * Constrained the service account key field to 5,000 characters.

* **Bug Fixes**
  * Added clear validation when keys exceed the character limit.
* Improved handling of unreadable files while preserving the existing
key.
  * Improved editing of imported service account key content.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-28 17:37:31 +10:00
Danny White 02bb456647 fix(studio): clarify pipeline form guidance (#49666)
## What kind of change does this PR introduce?

UI copy improvement for the current pipeline creation sheet.

## What is the current behavior?

Several pipeline fields use ambiguous labels or omit useful guidance.
Validation messages also use inconsistent punctuation.

## What is the new behavior?

- Explains how the pipeline name is used
- Clarifies invalidated replication slot behaviour
- Explains that BigQuery maximum staleness is optional
- Makes pipeline validation messages consistent

## To test

1. Open a project, then go to Database → Replication and select Add
destination.
2. Confirm Name explains that it identifies the pipeline in Supabase.
3. Expand Advanced settings and confirm Invalidated slot behaviour uses
Block startup and Recreate slot.
4. Select BigQuery and confirm Maximum staleness explains that leaving
it blank gives the freshest results.
5. Submit incomplete destination settings and confirm validation
messages end with full stops.

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

* **New Features**
* Replication slot behavior options now use clearer labels: “Block
startup” and “Recreate slot.”
* Added guidance explaining that the pipeline name identifies the
pipeline in Supabase.
  * Improved the BigQuery maximum-staleness description and display.

* **Bug Fixes**
* Standardized replication destination validation messages with
consistent punctuation.
  * Clarified the ClickHouse HTTPS validation message.
  * Updated validation tests to reflect the improved error messages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-28 17:37:08 +10:00
Danny White 3945234b9e feat(studio): polish replication destination sheet form (#49581)
## What kind of change does this PR introduce?

Feature (sheet polish, no wizard).

## What is the current behavior?

Edit destination sheet uses a disabled region Select, weaker BigQuery
JSON validation messaging, and a name field that password managers may
fill.

## What is the new behavior?

- Read-only pipeline region field with flag, display name, region code,
and destination-specific hint
- Clearer BigQuery service-account JSON validation
- Destination name ignores password managers (`data-1p-ignore` and
related attrs)
- Advanced settings can optionally group fields (defaults keep full
accordion for the sheet)

Independent of the [create-pipeline
wizard](https://github.com/supabase/supabase/pull/49243). Safe to merge
on its own.

| Before | After |
| --- | --- |
| <img width="1024" height="759" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/98360d10-3efd-4f77-9645-2f054bb8caab"
/> | <img width="1024" height="759" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/fdb55904-44f5-4fdf-a750-d4b7f1602b4e"
/> |
| <img width="1024" height="759" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/cd40e4c3-5653-467b-a3b6-c0c497f9c500"
/> | <img width="1024" height="759" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/d4115dab-fd94-411c-bbc4-ee69e22436d6"
/> |

## To test

1. Open a project → Database → Replication
2. Edit an existing destination
3. Confirm **Pipeline region** is read-only (not a combobox) and shows
flag + region name/code
4. Open Advanced settings and confirm fields still appear
5. For BigQuery: paste invalid service-account JSON and confirm a clear
validation message

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

- **New Features**
- Added grouped advanced settings for connection and data configuration.
- Added a read-only pipeline region display with destination-specific
guidance.
  - Destination names now receive focus automatically when forms open.

- **Bug Fixes**
- Improved BigQuery credential validation, including malformed or
missing service-account keys.
- Password-manager autofill is now suppressed for destination name
fields.

- **Tests**
- Added coverage for BigQuery validation and pipeline-region display
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-27 10:17:36 +10:00
Danny White 5f50338a2f fix(studio): keep region flags visible on light surfaces (#49517)
## What kind of change does this PR introduce?

Studio interface fix.

## What is the current behavior?

Region flags with light backgrounds, such as Japan, can disappear
against light Studio surfaces. Flag rendering is also repeated across
region selectors and infrastructure views.

## What is the new behavior?

Region flags use a shared `RegionFlag` component with the existing small
radius and a subtle 1px border. The treatment is applied consistently
across project creation, replication, read replicas, infrastructure, and
Edge Function observability.

| Before | After |
| --- | --- |
| <img width="746" height="246" alt="CleanShot 2026-08-25 at 14 01
07@2x"
src="https://github.com/user-attachments/assets/5ccffccd-f253-47ca-a587-e97d1e8306a8"
/> | <img width="746" height="234" alt="CleanShot 2026-08-25 at 14 09
20@2x"
src="https://github.com/user-attachments/assets/9d59f7f6-4364-4c2c-8b97-a9673616736a"
/> |

## To test

- Open the new project flow and inspect the selected region and region
menu. Confirm light flags remain visible without changing size or aspect
ratio.
- Open Database Replication and inspect region flags in the diagram and
destination form.
- Open `/project/<ref>/settings/infrastructure` and inspect flags in the
topology, map, and read replica details.
- Open Edge Function observability and inspect the region filter
options.


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

* **UI Improvements**
* Standardized region flag displays across project creation,
replication, infrastructure, read replica, and observability views.
* Region flags now use consistent styling, rounded borders, and
rendering throughout the Studio interface.
* Improved visual consistency for selected regions, database nodes,
tooltips, and region options.
* Decorative flags in observability views are handled appropriately for
assistive technologies.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-25 16:25:12 +10:00
Victor Farazdagi 3bc52101ee (docs/pipelines): early access destinations (#49304)
## What kind of change does this PR introduce?

Docs update


## Summary

- Add Early Access setup and reference guides for ClickHouse, DuckLake,
and Snowflake.
- Update Pipelines navigation and shared documentation with
destination-specific data models, source requirements, schema-change
support, and recovery behavior.
- Keep all three destinations organization-gated. DuckLake is documented
only as a Pipelines replication destination i.e. query compute remains
external and this is not a Warehouse launch.

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

* **New Features**
* Added ClickHouse, DuckLake, and Snowflake as Early Access Pipelines
destinations.
  * Added BigQuery as a managed destination.
* Added destination navigation and setup guides covering configuration,
replication behavior, schema changes, type mappings, troubleshooting,
and monitoring.

* **Documentation**
* Clarified destination availability, regional guidance, requirements,
limitations, and processing behavior.
* Documented destination-specific schema-change support, table identity
requirements, reset behavior, and CDC replication modes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-24 14:44:54 +03:00
Danny White 5f9ce727c0 fix(ui): systematise control surface fills and hover borders (#48887)
## What kind of change does this PR introduce?

Bug fix / design-system token hygiene for form and selector chrome.

## What is the current behavior?

After opaque default-button fills, text fields, selects, and selector
tiles drifted apart: inputs and selects mixed ad-hoc washes, hover
borders bounced between `border-stronger` / `border-foreground-muted`,
invalid fields had no hover step, and composites like InputGroup leaked
inner hover borders.

Follow-up to #48837 (opaque button fills) where Select rest still felt
darker than Input on forms such as scoped access tokens.

## What is the new behavior?

Named control roles and one interactive border:

| Role | Fill | Rest border | Hover / focus / open |
| --- | --- | --- | --- |
| Field (sunk) | `bg-field` | `border-control` | `border-control-hover`
|
| Raised control | `bg-control-raised` | `border-strong` |
`border-control-hover` |
| Overlaying action | card → popover | `border-strong` |
`border-control-hover` |
| Invalid field | `bg-destructive-200` | `border-destructive-400` |
`border-destructive` |

- `--field` / `--control-raised` / `--border-control-hover` live in
`semantic.css` (source of truth for roles; README points there)
- Input / Textarea / InputGroup / legacy TextArea use the field ladder
(incl. invalid hover)
- Select and empty MultiSelect use raised; filled MultiSelect sinks to
field
- Default + dashed Button, CommandMenu trigger, and radio
card/stacked/large use `border-control-hover`
- Studio selector tiles aligned: Connect mode, role impersonation,
DuckLake modes, compute “Contact us”

| Before and After |
| --- |
| <img width="1576" height="759" alt="Access Tokens Account Supabase"
src="https://github.com/user-attachments/assets/4bbe8b2b-a31a-4d63-80ba-04a1a8a5609d"
/> |
| <img width="1576" height="759" alt="Access Tokens Account Supabase"
src="https://github.com/user-attachments/assets/92271223-4103-4cc6-a7c0-9e4ff71cce30"
/> |

## Additional context

`--control-raised` aliases `--card` today (role name so fill can diverge
later). Rest `border-control` / `border-strong` both still map to
`--input` via compat; the shared interactive step is
`--border-control-hover`.

## To test

1. **[Account → Access
Tokens](https://studio-staging-git-dnywh-fixcontrol-surface-tokens-supabase.vercel.app/dashboard/account/tokens)**
Open Generate / New scoped token. Side-by-side Input, Select,
RadioGroupStacked, MultiSelect. Confirm sunk vs raised fills, shared
hover border, MultiSelect flips to sunk once a value is selected. Leave
a required field empty to check invalid rest → hover → focus.

2. **[Org →
Projects](https://studio-staging-git-dnywh-fixcontrol-surface-tokens-supabase.vercel.app/dashboard/org/_)**
Hover the dashed Status filter. Hover default / filled filter buttons
when active. Confirm hover/open borders match.

3. **[Project →
Connect](https://studio-staging-git-dnywh-fixcontrol-surface-tokens-supabase.vercel.app/dashboard/project/_)**
Open Connect from the header. Mode grid tiles: hover + selected borders
match radio cards (no old muted-foreground ring).

4. **[Project →
Compute](https://studio-staging-git-dnywh-fixcontrol-surface-tokens-supabase.vercel.app/dashboard/project/_/settings/infrastructure)**
(optional)
   Compute size radios + “Contact us” tile hover.
2026-08-18 16:54:25 +10:00
Riccardo Busetti c3742ba07f ref(pipelines): Align handling of credentials (#48896) 2026-08-10 14:40:02 +02:00
Danny WhiteandJoshen Lim 7a77760a10 fix(studio): confirm before discarding dirty replication destination forms (#48522)
## What kind of change does this PR introduce?

Bug fix (dirty form dismissal for Replication destination sheets), plus
small docs/skill updates so agents pick up the existing modality
pattern.

## What is the current behavior?

Closing the Add/Edit destination sheet (Cancel, Escape, or backdrop)
discards in-progress form state with no confirm. Same for the nested
Create publication sheet.

## What is the new behavior?

Dirty closes go through `useConfirmOnClose` +
`DiscardChangesConfirmationDialog`, matching other Studio sheets.
Successful submit still closes without prompting.

Also: skills + `forms.mdx` now point at Modality “Dirty form dismissal”.

| After |
| --- |
| <img width="1024" height="759" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/6f568a2a-c76b-442a-b592-d638bb36adc4"
/> |

### How to test

1. Studio → Database → Replication → **Add destination** (any pipelines
type with access).
2. Change a field so the form is dirty.
3. Try Cancel, Escape, and backdrop click → discard dialog appears;
**Keep editing** stays open; **Discard changes** closes.
4. Submit successfully with a valid config → sheet closes with no
discard dialog.
5. Repeat for **Edit destination** from a destination row menu.
6. Optional: Add destination → create a new publication from the
publication picker → dirty that nested sheet and dismiss the same way.
7. Optional: Add destination → Read Replica → change region → dismiss →
discard dialog; deploy still closes without prompting.

## Additional context

Sheet owns the close guard; forms report dirty via a ref because RHF
lives in the child. Nested `NewPublicationPanel` wires the guard
locally.

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

- **New Features**
- Added unsaved-changes tracking to replication destination and
publication forms.
- Added confirmation prompts before closing forms with unsaved changes
via Cancel, Escape, or backdrop dismissal.
- Forms now reset appropriately after successful submission or confirmed
dismissal.

- **Documentation**
- Updated form and UI pattern guidance to document dirty-form dismissal
behavior for sheets and dialogs.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-08-03 10:00:41 +10:00
Danny WhiteandJoshen Lim 205527c716 feat(studio): tune up replication page layout and empty state (#48265)
## What kind of change does this PR introduce?

UI polish for Database → Replication: empty state, page layout, diagram
containment, filter actions, and destination sheet copy.

## What is the current behavior?

- Empty destinations use a custom dashed box with generic copy.
- The diagram is full-bleed with `border-y`.
- Page chrome still uses legacy Scaffold wrappers and a long header
description that duplicates the empty state.
- Filter-row “Add destination” is a default button ahead of secondary
actions; Usage always shows.
- Local ETL warning sits on the page list.
- Destination sheet title/helper/access copy is more verbose; Type
helper sits beside the label.

## What is the new behavior?

- Empty state uses `EmptyStatePresentational` with clearer CTA copy;
toolbar “Add destination” is primary at the end of the filter row;
empty-state CTA stays default.
- Usage only appears when there is at least one Pipelines destination.
- Page uses `PageHeader` / `PageContainer` / `PageSection`, with a short
header: “Read replicas and analytics pipelines”.
- Diagram sits in a rounded bordered frame inside the page container
(same treatment as project overview).
- Local ETL warning shows in the add-destination sheet for Pipelines
types only, without blocking the form; Type + warning scroll with the
sheet body.
- Type helper sits under the dropdown as one flowing paragraph (“Cannot
be changed after creation…” plus shortened stage notice).
- Sheet title is “Add destination”; close only fires on dismiss; Lucide
icons (e.g. Snowflake) use consistent stroke width.

| Before | After |
| --- | --- |
| <img width="1479" height="930" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/a3caf0ba-ed1a-4659-bdef-f66b67e85be4"
/> | <img width="1479" height="930" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/d5a82641-a316-4577-9480-959346994c40"
/> |
| <img width="1479" height="930" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/4f956e26-b8d4-4653-a60e-ceca7ec1e070"
/> | <img width="1479" height="930" alt="Replication Database Chisel
Toolshed Supabase"
src="https://github.com/user-attachments/assets/a72461ab-dea9-48a6-ab88-852a12ac80a5"
/> |

### Test plan

- [x] Open **Database → Replication** with no replicas/destinations:
empty state, primary filter-row Add destination, default empty-state Add
destination, no Usage button.
- [x] Confirm header→diagram and diagram→filter spacing feel even;
filter→empty state/table stays tight (`space-y-4`).
- [x] Confirm diagram is contained (rounded border), not full-bleed.
- [x] Add a Pipelines destination (or use a project that has one): Usage
appears; table still works; search “no results” still works.
- [ ] Open **Add destination**: title “Add destination”; Type helper
under the dropdown; Read Replica has no local warning; Pipelines type
shows local warning without hiding fields (when ETL isn’t set up
locally).
- [ ] Without Pipelines access: request-access panel shows “alpha” copy
and “Request alpha access”.
- [ ] Spot-check dark/light themes.

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-07-31 06:20:38 +10:00
Joshen Lim fcfb0f0222 Refactor all usage of form.watch to either useWatch or subscribe (#48436)
## Context

Replaces all usage of `form.watch()` to use `useWatch` instead + follows
the "name what you watch" convention as specified in the react-hook-form
skills.

There's also a small refactor in `SmtpForm.tsx` which removes the
unnecessary use of a `useState` to track if SMTP is enabled or not

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

* **Improvements**
* Updated many Studio forms to watch specific fields more precisely,
improving live UI updates for previews, warnings, conditional sections,
and validation messages.
* Enhanced responsiveness across settings, authentication, billing,
storage, integrations, and support flows while keeping save/update
behavior the same.
* **Refined Experiences**
* Improved the analytics table creation flow with tighter, enum-based
column type validation and structured, type-specific column options.
* **Preserved Behavior**
* Maintained existing permission checks, submission flows, and
account-management workflows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-30 11:45:40 +08:00
Alaister YoungandAlaister Young ca2b50a0a7 chore(ui-patterns): collapse the admonition shim into ui-patterns/Admonition (#48377)
Follow-up to #48344: collapses the two resolution paths for the
Admonition module into one.

`src/admonition.tsx` was a back-compat shim re-exporting
`src/Admonition/`. Two ways to resolve one module is exactly what
produced the macOS self-import bug fixed in #48344, and the local
typecheck errors that #48374 worked around. This removes the shim and
standardizes on the PascalCase subpath, matching every other export in
the package.

**Changed:**

- Codemodded all 246 `ui-patterns/admonition` imports to
`ui-patterns/Admonition` (240 `.tsx`, 5 `.mdx`, 1 `.ts` across studio,
docs, www, design-system, and lite-studio)
- Pointed the 5 internal `'../admonition'` imports back at the
`'../Admonition'` directory

**Removed:**

- `packages/ui-patterns/src/admonition.tsx`, and its `./admonition`
entry in the exports map (regenerated with `pnpm gen:exports`)

## To test

- `grep -r "ui-patterns/admonition" --include='*.ts*'` → no hits
- `pnpm test:case-hazards` → passes
- `pnpm typecheck` → all 15 tasks green
- `pnpm --filter studio run lint:ratchet` → passes
- `pnpm --filter ui-patterns vitest run src/Admonition` → 11 tests pass

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

## Summary by CodeRabbit

* **Bug Fixes**
* Standardized Admonition component imports across the application and
documentation.
* Improved compatibility with case-sensitive environments by using the
canonical component path.
  * Removed the legacy Admonition import entry point.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-07-29 00:48:56 +08:00
Riccardo Busetti 6f8fe470a6 ref(pipelines): Update pricing descriptions given new egress calculation (#48241) 2026-07-27 12:52:37 +02:00
b2b150fa3c feat(pipelines): Add UI selector for choosing which tables to skip copy of (#47808)
## Summary

Adds initial-copy scoping to Pipelines in Studio. Users can copy all
existing rows, skip all initial copies, copy only selected publication
tables, or skip selected table copies. All publication tables continue
streaming new changes regardless of the initial-copy policy.

The policy now round-trips through create, edit, validation, and the
generated Management API contract. Initial-copy estimates and
table-restart confirmations use the same scope. Edit requests also
preserve redacted credentials and pipeline settings that Studio does not
own.

This completes the Studio layer of the [ETL API
change](https://github.com/supabase/etl/pull/897) and [Management API
change](https://github.com/supabase/platform/pull/35479).

## Screenshots

### Selector

<img width="1153" height="465" alt="image"
src="https://github.com/user-attachments/assets/bf615e82-ee61-4222-979d-a8695a957e82"
/>

### Select certain tables only

<img width="1153" height="465" alt="image"
src="https://github.com/user-attachments/assets/28adaa24-f239-4d1d-8fb8-fdb1988320cd"
/>

### Confirm copy costs

As the final step before the pipeline is created:

<img width="597" height="619" alt="image"
src="https://github.com/user-attachments/assets/a660bd87-bfb8-41c5-8099-4cdbdef943bf"
/>


### Policy-aware initial-copy estimate

#### Copy no table is selected

<img width="407" height="464" alt="image"
src="https://github.com/user-attachments/assets/99d859ec-2ec3-452a-ab69-11924a8db260"
/>

#### Some tables are selected

<img width="407" height="464" alt="image"
src="https://github.com/user-attachments/assets/e68aedf4-66bc-4372-98ef-0dd7fecef324"
/>


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

- **New Features**
- Added configurable “initial table copy” policies (copy/skip all and
copy/skip selected) during replication setup, including table-picker
behavior, pruning of stale selections, and updated restart/cost
estimates.
- **Bug Fixes**
- Improved restart flows to consistently use `schema.table` identity and
simplified “errored tables” targeting to match error-state tables.
- Reduced unnecessary loading by gating publication/table fetches to
when panels are visible; improved validation/toast handling when
publication tables are unavailable.
- **Tests**
- Added/expanded coverage for destination form submission, table-copy
selection, restart/cost dialogs, and copy-estimate summarization.
- **Style**
- Refreshed warning/label text for clearer configuration and
confirmation messaging.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-07-24 10:29:46 +03:00
Danny White e3d7267845 fix(studio): chip away explicit-tabindex ratchet debt (#48040)
## What kind of change does this PR introduce?

A11y cleanup follow-up to #47984 /
[DEPR-626](https://linear.app/supabase/issue/DEPR-626).

## What is the current behavior?

Studio had 82 ratcheted `supabase/require-explicit-tabindex` violations
(raw `<button>` / `role="button"` without explicit `tabIndex`).

## What is the new behavior?

- Explicit `tabIndex={0}` (or disabled → `-1`) on those Studio call
sites across nav, `components/ui`, Database, Storage, and the remainder
- Ratchet baseline cleared (**82 → 0**) and the rule **removed from the
Studio ratchet** (debt is gone; ratchet is temporary)
- Rule remains a shared **`warn`** for now — promoting to `error` (and
sweeping www/docs/design-system) is a follow-up
- Also fixed the learn/ui-library call sites that surfaced while
experimenting with error promotion
- Small follow-ups where making controls focusable exposed gaps:
accessible names, disabled/focus consistency, focus-ring polish on
To-test surfaces, home section `KeyboardSensor`, and an E2E locator
tightened after `aria-label="Remove column"`

Prefer migrating to `Button` from `ui` in future touch-ups; this PR
takes the minimal path so Studio debt can stay at zero.

## Additional context

Batches landed together so baseline conflicts stayed simple while
chipping away:

- Hotspots / nav (FirstLevelNav, Marketplace, AttachmentUpload, Column,
Tabs, …)
- `components/ui` shared
- Database + Storage
- Remainder

**Out of scope / intentional deferrals**

- Promoting `supabase/require-explicit-tabindex` to a lint **error**
(follow-up after www/docs/design-system sweeps)
- Tabs/Radio roving, tooltips, context menus, in-menu items
- Full keyboard-accessible tab-close UX (close stays hover +
`tabIndex={-1}`; context menu still closes tabs)
- Data API docs links (`/project/<ref>/api` redirect)

**Reviewer notes**

- Rule only flags raw `<button>` / `role="button"` without a `tabIndex`
prop. `Button` from `ui` already bakes this in
- `tabIndex={-1}` is intentional for disabled controls, in-menu /
roving-focus children, and hover-only tab close
- For dnd-kit grips, put `tabIndex` **after** `{...attributes}` so it
isn’t overwritten (TS2783)

### To test

Use **Safari** with macOS Keyboard navigation **off** (System Settings →
Keyboard). Chrome once for a sanity pass. For each surface below: Tab
until the control is focused, then activate with Enter/Space where
relevant.

1. **API Docs side panel** (Table Editor → open a table → **API docs**)
- Floating API Docs panel — **not** `/project/<ref>/api` (that redirects
to Data API docs; language ToggleGroup uses arrow keys; links are out of
scope)
- Left nav buttons — Tab through several and activate one; active
highlight / navigation still works

2. **Integrations → Marketplace**
- Enable **Integrations layout** feature preview first (avatar menu →
Feature previews)
   - `/org/<slug>/integrations` or project integrations marketplace
   - “Clear all”, grid/list toggles — Tab + activate

3. **Table Editor → create a table → Columns**
- Drag handles only appear while **creating** (not when editing an
existing table)
   - Tab to grip / remove (X) / sensitive-data eye if shown

4. **Project Home** — section drag handles
   - Tab to a grip (visible focus ring)
- Optional: Space to pick up, arrows to move, Space/Esc to drop
(KeyboardSensor added)
   - Mouse dnd still works

5. **Storage → Policies** — expand/collapse bucket list chevron
(design-system focus ring, no stuck grey open bg)

6. **Support form** (Help → Support) — attachment remove (×) and
add-attachment control when visible

Disabled controls should be **skipped** by Tab.

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

* **Accessibility Improvements**
* Improved keyboard navigation throughout Studio by explicitly managing
focus (`tabIndex`) across many interactive controls (menus, tabs,
tables, charts, dialogs, navigation, and form actions).
* Disabled or non-interactive controls are now removed from the tab
order (or made unfocusable), while available actions remain reachable.
* Ensured `type="button"` on relevant controls to prevent unintended
submissions, and refined keyboard focus behavior for various toggles and
copy/remove actions.
* **Chores**
* Updated the ESLint rule baseline configuration to match the new focus
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-21 08:22:43 +10:00
Jordan McQueenandJoshen Lim fa1e4c4bbf feat(studio): add ClickHouse replication destination (#46870)
Adds ClickHouse as a replication destination type in Studio.

- New ClickHouse option in the destination type selector, gated behind
the
`etlEnableClickHousePrivateAlpha` organization feature flag (off by
default).
- ClickHouse settings form: URL, user, password (optional), database,
and
  - Client-side URL validation requires HTTPS and rejects URLs targeting
    internal addresses (loopback, RFC 1918, link-local, CGNAT, IPv6
    loopback/link-local/ULA, and IPv4-mapped/NAT64 forms). Server-side
    validation remains authoritative.

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

## New Features
- Added **ClickHouse** as a replication destination option (private
alpha), including support in destination selection/panel, replication
diagram rendering, and destination icons.
- Introduced a ClickHouse destination form with fields for URL, user,
optional password (masked toggle), database, and engine selection.
- Added ClickHouse destination config handling for create/update flows,
with normalization and engine support.

## Tests
- Expanded unit tests to cover ClickHouse validation and destination
config building/normalization, including HTTPS-only and blocking
localhost/internal targets.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-07-20 12:09:13 +08:00
Riccardo Busetti f19cb09b43 feat(pipelines): Update product docs and UI copy (#47997) 2026-07-17 11:43:04 +02:00
Riccardo Busetti c9eb33abc7 feat(pipelines): Add new cost estimation dialog (#47915) 2026-07-15 06:20:59 +00:00
Riccardo Busetti f45389138b ref(pipelines): Remove unnecessary restarts (#47732) 2026-07-10 01:34:19 +00:00
Riccardo Busetti 34d641f50b feat(pipelines): Add clarification on region (#47641) 2026-07-07 10:36:55 +02:00
Coenen Benjamin a1716edc3c refactor(replication): do not fetch secrets from APIs and enable partial update on API (#47454) 2026-07-02 21:04:12 +02:00
Gildas Garcia b30db91d71 chore: cleanup UI patterns exports (#47406)
## Problem

We now export components under a subpath in ui-patterns to avoid barrel
files as they slow down every tools (from IDE to linters, etc.) and may
also affect bundles our users have to download.

## Solution

- Remove the UI patterns index file
- Fix invalid impors
2026-06-30 09:23:17 +02:00
Riccardo Busetti df7a0ca3f7 feat(replication): Evaluate new product name (#47066) 2026-06-24 16:36:23 +02:00
Joshen Lim 68525aedd6 Break down DestinationForm into its own hook for validation and submission (#47176)
## Context

Another pass on refactoring the ETL code, specifically for
`DestinationForm/index.tsx`

Splits out the validation + pipeline submission logic into its own hook
`useDestinationForm.ts` so the main file is broken into smaller pieces

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

* **Refactor**
* Streamlined the database replication destination form by centralizing
validation and save/submission workflow in a dedicated hook.
* Improved the validation flow so failed validations guide users by
scrolling to the inline validation section, and warning confirmations
submit through the standard pipeline flow.
* Updated form reset behavior when the panel opens to ensure validation
state clears consistently.
* **Bug Fixes**
* Corrected autogenerated S3 key “description” to derive from the
selected warehouse when using Analytics Bucket destinations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-22 17:44:31 +08:00
Coenen BenjaminandJoshen Lim 2ce01473bb feat(replication): add better form to create ducklake replication (#47069)
## What kind of change does this PR introduce?

Add support to use supabase projects as a pg catalog and storage when
adding a ducklake replication.

## What is the current behavior?

Only simple form with raw input text for custom parameters is available.

## What is the new behavior?

Being able to select supabase project to directly use projects in
supabase for the ducklake.
I also fixed a warning we had in the console for this form (cf
screenshot)

## Additional context

[API Changes ](https://github.com/supabase/platform/pull/34282)


https://github.com/user-attachments/assets/4ff9ee65-6ba4-4f17-9ea1-9aebad34171c

<img width="862" height="228" alt="Capture d’écran 2026-06-18 à 09 58
50"
src="https://github.com/user-attachments/assets/1592c3be-807e-426f-9a5a-84979e05d93c"
/>

### Test scenario
Follow the screencast, go to your supabase project (better if it's in
ap-southeast-1)
Create a test table with 1 row for example
-> Database -> Replication -> New destination -> Select ducklake and use
supabase option
-> Keep the same current supabase project selected for both catalog and
storage
-> Create destination -> You'll get a warning about the storage and
credentials
-> Confirm creation
-> Wait until it's in status Running, if it's runing then it works


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

## Release Notes

* **New Features**
* Added DuckLake replication destination with **Use Supabase** and
**Custom parameters** modes.
* Added DuckLake bucket selection with a **“New bucket”** creation
dialog.
* Added/expanded BigQuery, Analytics Bucket, and Snowflake destination
configuration.

* **Improvements**
* Updated DuckLake create vs edit behavior: mode selection is hidden in
edit mode and configuration is mapped correctly for the selected
variant.
* Enhanced field-level validation (including whitespace-only handling)
and added clearer validation issue messages.
* Added a cross-region warning for DuckLake when catalog and storage
regions differ.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Benjamin <5719034+bnjjj@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-06-19 16:07:20 +02:00