Commit Graph
318 Commits
Author SHA1 Message Date
Anthony Lio e3febf3b63 feat(lint): add shadcn lint warnings (#50676)
## Problem

six apps had no shared lint checks for invalid tailwind classes,
off-scale values, and raw colors.

## Solution

add @shadcn/lint warnings with narrow exceptions for existing theme
colors and artwork. fix several invalid classes. the existing lint
command reports findings without blocking prs on the current warning
count.

## Review instructions

1. check the shared rules and app-specific exceptions.
2. run `pnpm --filter design-system lint` and confirm it reports shadcn
warnings without errors.

## Checklist

Check all before review:

- [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

* **Bug Fixes**
* Improved vertical alignment of checkbox labels and supporting text in
dialogs, settings, and examples.
* Corrected alignment of organization member details and the color
styling of deprecated chart text.
* Standardized spacing in the date and time editor without changing its
appearance or behavior.

* **Developer Experience**
* Updated linting and UI configuration across several apps to support
consistent style checks.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-25 17:50:50 +03: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
Monica KhouryandJoshen Lim 4b365eb4ee fix: pass projectRef/orgSlug to support link in table grid error (#50724)
## Summary

Fixes
[FE-3987](https://linear.app/supabase/issue/FE-3987/contact-support-pre-fills-the-wrong-supabase-project-id):
the "Contact support" button shown in the Table Editor's inline error
banner (e.g. "Failed to retrieve rows from table") didn't pass the
current project or organization to the support form. This caused the
support form to fall back to the user's first organization/project
instead of the one actually affected — especially noticeable when the
Management API request used to resolve the org also fails.

## Test plan

  - [ ] Open a project in Studio, go to **Table Editor**, open a table.
- [ ] Trigger a failing table query — either block the `rest/v1/<table>`
request in DevTools, or apply a filter with a mismatched type (e.g. `id
= 'abc'` on an int column).
- [ ] On the inline red "Failed to retrieve rows from table" banner,
click **Contact support**.
- [ ] Confirm the support form pre-fills the **correct organization and
project** — the one the failing table actually belongs to.
- [ ] Repeat with a project belonging to an organization that is *not*
first in your org list, to confirm it's not coincidentally correct.
- [ ] Repeat while simulating a Management API failure (e.g. block
`api.supabase.com`/`*.supabase.co/platform/*`) to confirm the org still
resolves correctly via the `orgSlug` fallback instead of silently
defaulting to your first org.
- [ ] Sanity check other "Contact support" entry points (header Feedback
dropdown, Help sidebar) are unaffected — they use a separate,
already-correct code path.

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

* **Bug Fixes**
* Improved error handling when project details cannot be loaded,
preserving relevant project and organization context.
* Improved fallback behavior for identifying the correct organization
when project information is unavailable or unresolved.
* Support requests opened from error messages now include applicable
project and organization information.
* Error messages now consistently display available additional actions
alongside contact support options.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-09-23 10:02:32 +00: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
Andrew ValleteauandClaude Fable 5.1 10eaab766f fix(studio): filter on every column when viewing a composite FK record (#50256)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix

## What is the current behavior?

In the Table Editor, the "View referencing record" arrow on a foreign
key cell builds its filter from the table's `relationships` list. That
list is one entry per source-by-target column combination, and the
formatter takes the first entry whose source column matches the clicked
cell, then filters the referenced table on that single target column.

For a composite foreign key this fails in two ways:

- The value from the clicked column can be applied to the wrong target
column (whichever target column happens to be listed first for that
source column).
- Only one of the key columns is ever filtered on, so the peek and the
"Open table" link return zero rows or too many rows.

This is distinct from #41068 / #41080, which fixed the cartesian
expansion in the shared `tables.ts` introspection query. The bug
reproduces with that fix in place because the mis-pairing happens in
Studio when building the filter. Reported by a customer via support.

### Reproduction

Run this in the SQL editor. The referenced column list `(org_id,
bucket_id)` is deliberately not in the referenced table's physical
column order, which is what exposes the bug.

```sql
create schema if not exists dcs;

-- bucket_id declared first, org_id second
create table dcs.org_metering_buckets (
  bucket_id bigint not null,
  org_id    bigint not null,
  primary key (org_id, bucket_id)
);

create table dcs.machine_storage_usage_buckets (
  org_id                 bigint not null,
  org_metering_bucket_id bigint not null,
  constraint machine_storage_usage_buckets_org_metering_bucket_fkey
    foreign key (org_id, org_metering_bucket_id)
    references dcs.org_metering_buckets (org_id, bucket_id)
);

insert into dcs.org_metering_buckets (bucket_id, org_id) values
  (901, 1), (902, 1), (903, 2);

insert into dcs.machine_storage_usage_buckets (org_id, org_metering_bucket_id) values
  (1, 901), (1, 902), (2, 903);
```

1. Open `dcs.machine_storage_usage_buckets` in the Table Editor (select
the `dcs` schema).
2. Hover the `org_id` cell on the row where `org_id = 2`.
3. Click the "View referencing record" arrow.
4. Click "Open table" in the popover.

**Before this PR:** the popover shows "No results were returned". "Open
table" opens `dcs.org_metering_buckets` with a single filter `bucket_id
= 2`, which matches nothing.

**After this PR:** the popover shows the one row `(bucket_id = 903,
org_id = 2)`. "Open table" opens `dcs.org_metering_buckets` with two
filters, `org_id = 2` and `bucket_id = 903`, and the URL carries two
`filter=` params. Clicking the arrow on the `org_metering_bucket_id`
cell of the same row produces the same result.

Extra checks worth doing while you are there:

- Set one of the two key columns to NULL on a row. The arrow should
disappear for both key cells on that row, since a row with a null key
column does not reference anything under MATCH SIMPLE.
- A single-column foreign key (any existing table) should behave exactly
as before.

## What is the new behavior?

- New `ForeignKeyFormatter.utils.ts` with two pure functions.
`findColumnForeignKeyConstraint` locates the constraint on the current
table that contains the clicked column. `getReferencingRecordFilters`
pairs each source column with the target column at the same ordinal
position and builds one equality filter per pair from the row's values,
keeping the existing bytea-to-hex handling per column. It returns no
filters when any key column is null.
- `ForeignKeyFormatter` now reads the foreign key constraints query,
which returns ordinally paired source and target column arrays, instead
of the `relationships` list. The grid already fetches that query for the
same schema, so it is served from the React Query cache.
- `ReferenceRecordPeek` takes a `filters` array instead of a single
column and value. Both the peek query and the "Open table" link use the
full set, and the link emits one URI-encoded `filter=` param per column.
- Unit tests cover the reproduction above, single-column keys, bytea
values, null and missing values, falsy-but-valid values such as `0`, and
malformed constraints.

## Additional context

The table-editor introspection SQL in
`packages/pg-meta/src/sql/studio/table-editor/table.ts` and
`tables-paginated.ts` still expands composite foreign keys as a
cartesian product. #41080 only fixed the shared `tables.ts` query. The
arrow no longer depends on that data, but it can still mislabel the
referenced column elsewhere in Studio, so that is left for a follow-up
rather than widening this change into pg-meta SQL.

Before:
<img width="836" height="504" alt="Screenshot 2026-09-14 at 11 22 49"
src="https://github.com/user-attachments/assets/4645d64f-9bcb-44b0-b5b1-ab11ba7436db"
/>

After:
<img width="873" height="570" alt="Screenshot 2026-09-14 at 11 23 14"
src="https://github.com/user-attachments/assets/f2c47121-fd75-4efe-a370-28015c1b674e"
/>



🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01SkH86UV1KD4Xs5k9vt43tW

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved foreign-key record previews to correctly identify referenced
records across schemas and tables.
* Added support for composite foreign keys, ensuring previews and “Open
table” links apply all required column filters.
* Improved handling of binary values and incomplete or null foreign-key
data.

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

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 19:22:04 +02: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
claude[bot]andClaude 235488e66b fix(studio): guard two undefined dereferences crashing the table editor and SQL editor (#49412)
<!-- ccr-slack-attribution -->
_Requested by **Ali Waseem** · [Slack
thread](https://supabase.slack.com/archives/C063LNYJJKS/p1787336596649619)_

**Before:** editing a cell in the table editor could throw, and the edit
was silently lost — the typed value vanished and nothing was saved.
Separately, opening the SQL editor could throw before the editor
rendered, and the global error boundary replaced the entire page, so
there was no editor at all until a reload.

**After:** a row change with no matching previous row is a no-op instead
of a throw, and the SQL editor shows its normal loading state instead of
taking down the page.

Two independent undefined guards for two confirmed Sentry crashes, one
per commit so either can be dropped on its own.

**How:** the first commit moves the existing previousRow guard in
`useOnRowsChange` above the `changedColumn` computation that
dereferences it, and drops the non-null assertion that hid the problem
from TypeScript. The second reads the snippet content in
`deriveSnippetIdentity` through optional chaining, so a missing
`snippets` map, or an entry without a `snippet`, resolves to
still-loading — the same answer the old code gave for an id that is not
in the map. Behaviour is unchanged in every case that did not crash.

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix.

## What is the current behavior?

**[K7M, Cannot read properties of undefined (reading
'idx')](https://supabase.sentry.io/issues/7681899596/)** — 4 events / 1
user — in `apps/studio/components/grid/components/grid/Grid.utils.tsx`.
Inside `useOnRowsChange`, the callback passed to
`Object.keys(rowData).find(...)` reads the candidate column off
`previousRow` through a non-null assertion, three lines above the `if
(!previousRow || !changedColumn) return` that was meant to protect it.
`rows.find(...)` returns undefined whenever no row matches, and the
assertion is why TypeScript never flagged the dereference. The four
events came from one user inside about two minutes, so it is
deterministic rather than a one-off, and every throw is an edit the user
loses.

**[K7J, Cannot use 'in' operator to search for a snippet uuid in
undefined](https://supabase.sentry.io/issues/7680905437/)** — 1 event /
1 user, full-page crash — in
`apps/studio/components/interfaces/SQLEditor/SQLEditor.utils.ts`, line
331. `deriveSnippetIdentity` applies the `in` operator to its `snippets`
argument and then reads `snippets[id].snippet.content`. The parameter is
declared required and non-optional, but `snippets` arrived undefined at
runtime, so `in` threw and the error reached the global error boundary,
which unmounted the whole SQL editor page. The `snippets[id].snippet`
read on the same line is a second unguarded dereference: an entry
without a `snippet` crashes identically.

## What is the new behavior?

Both crashes become no-ops.

- Grid: return early when `previousRow` is missing, then compute
`changedColumn`, with the assertion removed. When a previous row is
found, the code takes exactly the path it took before.
- SQL editor: `snippets?.[id]?.snippet?.content === undefined` replaces
the `in` check. A missing map, a missing entry, and an entry with no
`snippet` all read as still loading, which is what the surrounding code
already does while a snippet is being fetched. The parameter type is
left required, since the only caller (`useSnippetIdentity.ts`) passes
the store's `snippets` record, which is typed as always present — the
type is not the thing that was wrong.

Two test cases are added to the existing `deriveSnippetIdentity` block,
which previously only passed fully populated maps: one for an undefined
`snippets` map, and one for an entry missing its `snippet`.

## Additional context

**Why `snippets` was undefined is unexplained.** The store initialises
it to an empty object
(`apps/studio/state/sql-editor/sql-editor-state.ts:34`) and its only
reassignment writes an object, so there is no code path in studio that
sets it to undefined. This commit is a defensive guard against a crash,
not a root-cause fix, and nothing here should be read as an explanation.

**Verification:** no local checks were possible in the authoring
environment — the checkout has no `node_modules` and `pnpm install`
cannot complete there, so typecheck, lint and the studio unit tests
could not be run. CI on this PR is the only verification.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-24 10:11:44 -06:00
Joshen Lim 67d4fed40d Joshenlim/fe 4157 explorer migrate results component into explorer (#49066)
## Context

Related to Notebooks/Explorers - this one's just shifting files from the
SQLEditor into more generic folders from a file organization POV, such
that files under the Explorer folder have no dependency on files within
the SQLEditor folder

Mainly
- UtilityTabResults.utils: `getSqlErrorLines`
  - Moved into `data/sql/utils.ts`
- SQLEditor.utils: `applyAutoLimit`, `getSqlErrorLines`,
`trimTrailingSemicolons`
  - Moved into `data/sql/utils.ts`
- SQLEditor/UtilityPanel: `ResultCell`, `Results`, `CellDetailPanel`
  - Moved into `components/ui/DataGridResults`
  - Also shifted corresponding tests over here
- Also addressed some `any` type casts 

## To test
- Just need to ensure that the SQL Editor still works as expected

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

## Summary by CodeRabbit

* **New Features**
* Standardized query results across the Studio with a shared data grid.
* Improved result-table formatting, column sizing, clipboard handling,
and large-value display.
  * Added safer automatic row limits for eligible SQL queries.
  * Centralized SQL error display and formatting utilities.

* **Refactor**
  * Improved type safety for query rows and cell values.

* **Tests**
* Added comprehensive coverage for result-grid and SQL utility behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-14 11:29:39 +07:00
ChloeGarciaMillerand e241a21a9a fix: ESLint errors relating to accessibility in table editor, API Key and Access Token (#48479)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Added aria-label attributes and Tooltip to buttons

## What is the current behavior?

alt attributes and Tooltip were missing

## What is the new behavior?

Buttons have now aria-label attributes and Tooltip.

## Additional context

No visual changes have been made.


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

* **Accessibility Improvements**
* Added tooltips and improved accessible labeling for filter removal,
sort controls, and action menu triggers.
* Enhanced “More actions”/“More options” tooltips and aria-labels for
API keys and access tokens.
* Updated token scope selection and token banner close actions to use
clearer tooltip messaging.
* Wrapped panel close control with a tooltip and added an aria-label for
clearer screen reader support.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 18:05:41 +02:00
Charis 50e1eb7436 chore(eslint): bump eslint-config-next to v16 for useEffectEvent (#48458)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Chore / build (ESLint config upgrade + lint cleanup).

## What is the current behavior?

`eslint-plugin-react-hooks` v5 (pulled in transitively by
`eslint-config-next` v15) doesn't recognize stable `useEffectEvent`, so
every effect that calls an effect-event handler needs an `eslint-disable
react-hooks/exhaustive-deps` to silence a false positive. There are 30
such dead disables across Studio.

## What is the new behavior?

Bumps `eslint-config-next` to v16, which pulls in
`eslint-plugin-react-hooks` v7 whose `exhaustive-deps` understands
`useEffectEvent`, and removes the 30 now-dead disable directives (and
their orphaned explanatory comments).

Supporting changes:

- **Flat-config migration**: v16 is a native flat-config array (v15 was
eslintrc), so `eslint-config-supabase` now spreads it directly instead
of bridging through `FlatCompat`.
- **React Compiler rules off**: v16 enables react-hooks v7's
`recommended`, which layers the React Compiler lint rules on top of the
two classic rules. These are switched off (derived dynamically from what
next enables) to keep this change scoped to the `exhaustive-deps`
improvement.
- **Plugin-registration fallout** (v16 scopes plugin registration to a
file glob rather than registering globally like FlatCompat did): stop
re-registering `@typescript-eslint` (shared) and `jsx-a11y` (studio);
scope our react / react-hooks / jsx-a11y rule overrides (studio, www) to
v16's plugin glob so they don't error on files outside it (e.g. `.cjs`).
- **Lint surface preserved**: v16's glob newly includes `.mts`/`.cts`
(v15 didn't lint them), which surfaced pre-existing errors in tooling
scripts. The shared config keeps the prior surface by leaving
`.mts`/`.cts` unlinted; linting them is left as a separate change.
- **Ratchet**: rebaselines `@tanstack/query/exhaustive-deps` 9 → 89. v15
forced next's `@babel/eslint-parser` onto `.ts` files, hiding these
deps; v16 parses `.ts` with `@typescript-eslint/parser` and correctly
surfaces the intentional `connectionString`-excluded-from-`queryKey`
pattern. Worth a follow-up to review whether any are real
cache-correctness bugs.
- Drops three now-dead devDeps from `eslint-config-supabase`:
`@eslint/eslintrc`, `@eslint/js`, `@typescript-eslint/eslint-plugin`.

Verified locally: `turbo run lint` → 7/7 packages pass with 0 errors;
Studio `lint:ratchet` passes; Prettier clean on changed files; typecheck
unaffected.

## Additional context

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

## Summary by CodeRabbit

* **Chores**
* Refined linting configuration and removed outdated lint suppressions
across Studio.
* Updated Next.js linting support and refreshed related development
configuration.
  * Expanded lint baseline coverage for query-related code.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 09:01:05 -04: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
ChloeGarciaMillerandandGildas Garcia da847254d5 fix: ESLint errors relating to accessibility (alt attribute and tableEditor components) (#48186)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Improvements for screen readers:
- Added `alt` attributes to image components
- Added `aria-label` attributes and Tooltip to buttons

## What is the current behavior?

`aria-label`, `alt` attributes and Tooltip were missing

## What is the new behavior?

Buttons have now `aria-label` attributes and Tooltip.
Images have `alt` attributes

## Additional context

I’ve added `aria-label` attributes to the buttons in the Pagination.tsx
component, but these buttons don’t trigger any action. Shouldn’t we be
using non-interactive elements here?

No visual changes have been made.

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

* **Accessibility**
* Added a tooltip to the “date options” control when the value is
nullable.
* Improved screen-reader labeling by adding an `aria-label` to the
number editor input.
* Added explicit `aria-label` text to pagination footer buttons for
loading, error, and help/estimate states (and marked the error-state
button as disabled).
* **UI**
* Updated the pagination loading-state button to rely on the button’s
built-in loading behavior instead of a custom spinner icon.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
2026-07-27 14:32:41 +02:00
ChloeGarciaMillerand cea246d195 Fix: improve accessibility for icon buttons (Table Editor menu) (#47639)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix (accessibility improvement)

## What is the current behavior?

Icon-only buttons do not have explicit accessible names for screen
readers or tooltips.

## What is the new behavior?

All icon-only buttons now have explicit accessible names using visually
hidden text (sr-only), ensuring proper screen reader support.

## Additional context

Tooltip text is preserved or added for visual users.
No visual changes were introduced.


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

* **Accessibility Improvements**
* Updated table editor action controls with clearer, context-aware
`aria-label`s (e.g., “Add new column”, “More options for …”, “New
table”).
* **UI Refinements**
* Added hover tooltips to key table editor actions, including
add-column, more-options dropdown triggers, and create-new-table button,
improving discoverability and guidance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-24 10:47:14 +02:00
Alaister YoungandAlaister Young fbf7ce44ef [FE-3544] fix(studio): role impersonation for truncated cell loads (#48215)
Loading a truncated cell's full value from the inline grid editors or
the row side-panel editors called `getCellValue` without
`roleImpersonationState`, so the fetch ran with full DB privileges
instead of the role selected in **View as role** — leaking values RLS
would deny. Same class of bug #46442 fixed for row copy/export; the
mutation already accepted the state, these call sites just weren't
passing it.

**Changed:**

- Pass `roleImpersonationState` into `getCellValue` in all 4
truncated-cell loaders (inline grid Text/Json editors + row side-panel
Text/Json editors), mirroring the existing `Header.tsx` pattern

**Added:**

- MSW component test on the row side-panel `TextEditor` asserting the
cell-value SQL is wrapped with `set local role` when impersonation is
active, and not wrapped when it isn't

## To test

Note: if the impersonated role can't select the row at all (e.g. force
RLS with no policy), the main grid correctly shows 0 rows under **View
as role**, so the "Load full value" button is never reachable — you
can't exercise this path that way. Use a row the role *can* see and
verify the request is role-wrapped:

- Create a table with a text value long enough to be truncated in the
grid (>16KB), with RLS enabled and an anon-visible row:
  ```sql
  create table public.secrets (id int primary key, secret text);
  alter table public.secrets enable row level security;
  alter table public.secrets force row level security;
create policy "anon can read" on public.secrets for select to anon using
(true);
  insert into public.secrets values (1, repeat('a', 20000));
  ```
- In the Table Editor, set **View as role → anon** — the row should be
visible with the `secret` cell truncated
- With the network tab open, load the full value via each path:
double-click the cell (inline editor) and the row side panel's expand
editor → "Load full text data" (a `jsonb` column exercises the two JSON
editor paths the same way)
- The `pg-meta` query request body should start with `set_config('role',
'anon', true)` + anon JWT claims before the `select secret …`. Before
this fix it was a bare unwrapped `select secret from public.secrets
where id = 1;`
- Drop the policy and confirm the grid shows 0 records under anon
(denial still applies at the grid level); switch back to the default
role and confirm the full value still loads normally with no wrapper

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-07-23 16:46:51 +08:00
Danny White 9ea3919fb5 fix(studio): show column format in sort/filter type labels (#48201)
## What kind of change does this PR introduce?

Bug fix

## What is the current behavior?

Table editor sort (and filter) column pickers show `USER-DEFINED` for
extension types such as PostGIS `geography`, because they use `dataType`
from pg-meta.

| Before |
| --- |
| <img width="549" height="196" alt="CleanShot 2026-07-22 at 11 32 44"
src="https://github.com/user-attachments/assets/9ba2dec8-f5a3-479f-81c8-2dd133f6d419"
/> |

## What is the new behavior?

Those pickers use the same display helper as column headers
(`getColumnFormat`), so labels match the header (e.g. `geography`,
`int4[]`).

## Test plan

In SQL Editor:

```sql
create extension if not exists postgis with schema extensions;

create table public.geography_sort_repro (
  id bigint generated always as identity primary key,
  location extensions.geography(point, 4326),
  tags text[]
);
```

Then open `geography_sort_repro` in the Table Editor → Sort → pick
`location` / `tags`. Confirm labels are `geography` and `text[]` (not
`USER-DEFINED` / `_text`). Same check in the Filter column picker.

Cleanup: `drop table public.geography_sort_repro;`

## Additional context

`data_type` is intentionally coarse for non-`pg_catalog` types in
pg-meta; `format` already carries the real type name. Arrays need
`getColumnFormat` so `_int4` becomes `int4[]`.

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved column type labels in filter and sort menus by displaying the
appropriate format instead of raw data types.
* Preserved existing JSON-field restrictions and tooltips while
improving the clarity of displayed column information.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-23 02:02:28 +10: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
fd8a37b1d0 feat: add toggle for sensitive data visibility in table columns (#46180)
## Fixes

FE-2619

## What is the new behavior?

This PR adds support for marking table columns as sensitive and masking
their values in the grid view.

Sensitive columns:

- Display an 8-dot mask instead of the underlying value
- Remain masked across page refreshes
- Can be temporarily revealed for 5 seconds via the **Show data** action
- Display a warning when copying rows containing sensitive data

This helps prevent accidental exposure of sensitive information when
sharing screens, recording demos, or taking screenshots.

## Testing

- [x] Toggle sensitivity ON → save → refresh → remains masked
- [x] Toggle sensitivity OFF → save → refresh → remains unmasked
- [x] Toggle sensitivity multiple times → state remains consistent
- [x] Copy row with sensitive columns → warning shown
- [x] Click **Show data** → value revealed for 5 seconds then re-masked
- [x] Text, Boolean, Binary, JSON, and Foreign Key columns all display a
consistent 8-dot mask

### Test data

SQL fixture covering multiple PostgreSQL data types:

https://gist.github.com/monicakh/2485e9054bf21045912359871e9a1cb4. 

### UI

<img width="1284" height="554" alt="CleanShot 2026-06-09 at 12 01 33@2x"
src="https://github.com/user-attachments/assets/4aec0ba7-c874-42d7-9442-d2c704b319cc"
/>

<img width="1200" height="560" alt="CleanShot 2026-06-07 at 10 43 40@2x"
src="https://github.com/user-attachments/assets/b9569484-6fcc-47de-bc3d-881d0edc4060"
/>

The **Show data** action is only available for sensitive columns.

<img width="450" height="400" alt="CleanShot 2026-06-07 at 10 42 18@2x"
src="https://github.com/user-attachments/assets/d48849a2-ec0b-4522-a787-561a1d204ec9"
/>

Warnings on Copy command

<img width="450" height="80" alt="CleanShot 2026-06-09 at 11 58 42@2x"
src="https://github.com/user-attachments/assets/374e7d6b-b82a-4923-b035-2ec9b2f7bb7d"
/>

<img width="450" height="80" alt="CleanShot 2026-06-09 at 11 58 58@2x"
src="https://github.com/user-attachments/assets/ecd951bb-e9e2-47ae-9ddd-d32969e01c12"
/>


<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46180?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

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

---------

Co-authored-by: supabase-autofix-bot <noreply@supabase.com>
Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-07-09 10:44:42 +03:00
Gildas Garcia cabe14e5ca chore: remove _Shadcn_ suffix from ui tabs components (#47628)
## Problem

Now that we migrated all usages of the deprecated `Tabs` component, we
don't need the `_Shadcn_` suffix anymore.

## Solution

Remove `_Shadcn_` suffix from `ui` tabs components. That's all this PR
does, no visual nor functional changes

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

## Summary by CodeRabbit

* **New Features**
* Standardized tab components across the app so pages and dialogs now
use the same consistent tab UI.
* Improved tab-based views in design, docs, studio, learn, and website
experiences for a more uniform interface.

* **Chores**
* Updated shared UI exports to expose tab components directly,
simplifying future usage across the product.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-06 15:29:16 +02:00
Vaibhav 38669218ac fix: preserve copy (#47607)
- closes https://github.com/supabase/supabase/issues/47606

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

## Summary by CodeRabbit

* **Bug Fixes**
* Copying cell values now preserves `false` and `0` instead of treating
them like empty values.
* Clipboard copy behavior now only returns blank for truly empty inputs,
helping keep table data accurate when copied.
* **Tests**
* Added end-to-end coverage for copying table cells with `false`, `0`,
and `true` values.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-06 07:17:17 -06:00
Saxon FletcherandClaude Opus 4.8 fb02182e86 Color system (#47288)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES/NO

## What kind of change does this PR introduce?

Bug fix, feature, docs update, ...

## What is the current behavior?

Please link any relevant issues here.

## What is the new behavior?

Feel free to include screenshots if it includes visual changes.

## Additional context

Add any other context or screenshots.


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

* **New Features**
* Refreshed theming across the UI to use modern color expressions and
shared theme variables (including OKLCH-based gradients), improving
consistency for charts, code blocks, overlays, icons, and decorative
backgrounds.
* **Bug Fixes**
* Improved light/dark color and gradient consistency across axis/grid
styling, reference lines, buttons/badges, sidebar accents, loaders, and
other visual components.
* **Documentation**
* Updated styling/theming guidance to align with the revised semantic
token system and the updated theme variable usage patterns.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 15:00:43 +10:00
Ali Waseem 2b566175b1 fix(studio): prevent FK peek popup from extending outside viewport (#47510)
Fixes the `ReferenceRecordPeek` popup extending outside the browser
viewport when clicking the FK arrow button on lower table rows in the
Table Editor.

Closes FE-3761

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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved popover positioning near screen edges so reference previews
stay visible in more cases.
* Constrained the reference preview table to a fixed height with clipped
overflow, keeping the preview panel compact and easier to scan.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-02 07:18:02 -06:00
Gildas Garcia 70c3bafe63 chore: CSS cleanup (#47443)
## Problem

- We have unused CSS from previous design system (`.sbui-*` classes)
- We use Tailwind `@apply` when we could set the tailwind classes on the
components directly

## Solution

- Delete all `.sbui-*` classes as we don't use them anymore
- Move classes directly on components when that make sense

## Notes

I did not migrate all `sbgrid` classes as they are applied in multiple
components

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

## Summary by CodeRabbit

* **Bug Fixes**
* Updated grid editors, placeholders, headers, and dropdowns for cleaner
spacing, truncation, and alignment.
* Improved layout consistency across text, number, time, JSON, and
foreign-key cells.
  * Adjusted search and impersonation inputs for better fit and padding.

* **Chores**
* Simplified and removed outdated styling overrides across the Studio
and web app.
* Reduced unused UI package surface by removing an unused input icon
container export.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-30 18:06:38 +02:00
hallidayo 35df0898c8 fix: table editor search state (#47085)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Supabase > Studio > Table Editor > Filters

## What is the current behavior?

When you add a filter and you are on a different page from the first or
total pages from the filter you have to manually go back to the first
page:



https://github.com/user-attachments/assets/d254c8d4-3a5a-4e90-b7be-25a3a16a5b6f



## What is the new behavior?

Table editor now automatically redirects to the first page or page in
which you will see data:



https://github.com/user-attachments/assets/e77aa27e-884f-45a2-a951-7fd1c675e62f





## Additional context

Add any other context or screenshots.


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

* **Bug Fixes**
* Updated pagination so the current page automatically returns to page 1
whenever filters are changed, keeping results consistent with the new
criteria.
* The reset is skipped on the initial load to avoid disrupting the
default starting state.
* Prevents pagination from becoming out of sync after applying or
modifying filters.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-30 14:07:32 +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
Aaditya BhusalandAli Waseem 719434a7fd fix(studio): batched table edits issues (#47319)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix

## What is the current behavior?

Fixes #47318

Supabase Studio's batched table edit queue has a few related row
identity issues:

- Editing a row's primary key can make later queued edits or deletes
lose track of the original row.
- Editing a primary key and another column in the same row before saving
can save only the primary key change, because later updates still use
the old primary key in the `WHERE` clause.
- Adding a row in batched edit mode and then deleting it before saving
may not remove the pending row correctly.

## What is the new behavior?

- Preserves the original row identity for queued operations after
primary key edits.
- Applies multiple queued edits for the same row as a single update when
saving.
- Correctly deletes newly added pending rows before they are saved.
- Adds regression coverage for these batched table edit cases.

## Additional context


https://github.com/user-attachments/assets/75672361-d781-4fe5-a542-071574ad57bd


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

* **Bug Fixes**
* Improved row identity handling for grid edits, optimistic updates, and
queued operations so changes stay correctly attached when primary keys
are edited, reverted, or “taken” by another row.
* Updated header row deletion to delete from the currently
visible/targeted rows rather than relying on the full dataset.
* Reduced retry noise for missing tables by clearing conflicting sorts
and preventing repeated retries for the same “does not exist” error.
* More reliably consolidated queued edits for the same row into fewer
combined save statements.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ali Waseem <waseema393@gmail.com>
2026-06-29 08:12:18 -06:00
Joshen Lim 3d10f2cab9 Add user flow for iceberg wrapper if api keys are rotated (#47336)
## Context

We found an issue regarding Analytics Buckets and the Iceberg wrapper -
upon creation of an analytics bucket, the wrapper is automatically
created for the users which involves using the project's API keys as the
catalog's token.

However, if the user were to rotate the API keys, this will cause the
wrapper to break and there's currently no clear user flow for the user
to self-remediate - the only indicator they'll see is just a 403 error
(e.g when trying to view the analytics bucket table via FDW on the table
editor or SQL editor)

## Changes involved

Am adding a user path for users to self-remediate a little, starting
from the Table Editor - we'll add a contextual error message as such if
we detect a 403 that's caused by an invalid token:
<img width="1110" height="320" alt="Screenshot 2026-06-26 at 17 33 11"
src="https://github.com/user-attachments/assets/28ea4ce6-5b81-4217-9952-880acb02f2bd"
/>

We'll subsequently also float this issue up in the Analytics Bucket UI
(which is linked from the contextual error above)
<img width="1114" height="466" alt="Screenshot 2026-06-26 at 17 31 52"
src="https://github.com/user-attachments/assets/8d112e5b-6ecc-458b-b4dc-7e7647da3fb2"
/>

And users can then choose to use another API key as the catalog token
<img width="585" height="246" alt="Screenshot 2026-06-26 at 17 31 56"
src="https://github.com/user-attachments/assets/3d9689a5-b18d-4f07-a5a5-d882e41c5958"
/>

The warning will thereafter go away, and users will be able to query the
FDW again via Table Editor or SQL Editor

## To test

- [ ] Create an analytics bucket, set up a table and foreign schema (via
Query via Postgres)
- [ ] Insert some data, or verify that you can view the iceberg table
from the Table Editor
- [ ] Now rotate your API secret key (delete the old, create a new)
- [ ] Verify that you'll run into that error if you view the iceberg
table from the Table Editor
- [ ] Follow the flow -> Go to the Analytics Bucket UI to update the
catalog token
- [ ] Verify that thereafter, you can view the iceberg table again from
the Table Editor

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

* **New Features**
* Added clearer Iceberg/analytics bucket setup prompts for missing,
outdated, or uninstalled wrappers.
* Added an “Update catalog token” dialog and a collapsible “View error”
troubleshooting UI.
* **Bug Fixes**
* Improved detection of Iceberg authorization failures and now shows a
more specific error with guidance.
* Warn users when the saved catalog token no longer matches available
API keys.
* Enhanced post-update refresh behavior so updated token values display
correctly.
* **Documentation**
* Clarified vault token description to indicate it may be a secret or
service role key.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-29 17:43:38 +08:00
Joshen Lim f2e20eac34 Joshen/fe 3651 deprecate monacoeditor from grid folder to use codeeditor (#47179)
## Context

Part of efforts to consolidate all the code editors that we have in the
repository

`CodeEditor` will serve as the base monaco editor file that all UIs
should consume from
It's aimed to be generic and just stores the common logic that will be
generally used where-ever we need a code editor (editor options, base
editor set up on mount, etc)

The idea is that `CodeEditor` holds just 3 default actions (run queyr,
format document and placeholder fill)
If any editor needs specific behaviours (e.g SQL Editor), they can
declare them in the `onMount` prop of `CodeEditor` which gives some
flexibility

## Changes involved
- Use `CodeEditor` component for SQL Editor's `MonacoEditor`
- Shifted Cmd K behaviour into `CodeEditor` since that's probably needed
everywhere that we render that UI
- Deprecate `MonacoEditor` from the table editor's `grid` folder
- All files that were using that component to use `CodeEditor` component
instead

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

## Release Notes

* **Refactor**
* Migrated the studio’s code editing UI (including JSON, text, and
payload viewers) to a unified CodeEditor experience.
* **New Features**
  * Added plaintext language support for read-only/truncated views.
* **Behavior Changes**
* Improved editor startup by setting cursor position consistently and
deferring autofocus.
* Streamlined editor context-menu actions to the core set (run query,
format, placeholder fill).
* Updated SQL editor wiring for more consistent command/menu and
selection handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-23 11:39:24 +08:00
Vaibhav 84edf0dc94 fix: protect csv import (#47040)
## TL;DR 
fixes protected schema empty tables still exposing CSV import actions in
table editor...
## ref: 
- closes https://github.com/supabase/supabase/issues/41358
- supersedes: https://github.com/supabase/supabase/pull/41362
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Updated the table empty state so CSV import actions are shown only
when the table is allowed to accept imports, and are hidden for
protected cases (including foreign-table scenarios).

* **Tests**
* Added an end-to-end test confirming that empty tables in protected
schemas do not expose the “Import data from CSV” button or the
drag-and-drop CSV hint.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-18 15:43:46 +01:00
Gildas GarciaandIvan Vasilov 96d43099bb chore: refactor Button API so that it can be used a standard button (#46880)
## Problem

Our `<Button>` component breaks the default `button` contract by
redefining the `type` prop to set its variant (`primary`, `default`,
etc) instead of the button type (`submit`, `button`, etc).
This is confusing and forces to write more code when using it with
shadcn components that expect/inject the standard button props.

## Solution

- rename the `type` prop to `variant`
- rename the `htmlType` prop to `type`
- propagate the changes where necessary
- format code

## How to test

As this is just prop renaming, if it builds it's ok

---------

Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
2026-06-16 23:59:58 +02:00
Joshen Lim 1baaded0bb Consolidate execute-sql-query into execute-sql-mutation (#46944)
## Context

Just some clean up as I was going through stuff
- `useExecuteSqlQuery` is deprecated and not used at all
- As such `execute-sql-query` is technically irrelevant, the more
relevant file is `execute-sql-mutation`
- Hence opting to consolidate `execute-sql-query` into
`execute-sql-mutation`
- Also removing `ExecuteSqlError` since its just re-exporting the
`ResponseError` type

There's a lot of file changes but its essentially just updating the
importing statements across the files
2026-06-16 00:07:16 +08:00
Ivan Vasilov 40c947ebfb fix: Handle non existant columns when sorting tables (#46741)
When a user has sorted by some column in the Table Editor and the column
is deleted, the sort data is wrong so it causes issues. In the general
view in the Table Editor, the error is handled by removing the sort key
when a specific error is detected but it can still happen in
ForeignRowSelector.

To test:
1. Have 2 tables with references between them.
2. In the `sessionStorage`, under the `supabase_grid-<ref>` key, update
the sort key to a non-existant column for a table.
3. Try to open the `ForeignRowSelector` for that table by clicking on a
cell in the referencing column.

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

* **Bug Fixes**
* Sorting now validates referenced columns and ignores invalid sort
entries.
* Local sort restoration and UI sort application now derive sorts from
the original table context for more consistent behavior across editors
and popovers.
* Prefetch logic uses the resolved table context when falling back to
saved sorts.

* **Tests**
* Added cases for malformed and out-of-scope sort parameters to prevent
regressions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-09 12:30:13 +02:00
Vaibhav 02422bed2c fix: keep role view (#46426)
## TL;DR

fixes export hydration so it stays under the active impersonated role in
table Editor

## Example: while viewing as `anon`

| Before | After |
| --- | --- |
| <img width="653" height="234" alt="before: hydration query wrapped
with anon impersonation"
src="https://github.com/user-attachments/assets/0a7b9b21-b5b5-4eac-94f4-1bffe7238eee"
/> | <img width="518" height="226" alt="after: plain select without
impersonation wrapper"
src="https://github.com/user-attachments/assets/b4228a1a-2972-4ed6-87c7-85f85f61f8ca"
/> |

PS: The  `Export` path was skipping the active impersonation context and
 issuing the query without the `anon` role wrapper

## ref

- closes #46423

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

* **Bug Fixes**
* Export functionality now includes role impersonation context for both
full dataset and selected row exports, ensuring consistent behavior
across all export operations.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46426?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-08 10:45:39 -06:00
Vaibhav ddf8569533 fix: toggle regression (#46751)
- Broken by: #45504
- closes: #46744

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

## Summary by CodeRabbit

* **Style**
* Refined the footer layout to improve alignment of view and table
toggle controls.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-08 10:45:02 -06:00
Ali Waseem 1c2d28d5b3 chore: wrap local storage into helper methods that are safer (#46628)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

- Noticing our code we have many patterns of calling localstorage and
handling those errors
- We should add those in a single well tested file
- Handle those errors in the singleton which makes it easier for us to
debug customer issues. Logger is outputing local storage warnings for
feature we expose
- Side effect of this is random crashes on studio when local storage
isn't available or handled correctly

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

* **Refactor**
* Improved browser storage handling across the app for more reliable
persistence and graceful behavior in restricted or non-browser
environments (settings, previews, charts, tabs, sign-in/session flows,
integrations, and UI state).

* **New Features**
* Introduced a safe storage layer to standardize and harden
local/session persistence.

* **Tests**
  * Added comprehensive tests covering the new safe storage behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-04 07:41:28 -06:00
Alaister YoungandAlaister Young 446398bd28 fix(studio): remove default DataGrid borders in table editor (#46633)
Follow-up to #46448, which removed the doubled DataGrid borders across
Studio. The table editor grid had the same doubled border at the bottom,
but unlike the other grids it still needs a top border — and that top
border was rendering in react-data-grid's own `--rdg-border-color`
rather than the studio default.

**Changed:**
- Removed the doubled bottom border on the table editor `<DataGrid>`
(`border-b-0!`)
- Forced the top border to the default border color via the
`border-t-default!` token (≈ rgb(46,46,46) / `--border-default`) instead
of leaning on react-data-grid's `--rdg-border-color`

## To test

- Open the table editor for any table (`/project/[ref]/editor/[id]`)
- Confirm there's a single top border between the filter/sort toolbar
and the grid header, in the standard border color
- Confirm there's no extra line at the bottom of the grid

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

## Summary by CodeRabbit

* **Style**
* Refined grid visuals and spacing to improve alignment and visual
consistency across the app. Adjustments to border and growth behavior
reduce border inconsistencies and layout jitter during resizing. Context
menu display behavior remains intact, ensuring expected right-click
interactions continue to work smoothly for users.

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

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-06-04 17:28:30 +10:00
Alaister YoungandAlaister Young 7e9badc6b8 chore(studio): migrate useStaticEffectEvent to React 19 useEffectEvent (#46415)
Studio is on `react@^19.2.6`, and `useEffectEvent` shipped stable in
React 19.2 with the same signature as the userland polyfill. This drops
the local hook in `apps/studio` and `apps/www` in favor of the built-in.

**Removed:**
- `apps/studio/hooks/useStaticEffectEvent.ts`
- `apps/www/hooks/useStaticEffectEvent.ts`
- `.claude/skills/use-static-effect-event/` — skill is obsolete

**Changed:**
- 26 call sites: dropped the `useStaticEffectEvent` import, added
`useEffectEvent` to the existing `react` import, renamed call sites
- `.claude/CLAUDE.md`: `apps/studio` row updated React 18 → React 19
- `.claude/skills/vercel-composition-patterns/SKILL.md`: removed stale
"Studio uses React 18, skip these patterns" warning

## To test

- `pnpm typecheck --filter=studio` — passes locally
- `pnpm typecheck --filter=www` — passes locally
- `grep -rn "useStaticEffectEvent"` returns nothing outside
`node_modules`
- Smoke-test areas that use the hook: schema visualizer edges
(intersection check), spreadsheet import, sign-in/CLI login flows, side
panels with unsaved-changes prompts

**Out of scope:** pre-existing Tailwind lint warning on
`DefaultEdge.tsx:141` (`outline` + `outline-1` conflict) — unrelated to
this migration

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

* **Refactor**
* Internal event handling migrated to React’s built-in event hooks
across the Studio app; no user-facing changes.

* **Documentation**
* Clarified React 19 compatibility and noted Studio now targets React
19.
  * Removed obsolete documentation for a deprecated internal hook.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46415?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

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

---------

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-05-28 23:30:42 +08:00
Alaister YoungandAlaister Young 29af5308f3 [FE-3493] fix(studio): respect role impersonation when copying truncated rows (#46442)
Copy/export of selected rows in the Table Editor refetches full values
for cells truncated in the grid (via `getCellValue`), but that refetch
was bypassing role impersonation. The main grid query respects the
impersonated role; the truncated-cell hydration didn't, so the copy
could fetch as the service role even when "View as <role>" was active –
an inconsistency, since the UI still indicates the impersonated role is
in effect.

Threads `roleImpersonationState` through `hydrateTruncatedRows` →
`getCellValue`, and wraps the SQL in `wrapWithRoleImpersonation`
(matching how `getTableRows` does it). Addresses FE-3493.

**Changed:**
- `getCellValue` accepts an optional `roleImpersonationState` and wraps
its SQL with `wrapWithRoleImpersonation` + flags
`isRoleImpersonationEnabled` on `executeSql`
- `hydrateTruncatedRows` threads `roleImpersonationState` through to
`getCellValue`
- `Header.tsx`'s `onCopyRows` passes the in-scope
`roleImpersonationState` into `hydrateTruncatedRows`

## To test

1. Open the Table Editor on a table with a row containing a
large/truncated string value and a primary key
2. Enable role impersonation → "View as role" → pick any role with read
access to the table
3. Select the row, then `Copy → Copy as JSON` (also try CSV / SQL)
4. The copy should succeed and contain the full (non-truncated) value
5. Inspect the SQL request – it should now be wrapped with the
impersonation context, matching how the main grid query is wrapped

Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
2026-05-28 15:22:20 +08:00
Joshen Lim 65c570e85b Fix copy / export large values in table editor (#46268)
## Context

There's an issue with copying / exporting rows from the table editor
with the following conditions:
- Row has a column value that exceeds 10,240 and hence is truncated for
performance reasons
<img width="300" alt="image"
src="https://github.com/user-attachments/assets/4639edbb-ece6-4028-89b6-769ac314c3f3"
/>
- User is trying to copy/export selected rows (not all rows in the
table)
<img width="300" alt="image"
src="https://github.com/user-attachments/assets/e7c0da77-051c-4c46-af0d-f9510e0b37c4"
/>

The copy/export action will return the truncated data which is incorrect
(Should return the full data)

## Problem

This is happening as if we're only copying/exporting selected rows,
we're just using what's been loaded in the table editor to export (as
opposed to if the user is copying/exporting all rows in the table, we'd
be fetching the data from the database first before doing so)

Hence am opting to add a data hydration logic, such that if there's a
selected row that's been truncated, we'd fetch them on demand first
before copying/exporting.

There's limitations to this though - e.g if the table doesn't have a
primary key we can't do this (since we need to run a query to fetch the
data). This is already an existing behaviour when trying to load the
column value in the table editor in the grid so no issues I believe.
We'll just show this toast:
<img width="300" alt="image"
src="https://github.com/user-attachments/assets/442637bb-4b9b-492d-b202-bbf6e5ae7512"
/>

## To test
You'll need a column with a really large value - the way I do it is to
load the data directly into the DB via TablePlus
- [ ] Verify that copying / exporting selected rows with really large
column values copies/exports all the data correctly (there shouldn't be
any truncated value)

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

## Summary by CodeRabbit

* **New Features**
* Improved handling of truncated cell values during copy and export
operations

* **Bug Fixes**
  * Copy and export operations now require an active project selection
  * Fixed data export for tables without primary keys

* **Style**
  * Updated grid header copy and export control layout

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46268?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-25 11:26:43 +07:00
Ali Waseem 34303997c6 fix(table-editor): wait for filter value before applying (#46113)
## Summary

- Closes
[FE-3399](https://linear.app/supabase/issue/FE-3399/make-table-editor-filter-bar-wait-for-a-value)
- Table editor's filter bar was firing a row request as soon as a
property was selected, before any operator/value was set. This regressed
after #46071 unified the table editor and unified logs onto the shared
`FilterBar`.
- `LogsFilterBar` already validates that each condition has a
propertyName, operator, and non-empty value before applying.
`FilterPopoverNew.handleApply` did not — it called `setFilters`
unconditionally on every `onApply` from the shared bar (property change,
operator change, blur, etc.). This PR mirrors the `LogsFilterBar`
validation so the table editor stops requesting rows until the condition
is complete.

## Test plan

- [ ] Open the table editor on any table
- [ ] Click the filter bar, pick a column → no network request fires, no
toast, grid unchanged
- [ ] Pick an operator → still no request
- [ ] Type a value and hit Enter → row request fires, grid filters
- [ ] Remove the filter → grid refetches with no filter
- [ ] New e2e test: `pnpm --prefix e2e/studio run e2e --
features/filter-bar.spec.ts --grep "does not trigger a row request"`

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

## Summary by CodeRabbit

* **Bug Fixes**
* Filter validation now prevents incomplete filter conditions from being
applied, ensuring only fully-specified filters affect table data.

* **Tests**
* Added end-to-end test coverage for filter bar operations to verify
expected behavior during filter setup.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46113?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-19 10:31:57 -06:00
Joshen LimandGildas Garcia 7728bfae1d Joshen/debug 97 use the same filter bar in unified logs and table editor (#46071)
## Context

Swaps out (and deprecates) the unified logs's own filter bar, for our
existing design system's filter bar
<img width="1450" height="355" alt="image"
src="https://github.com/user-attachments/assets/c5e83bd1-4e67-4bb5-8f27-a3d9beacbbb5"
/>

Other changes involved for the FilterBar itself includes the following
(more details in subsequent sections)
- Add `onApply` param for `FilterBar` that will only trigger when an
entered filter is "complete" (e.g on enter or blur)
- Automatically select the operator if only one exists

## To test
- Verify that the filter bar in general works BUT note there's some odd
behaviour when searching on say the "status" column (more details under
known issues)
- likely something with the internal SQL i think, will need to
investigate separately
  - afaict testing on the method seems to be working at least

---

### Add `onApply` parameter for `FilterBar`
The search behaviour for the filter bar feels a bit awkward atm -
referencing the table editor:
- selecting the column triggers a search, which returns an error cause
the search query is incorrect (operator and value not selected yet)
- when typing the search value (after selecting the column + operator),
the search triggers on debounce, which feels odd in this context as I'd
expect the search to only trigger when i've hit enter (e.g to "finalize"
my search parameters)
- Am adding an `onApply` parameter gets called when a filter is
"complete" -> column, operator, and value are finalized (e.g via Enter
or onBlur)
- Updated both Unified logs and table editor to use this behaviour

### Automatically select operator if only one exists in `FilterBar`
This one's more specific to unified logs since there's only an `=`
operator - but saves an unnecessary "enter" key event when filtering in
unified logs

### Known issues
- For some reason (even with the existing filter bar) - searching
against status for e.g for postgres logs doesnt return the expected
rows. e.g i've got rows with status as `00000`, but searching for
`00000` doesnt return anything. Suspect its something to do with the SQL
we're firing?
<img width="1167" height="271" alt="image"
src="https://github.com/user-attachments/assets/1dde74cf-8366-4cf1-8d8f-6907ba2473f6"
/>
<img width="1184" height="453" alt="image"
src="https://github.com/user-attachments/assets/bf55f0fb-cb27-4e8f-b2d9-cd913d6ac6b9"
/>


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

* **New Features**
* Added a dedicated Logs filter bar with an explicit "apply"/commit
callback for filter UI.

* **Bug Fixes**
* Filter edits are buffered locally and only committed on apply to
prevent aggressive data requests.

* **Refactor**
* Replaced legacy command-style table filter UI and removed related
utilities.
* Updated filter commit lifecycle and narrowed option value typing;
adjusted top-level provider ordering.

* **Style**
* Small layout and trigger behavior tweaks for filter controls, timeline
chart spacing, and download button.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46071?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

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

---------

Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
2026-05-19 21:03:02 +07:00
Pamela Chia 0bed80b340 chore(telemetry): clean up frontend event catalog (#45964)
## Summary
Resolves 13 findings (2 HIGH, 5 MEDIUM, 6 LOW) from the frontend
telemetry audit: 1 action-string collision, 1 camelCase experiment name,
9 dead events removed, 4 missing org groups attached, 1 ambiguous
property renamed, 1 raw-string property narrowed, plus consolidations
and a structural tightening on TABLE_EVENT_ACTIONS.

## Changes
### HIGH
- Rename `EventPageCtaClickedEvent.action` to
`www_event_page_cta_clicked` so it no longer collides with the pricing
CTA event (which had a different schema sharing the same action string)
- Snake_case the header-upgrade experiment exposure name
(`headerUpgradeCta_experiment_exposed` →
`header_upgrade_cta_experiment_exposed`); PostHog flag key and
`?source=` URL param unchanged

### MEDIUM
- Remove 4 dead `ProjectCreation*Step*` events (referenced a v2 route
that doesn't exist; 0 emissions)
- Remove 4 dead experiment exposure events:
`ProjectCreationRlsOptionExperimentExposed`, `HomeNewExperimentExposed`,
`TableCreateGeneratePoliciesExperimentExposed`,
`TableCreateGeneratePoliciesExperimentConverted` (0 emissions)
- Attach org group to `dpa_request_button_clicked` (0% had `$group_0`
per Hex)
- Delete `RegisterStateOfStartups2025NewsletterClicked` (interface
naming outlier, 0 emissions, page renamed to 2026)
- Rename `AssistantSuggestionRunQueryClickedEvent.category` to
`mutationType` with tightened literal union (`'functions' |
'rls-policies' | 'unknown'`)
- Attach org group to `project_creation_default_privileges_exposed` on
Vercel surface via explicit `groupOverrides` (auto-injection misses
because `useSelectedOrganizationQuery` is undefined on that page)

### LOW
- Consolidate `IndexAdvisorBannerEnableButtonClickedEvent` +
`IndexAdvisorDialogEnableButtonClickedEvent` into one event with
`origin: 'banner' | 'dialog'`
- Rename `ImportDataFileDroppedEvent` → `ImportDataFileAddedEvent` so
the interface name matches the action and the verb is on the approved
list
- Rename `LogDrainConfirmButtonSubmittedEvent` → `LogDrainRemovedEvent`
and action to `log_drain_removed` (fires on delete-confirm modal,
matches `CronJobRemovedEvent` pattern)
- Add `type` property to `CronJobRemovedEvent` (parsed from the job's
command), matching the create/update event shape
- Tighten `TABLE_EVENT_ACTIONS` values with `satisfies` against the
event union so renames in the union fail typecheck here too
- Attach org group to `www_pricing_plan_cta_clicked` at 5 emission sites
when an org is available in the page context
- Narrow `unified_logs_row_clicked.logType` from raw `string` to the
5-literal `LOG_TYPES` union (zod already validates server values)

### Bundled refactor
Migrated 5 emission sites from deprecated `useSendEventMutation` to
`useTrack` while their containing files were being edited: `DPA.tsx`,
`DisplayBlockRenderer.tsx`, `Grid.tsx` (2 events), `DeleteCronJob.tsx`.
Full sweep of the remaining ~79 files is a separate follow-up.

## Testing

Mostly just renaming of events

## Linear
- fixes GROWTH-798


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

## Summary by CodeRabbit

* **Refactor**
* Standardized telemetry to a unified tracking system for more
consistent analytics.
  * Simplified experiment exposure reporting for upgrade prompts.

* **New Features**
* More granular tracking for CSV import, cron job deletions, log drain
removals, DPA downloads/requests, and pricing CTAs.
  * Assistant now classifies mutation queries more precisely.

* **Bug Fixes**
* Improved default-privileges exposure logic on Vercel deployments
(skips when org missing).

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45964)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-18 18:21:58 +08:00
Gildas Garcia 5d97339d41 chore: remove <Select> _Shadcn_ suffix (#45988)
## Problem

The `_Shadcn_` suffix isn't needed anymore on `Select` components

## Solution

Remove it. No other changes

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

## Summary by CodeRabbit

* **Refactor**
* Updated internal component architecture to standardize and simplify
the codebase. These changes improve code maintainability and consistency
across the application without affecting existing functionality or user
experience.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45988)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-15 16:39:57 +02:00
Gildas Garcia 86a3f8b03d chore: upgrade to react-19 (#45886)
- Most changes are related to either types or `useRef` usages (it now
requires an initial value).
- also updated `vaul` to its latest version and haven't noticed any
change ([design-system
demo](https://design-system-git-react-19-supabase.vercel.app/design-system/docs/components/drawer))

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

* **New Features**
  * Upgraded workspace to React 19.

* **Bug Fixes**
* Improved null-safety and ref handling across editors, UI components,
shortcuts, and markdown/image rendering to reduce runtime errors.
* Safer event/timeout/interval cleanup and more robust command/context
handling.

* **Chores**
  * Bumped vaul dependency versions.

* **Documentation**
* Type and TypeScript accuracy improvements for clearer developer
feedback.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45886)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-15 16:04:41 +02:00
Gildas Garcia d0fd4478c0 chore: migrate Popover usages to Shadcn components (#45980)
## Problem

We have multiple Popover components

## Solution

- [x] migrate Popover usages to Shadcn components
- Migrated JSON and text editor in the `TableEditor` (inline row
edition)
  - Migrated the template popover in the logs explorer templates page
- [x] remove `_Shadcn_` suffix from Popover components (renaming +
prettier)

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

* **Refactor**
* Unified popover implementation across the app and design system;
dropdowns, calendars, menus and tooltips now use a consistent popover
API with no visual or interaction changes.

* **Chores**
* Minor prop typing update for the logs date-picker to align with the
consolidated popover content type.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45980)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-15 15:20:28 +02:00
Gildas Garcia 4e86c39ea1 chore: remove <ContextMenu> _Shadcn_ suffix (#45971)
## Problem

The `_Shadcn_` suffix isn't needed anymore on `<ContextMenu_Shadcn_>`
and related components

## Solution

Remove it. No other changes

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

* **Refactor**
* Replaced legacy context-menu component variants with the unified UI
context-menu components across the app for consistent rendering and
imports; behavior and menu content remain unchanged.
* **Tests**
* Updated a test mock to track the unified context-menu component mount
count.
* **Chores**
* Simplified UI package re-exports to expose the canonical context-menu
symbols.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45971)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-15 15:09:25 +02:00
Gildas Garcia 0713a1efc1 chore: remove shadcn suffix for Input, Textarea, Alert and Collapsible (#45867)
## Problem

Now that we migrated old components to their new shadcn alternatives, we
don't need the `_Shadcn_` suffix anymore.

## Solution

Remove it

<img width="659" height="609" alt="image"
src="https://github.com/user-attachments/assets/2d7271a9-066a-4dcc-92fe-729b106d2c2f"
/>
2026-05-15 14:55:37 +02:00
Jahanzaib iqbal 802be950ba fix(studio): fix grammar typo and add aria-labels for icon-only buttons (#45762)
## Summary

- Fix a grammar error in `GridError.tsx`: the `title` prop used `"is not
supporting on"` (wrong verb form) while the body text immediately below
in the same component already correctly reads `"is not supported on"`.
- Add `aria-label` to two icon-only `<Button>` elements in the table
grid editor — `RefreshButton` and the TextEditor expand button — which
had no accessible name for screen readers. Tooltip content alone is not
announced by assistive technology (WCAG 2.1 §4.1.2).

## Changes

- `apps/studio/components/grid/components/grid/GridError.tsx` — grammar
fix (`supporting` → `supported`)
- `apps/studio/components/grid/components/header/RefreshButton.tsx` —
add `aria-label="Refresh table data"`
- `apps/studio/components/grid/components/editor/TextEditor.tsx` — add
`aria-label="Expand editor"`

## Test plan

- [ ] No logic changed; UI text and accessibility attributes only
- [ ] Visually identical for sighted users
- [ ] Screen reader users can now identify both icon-only buttons by
their accessible name

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

## Summary by CodeRabbit

## Release Notes

* **Bug Fixes**
  * Corrected error message text for invalid sorting operations.

* **Accessibility**
* Added descriptive labels for screen readers to the "Expand editor" and
"Refresh table data" buttons.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45762)

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-15 11:21:51 +02:00
Charis d4079083fc chore(studio): drop @supabase/postgres-meta in favor of @supabase/pg-meta (#45844)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Refactor / dependency cleanup.

## What is the current behavior?

`apps/studio` lists both `@supabase/pg-meta` (workspace package) as a
runtime dep and `@supabase/postgres-meta` (external npm package,
`^0.64.4`) as a devDependency. The external package is used only for
type imports across 44 files — there is no runtime usage and no codegen
pipeline that needs it.

## What is the new behavior?

Every `Postgres*` type import (`PostgresTable`, `PostgresColumn`,
`PostgresPolicy`, `PostgresTrigger`, `PostgresView`,
`PostgresMaterializedView`, `PostgresForeignTable`, `PostgresSchema`,
`PostgresPublication`, `PostgresRelationship`, `PostgresPrimaryKey`) is
replaced with its `PG*` counterpart from `@supabase/pg-meta`, and the
external dep is removed from \`apps/studio/package.json\`. Top-level
type re-exports were added to \`packages/pg-meta/src/index.ts\` so
consumers can import directly from the package root.

Two latent issues surfaced by the stricter pg-meta types are also fixed:
- \`data/foreign-tables/foreign-tables-query.ts\` was casting
foreign-table results as \`PostgresView[]\`; corrected to
\`PGForeignTable[]\`.
- \`pg-meta\`'s \`PGTrigger\` Zod schema declared
\`orientation\`/\`activation\` as \`z.string()\`, inconsistent with
pg-meta's own \`getDatabaseTriggerUpdateSQL\` helper that requires the
narrow literal unions; tightened to \`z.enum\`.

## Additional context

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

## Summary by CodeRabbit

* **Chores**
* Updated internal TypeScript type definitions across the codebase to
use the latest type system from `@supabase/pg-meta`.
  * Removed `@supabase/postgres-meta` dependency.
* Enhanced type validation for database triggers and schemas to enforce
stricter constraints.

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45844)

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-13 16:07:10 +00:00
Gildas Garcia 678aec3845 chore: migrate Input usages to Shadcn component in various screens/components (#45604)
## Screenshots

### Table editor: foreign record selector
Before:
<img width="802" height="213" alt="image"
src="https://github.com/user-attachments/assets/82ee3ce6-ac72-4b49-b1b0-2e635688cbb1"
/>

After:
<img width="609" height="194" alt="image"
src="https://github.com/user-attachments/assets/e9cc09c1-1c6b-4099-8cae-abe08f50fda9"
/>


### Account - Add TOTP
Before:
<img width="527" height="679" alt="image"
src="https://github.com/user-attachments/assets/b9f4a626-e24b-46e3-8385-700ef181308b"
/>

After:
<img width="531" height="684" alt="image"
src="https://github.com/user-attachments/assets/549745a7-9655-4a7d-9e0e-51f75b6a1c61"
/>

### Organisation Audit Logs Details
Before:
<img width="673" height="1321" alt="image"
src="https://github.com/user-attachments/assets/0bb360cf-6f27-4574-b9af-485a3836b17b"
/>

After:
<img width="669" height="1273" alt="image"
src="https://github.com/user-attachments/assets/0382c662-e270-41fd-a8ee-08528dedfce3"
/>

### Data API Integration Docs
Before:
<img width="1115" height="891" alt="image"
src="https://github.com/user-attachments/assets/db0c7698-53b7-4422-aac3-5e674b0bf151"
/>

After:
<img width="1193" height="1272" alt="image"
src="https://github.com/user-attachments/assets/927e5c43-413b-49c1-9b71-8ab628179c70"
/>

### Edge Function Edit Secret
Before:
<img width="599" height="255" alt="image"
src="https://github.com/user-attachments/assets/d6aa2f87-e247-4724-9e43-02b71933241c"
/>

After:
<img width="596" height="261" alt="image"
src="https://github.com/user-attachments/assets/d94acb41-07e1-497f-9697-830390526f4a"
/>

### JWT Key Details
Before:
<img width="536" height="549" alt="image"
src="https://github.com/user-attachments/assets/43672adc-dc0e-4e65-b7d4-b4537d22f6ea"
/>

After:
<img width="523" height="517" alt="image"
src="https://github.com/user-attachments/assets/e501e8a8-7f41-46a0-bb69-d240cea594f0"
/>

### Realtime Filter Popover
Before:
<img width="403" height="576" alt="image"
src="https://github.com/user-attachments/assets/73842450-ba87-456b-98fc-625b99149449"
/>

After:
<img width="387" height="564" alt="image"
src="https://github.com/user-attachments/assets/f2b35035-947c-4342-84dd-3548f9bd5e9f"
/>

### Realtime broadcast message dialog
Before:
<img width="520" height="393" alt="image"
src="https://github.com/user-attachments/assets/4f4a1a93-e0cf-4268-ae4e-baf8b8a62e74"
/>

After:
<img width="525" height="392" alt="image"
src="https://github.com/user-attachments/assets/e1c1934a-1812-4013-8606-9b846dc2498d"
/>

### Impersonation Popover
Before:
<img width="604" height="501" alt="image"
src="https://github.com/user-attachments/assets/9abdc604-94f8-4ed4-9a95-4688e6504e76"
/>
<img width="587" height="599" alt="image"
src="https://github.com/user-attachments/assets/5293c80c-9abd-43eb-899f-da759c83b598"
/>

After:
<img width="594" height="585" alt="image"
src="https://github.com/user-attachments/assets/5eaf2162-2d7f-444c-9052-c9afb00080f6"
/>
<img width="590" height="597" alt="image"
src="https://github.com/user-attachments/assets/149dc7c1-689c-4e0f-a884-c6f5b0228ebc"
/>

### Storage move item
Before:
<img width="521" height="285" alt="image"
src="https://github.com/user-attachments/assets/7d0f945f-add5-412b-813a-9325b260ab28"
/>

After:
<img width="529" height="274" alt="image"
src="https://github.com/user-attachments/assets/ab0891a1-b31b-40b6-be53-92afc95095ea"
/>

### Table Editor - Spreadsheet import
Before:
<img width="673" height="506" alt="image"
src="https://github.com/user-attachments/assets/7a722908-10c2-4c04-95fb-b12d3c23557c"
/>

After:
<img width="671" height="638" alt="image"
src="https://github.com/user-attachments/assets/689b1fb6-031c-4a02-9e7f-739356c1453d"
/>

### Org Billing downgrade survey
Before:
<img width="788" height="655" alt="image"
src="https://github.com/user-attachments/assets/c7a0d4c6-e9b9-4c6c-9cf1-e7d05016233f"
/>

After:
<img width="1630" height="1354" alt="image"
src="https://github.com/user-attachments/assets/e3f5473b-db9a-42b1-9242-40480c25fc02"
/>

### Project API Docs
Before:
<img width="1030" height="396" alt="image"
src="https://github.com/user-attachments/assets/95643b21-811a-4ba7-918a-5e655c262ac1"
/>

After:
<img width="1012" height="457" alt="image"
src="https://github.com/user-attachments/assets/d5559646-bb89-43b6-ad62-c5684b54b3fb"
/>


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

* **Refactor**
* Standardized form field layouts across panels, dialogs, and modals for
a more consistent editing and reading experience.
* Replaced several Input-based textareas with dedicated
TextArea/ExpandingTextArea controls and aligned labels with wrapper
layouts for clearer accessibility.
* Introduced grouped/composable input controls, added additional
read-only detail fields and labeled value/copy blocks, and tightened
header/layout spacing and control alignment.
  * Swapped notice styles for improved warning/admonition presentation.

* **Chores**
  * Removed a deprecated AutoTextArea component.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-07 17:07:11 +02:00