## Context
There's a chance users may run into tax ID issues when upgrading a plan
as such:
<img width="412" height="120" alt="image"
src="https://github.com/user-attachments/assets/4c559ae0-d942-4c10-b83a-c5944a2a49ee"
/>
Adding a CTA here to guide users and mitigate confusion on how to
proceed to remediate
<img width="399" height="147" alt="image"
src="https://github.com/user-attachments/assets/3bcaca14-bd77-4168-b9ab-cd6b75f79e24"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved billing-profile validation feedback by standardizing error
messaging for tax ID vs. billing address country mismatches.
* Added an in-toast “Update tax ID” action to guide users directly to
the fix.
* Updated the billing dialog’s close behavior so it returns users to the
relevant address section (including scrolling to it automatically).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- Downgrading to Free tier is blocked server-side when an org has an
active branch, but the resulting error toast in `ExitSurveyModal.tsx`
used the default 4s toast duration, making it easy to miss.
- Adds `duration: 10_000, dismissible: true`, matching the pattern
already used for other important billing error toasts
(`org-subscription-update-mutation.ts`, `NewOrgForm.tsx`).
Fixes FE-3882
## Test plan
- [ ] Attempt to downgrade an org with an active branch to Free tier and
confirm the error toast stays visible for 10s and can be dismissed
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved the downgrade error message to stay visible longer and be
easier to dismiss, making failures clearer for users.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
App-level fixes that reproduce on BOTH the Next and TanStack builds —
split out of #47657 (which stays TanStack-only) for reviewability. All
were found by a full-site click-through of the dashboard.
## Invalid HTML nesting (React 19 "will cause a hydration error" console
errors)
- **FormLayout description rendered in a `<p>`**
(`packages/ui-patterns`): consumers pass arbitrary JSX (the RowEditor's
`created_at` timezone note passes a `<div>` with `<p>`s) →
`<p>`-in-`<p>` / `<div>`-in-`<p>`. Container is now a `<div>` with
identical classes (Tailwind preflight makes them render the same).
- **Switch toggles nested inside Tooltip trigger buttons**
(button-in-button) in ColumnEditor ("Allow Nullable" + "Is Unique"),
ExtensionRow, and PublicationsTableItem → repo-standard `TooltipTrigger
asChild` + `<div>` wrapper.
- **Saved log queries rendered a `<div>` directly inside `<tbody>`**
(`/logs/explorer/saved`) → rows are now proper `<tr><td colSpan>`
wrappers; the component itself is untouched (it's valid in its sidebar
usage).
- **Nested anchors in observability metric cards**: a card-level
`<Link>` wrapped MetricCard's "More information" `<Link>` (identical
URLs) → the chevron affordance renders as a `<span>` when no `href` is
passed; clicks bubble to the card link, tooltips preserved.
Design-system standalone usage unaffected.
- **`objectFit="cover"` passed to modern `next/image`** on the featured
integration card (unknown-prop warning) — the className already had
`object-cover`; prop dropped.
## Ghost dead-snippet after deletion
Deleting the active SQL snippet left its id in `useDashboardHistory`
(`history.sql`), so the "SQL Editor" nav item navigated to
`/sql/<deleted-id>` — content fetch 404s, no editor pane renders, and a
phantom tab reappears. Fixed both ends: delete flows now purge dashboard
history (and the tabs store clears a stale `previewTabId`), and
`/sql/[id]` treats a snippet 404 as "clean up + `router.replace` to
`/sql/new` + toast" instead of rendering the dead state. Unit tests for
the store/history cleanup.
## `pg-meta` migrations query 400s on every project load
`ActivityStats` on project home runs the migrations list query, whose
SQL was a bare `select * from supabase_migrations.schema_migrations` —
that table only exists once a migration has run, so every other project
logged a failed `?key=migrations` request on every load (visible in
production consoles too). The SQL is now guarded with `to_regclass` +
`query_to_xml` (same pattern as the advisor lints' `storage.buckets`
guard), returning zero rows instead of erroring; legacy version-only
tables still work. Tested against real dockerized Postgres (absent
table, populated ordering, special chars, legacy schema) + MSW hook
tests.
Found and verified via /test-supabase-local (browser click-through +
console audit on both builds).
## To test
Console must stay free of React DOM-nesting errors ("cannot be a
descendant of" / "cannot contain a nested") on each surface:
1. Table editor → Insert row panel (`created_at` field renders its
timezone note) and Edit column panel ("Allow Nullable"/"Is Unique"
tooltips still hover).
2. `/database/extensions` and `/database/publications` → toggle switches
render, tooltips hover.
3. `/logs/explorer/saved` (with ≥1 saved query) → rows render full-width
inside the table, hover shows Actions.
4. `/observability` → no nested-anchor error on load; card body click
and the chevron both navigate; label help-icons still show tooltips.
5. `/integrations` → no `objectFit` unknown-prop warning; featured card
images still cover.
6. **Ghost snippet**: open a SQL snippet → delete it via the sidebar →
click the "SQL Editor" nav item → lands on `/sql/new` (no phantom tab,
no 404 content fetch). Direct-load `/sql/<random-uuid>` → toast +
redirect to `/sql/new`.
7. **Migrations 400**: load project home with a project that has never
run a migration → the `pg-meta/<ref>/query?key=migrations` request
returns **200** with `[]` (previously a 400 on every load). Database →
Migrations still lists real migrations when they exist.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Summary by CodeRabbit
* **Bug Fixes**
* Deleted SQL snippets are fully removed from dashboard history and
stale editor/tab state; users are redirected with a toast.
* Closing preview tabs no longer leaves stale references.
* Improved toggle/tooltip/dialog interactions to avoid broken UI,
including metric headers showing tooltips even without direct links.
* Migrations display safely when migration tables/relations are missing.
* **UI Improvements**
* Refreshed layout for saved queries, form descriptions, and integration
imagery.
* **Tests**
* Added coverage for snippet history cleanup, tab removal, migrations
SQL behavior, and query edge cases.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---
### Review feedback: `query_to_xml` breaks on Multigres (Ivan)
The defensive migrations query (added here to stop the `?key=migrations`
400 when the table doesn't exist yet) originally guarded with
`query_to_xml`, which is forbidden through Multigres's pooler (MUL-736 /
PSQL-1318). Rewritten without `query_to_xml`/`xmltable` using the
splinter#170 pattern: a PL/pgSQL `do` block guarded by `to_regclass`
(PL/pgSQL defers planning, so a missing table never errors) stashes the
rows into a transaction-local GUC via `set_config`, and a trailing
`select` reads them back with `jsonb_array_elements`. Verified that
postgres-meta sends the whole SQL as one simple-query string → single
implicit transaction → the local GUC survives to the `select` and
doesn't leak into the pooled connection. 6/6 dockerized-Postgres tests
(absent table → `[]`, populated/ordered/special-chars, legacy
version-only table, full pg-meta-shaped multi-statement string, GUC
non-leakage).
Note (out of scope, pre-existing):
`packages/pg-meta/src/sql/studio/advisor/lints.ts` still uses
`query_to_xml` — a separate pre-existing Multigres risk that should get
its own splinter-pattern sync.
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
Co-authored-by: Saxon Fletcher <saxonafletcher@gmail.com>
## 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
## Problem
Knip reports many duplicate exports (both named and default). Besides,
we're moving away from default exports and even have an eslint rule to
enforce it on new code.
## Solution
- Cleanup those exports
- Update imports when necessary
No functional changes. If it builds, it's fine
### Summary
This PR trims the Tax ID value on the frontend so that whitespace-only
entries (e.g. " ") are correctly treated as "not set" instead of a valid
value.
Previously the "is the Tax ID set?" checks relied on string
length/truthiness, so whitespace-only input slipped through as a real
value - bypassing validation and getting persisted.
### Testing
- Subscription upgrade & top-up forms: verified the form no longer
submits when only whitespace is entered for the Tax ID. The validation
message now shows.
- Billing address form: no inline message is shown, but the Tax ID is
submitted as null, which clears it. This is unchanged from current
behaviour.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Tax ID values are now trimmed before validation and submission,
reducing errors caused by accidental leading or trailing spaces.
* Billing and payment flows now consistently use the cleaned Tax ID
value when deciding whether to save or send it.
* Customer tax ID details passed to payment setup now reflect the
trimmed value, helping avoid mismatches with external payment
processing.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
**Stack 1/6** of the TanStack Start migration (#46424), split into
reviewable, independently-mergeable PRs.
> [!IMPORTANT]
> **Next stays the default and only active framework after this PR.**
This wires up the Vite/TanStack-Start build pipeline behind the
`STUDIO_FRAMEWORK` flag, but there are no TanStack routes yet — so the
TanStack build isn't functional or tested until later PRs in the stack.
Nothing about the Next build, dev, or deploy changes behaviourally here.
## What's in this PR
- **Dispatch:** `dev`/`build`/`start` now go through
`scripts/dispatch.js`, which runs the Next variant unless
`STUDIO_FRAMEWORK=tanstack`. The original commands are preserved as
`dev:next`/`build:next`/`start:next`.
- **Build pipeline:** `vite.config.ts`, `serve.js`, `smoke-server.mjs`,
vite/tanstack deps, `turbo.jsonc`.
- **`tsconfig.json`:** `jsx: react-jsx`, `moduleResolution: Bundler`,
`target: ES2022`. Because `include` is `**/*.ts(x)`, this re-typechecks
the whole app, so the companion adaptations below land with it.
- **Shared adaptations (companions to the tsconfig change):**
`BufferSource` casts, `packages/ui` unused-`React` import removals, etc.
- **Routing/middleware plumbing:** `next.config.ts` +
`redirects.shared.ts` (redirect rules now shared with `vercel.ts`),
`proxy.ts`/`start.ts` middleware + `hosted-api-allowlist.ts`.
## Verification
Run locally off `master`: frozen install ✓, `studio` typecheck ✓, **Next
build ✓** (compiles + generates all routes), lint ratchet ✓ ("some rules
improved"), prettier ✓.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added a hosted API endpoint allowlist to return 404 for non-supported
`/api/*` routes.
* Introduced a TanStack route-migration checklist and expanded TanStack
Start routing support.
* **Improvements**
* Enhanced deployment refresh/detection by tightening cookie handling
for “latest deployment” updates.
* Centralized redirect/maintenance-mode rules for consistent platform vs
self-hosted behavior.
* Improved production serving with a dedicated static + proxy server and
a post-build smoke test.
* **Dependencies**
* Updated TanStack-related packages and React Table/query tooling
versions.
* **Documentation / Chores**
* Updated formatting and tooling config; added shared build environment
parsing utilities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
Replaced the `DowngradeModal`'s `AlertDialog` with a normal `Dialog`,
since `AlertDialog` won't close if you click outside the modal by
design.
Left is current PR, right is staging:
<img width="1600" height="537" alt="Screenshot 2026-06-18 at 10 07 46"
src="https://github.com/user-attachments/assets/ce1bcc17-d1c9-4fcd-ad3b-f2fcfd8824f6"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Updated the downgrade confirmation modal to use the newer dialog UI
components.
* Preserved the existing warning and checklist content (including
project impact and email/reset notices) and kept the same confirm/cancel
behavior and disabled state handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com>
## 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>
The usage page link in the UpcomingInvoice billing breakdown used the
incorrect path, resulting in a 404. Corrected to to match the rest of
the app.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Corrected the usage page link shown in the billing breakdown tooltip
for non-compute items so it now points to the proper /org/... URL,
ensuring users are taken to the correct usage page from billing
documentation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Extracts the Cancellation Flow from the subscriptions side panel and
adds a new button that initiates the flow (old journey is still
possible):
(screenshots see below)
Verified manually:
- ✅ confirmed the old downgrade flow works, Team -> Pro; Pro -> Free
- ✅ confirmed the new downgrade flow works
- ✅ button does not show up when on free plan; no flicker
- ✅ button does not show up on enterprise/platform plan
- ✅ verified button is disabled when managed by AWS marketplace
(hardcoded in `useSelectedOrganizationQuery`)
- ✅ verified button is disabled if `canUpdateSubscriton` is false,
hardcoded in `useAsyncCheckPermissions`
- ✅ modal for exceeding-free-projects shows up
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added a guided subscription cancellation flow with confirmation steps,
member/usage checks, and an exit survey.
* Exposed a visible "Cancel Subscription" control in billing settings,
enabled/disabled with contextual tooltip messaging.
* **Improvements**
* Downgrade/exit survey confirm action can be disabled when appropriate;
exit survey confirm label updated to "Downgrade Now".
* **Chores**
* Added frontend telemetry for cancellation button interactions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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 -->
[](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>
## What kind of change does this PR introduce?
Feature / abuse-prevention update. Resolves DEPR-198.
## What is the current behaviour?
Free projects using Supabase's built-in email service can edit raw Auth
email template subjects and HTML in Studio. That is the risky cohort
this project is trying to constrain.
## What is the new behaviour?
### Template editing restrictions
For free projects using Supabase's built-in email service, Studio keeps
Auth email templates viewable and previewable but disables subject/body
editing and saving. Editing is unlocked by setting up Custom SMTP,
configuring a send-email hook, or upgrading to a paid plan.
**Grandfathering:** projects created before `2026-06-01T00:00:00Z` (the
platform enforcement cutoff) are exempt; their editing UI stays
unlocked. This mirrors `FREE_TIER_TEMPLATE_BLOCK_CUTOFF_DATE` in the
platform PR exactly.
| After |
| --- |
| <img width="1024" height="759" alt="Emails Authentication Fizz Test
Supabase-173BB09B-0FB9-4133-8202-9E310DDB347A"
src="https://github.com/user-attachments/assets/c966212d-ed0c-443b-8197-440cc2937ef6"
/> |
| <img width="1024" height="759" alt="Emails Authentication Fizz Test
Supabase-CD5845EB-0E45-4779-8989-44E775B2411A"
src="https://github.com/user-attachments/assets/055a64d6-b5e8-4d37-a261-6e280f04536a"
/> |
### Warning dialogs on transitions that reset templates
Two flows now surface a warning before the user commits to a state
change that resets their custom email templates to defaults:
1. **Disabling custom SMTP** (SMTP settings page): a confirmation dialog
warns that templates will be reset to defaults and the email rate limit
reduced to 2 per hour. On confirm, Studio resets all 13 templates via
the existing per-template reset endpoint (`Promise.allSettled`). The
"won't be able to edit" sentence is shown only for post-cutoff projects;
grandfathered projects skip it. The corresponding server-side
enforcement is in the Platform PR:
https://github.com/supabase/platform/pull/33129
2. **Downgrading to the Free plan** (billing settings): an admonition in
the existing downgrade confirmation modal warns that custom templates
will be reset to defaults and won't be editable without custom SMTP. The
admonition is shown only when the org has at least one post-cutoff
project; orgs whose projects are all grandfathered skip it.
| Custom SMTP | Downgrading |
| --- | --- |
| <img width="862" height="586" alt="66764"
src="https://github.com/user-attachments/assets/6470c8a6-2f79-40a5-ad3b-bfe5b0ba9c54"
/> | <img width="1268" height="1552" alt="CleanShot 2026-05-22 at 17 28
37@2x-FEB1901E-38E6-42DF-8C27-0A036D8A1B94"
src="https://github.com/user-attachments/assets/e8caa9e6-c3ed-4787-b771-af77a43eb854"
/> |
### Informational admonition when enabling SMTP
When a user enables custom SMTP for the first time, a sandwiched
admonition above the save footer informs them that the email rate limit
will be increased to 30 per hour and can be adjusted.
_This is just a minor cosmetic change, unrelated to the email template
disabling. Sorry._
| Before | After |
| --- | --- |
| <img width="1024" height="759" alt="Emails Authentication Chisel
Toolshed Supabase-54317D18-803C-4A58-8211-2359355D083B"
src="https://github.com/user-attachments/assets/29eff649-02dc-40f3-a379-0b4d484a76c7"
/> | <img width="1024" height="759" alt="Emails Authentication Chisel
Toolshed Supabase-9E12399E-E9FB-4F9A-B029-A08008EA4B50"
src="https://github.com/user-attachments/assets/e542ed86-4da6-407e-8293-0f4c0f071e18"
/> |
## How to test
All existing projects pre-date the enforcement cutoff
(`2026-06-01T00:00:00Z`) and are grandfathered, so the restriction UI
won't appear by default. To force the restricted state locally,
back-date the cutoff in one file:
In
`apps/studio/components/interfaces/Auth/EmailTemplates/EmailTemplates.utils.ts`,
temporarily change:
```ts
export const FREE_TIER_TEMPLATE_BLOCK_CUTOFF_DATE = '2026-06-01T00:00:00Z'
```
to:
```ts
export const FREE_TIER_TEMPLATE_BLOCK_CUTOFF_DATE = '2025-01-01T00:00:00Z'
```
Revert before committing. With the cutoff back-dated, use a free-plan
project and:
- **Template restriction + admonition:** navigate to Authentication >
Emails with no custom SMTP configured. Subject/body fields should be
read-only and the "Set up SMTP" admonition should appear, with its
dropdown offering upgrade and send-email hook options.
- **SMTP disable warning:** enable custom SMTP on a project, then
disable it via Authentication > SMTP Settings. The confirmation dialog
should warn that templates will reset to defaults and that editing will
be restricted after disabling.
- **Downgrade warning:** in billing settings, initiate a downgrade to
the Free plan. The downgrade modal should include an admonition warning
about template reset and restricted editing (only if the org has at
least one post-cutoff project).
## Additional context
The default Auth email template copy was also improved across docs,
examples, and UI library snippets (separate prior commits).
The per-template reset button (`ResetTemplateDialog`) was migrated to
the async `AlertDialogAction` pattern introduced in #45960; the dialog
stays open and shows a loading state while the reset is in-flight,
closes on success, and stays open on error.
Closes PRODSEC-183
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Stephen Morgan <stephen@doublethink.co.nz>
## Summary
I migrated every `useSendEventMutation` call site in `apps/studio` to
`useTrack`, deleted the legacy hook, and added a lint guardrail so it
can't return. `useTrack` is the type-safe replacement: it auto-injects
`groups: { project, organization }` from the selected project/org and
types `action` + `properties` against `TelemetryEvent`. Existing call
sites built groups manually and were not type-checked at the action
level. The migration covers 81 files (60 trivial swaps, 9 org-only, 3
pre-auth, 5 bespoke, 4 test mocks).
## Changes
- Migrated trivial call sites across `pages/project/[ref]`,
`components/interfaces/*` (Reports, Storage, Realtime/Inspector,
SQLEditor, Functions, EdgeFunctions, Integrations, ProjectAPIDocs,
Branching/BranchManagement, TableGridEditor, Connect, Docs, Auth,
Support, Home, ProjectHome, App), `components/layouts/*`, and
`components/ui/*`.
- Migrated org-only sites (`Organization/Documents/*`,
`Organization/BillingSettings/Subscription/*`,
`Organization/SecuritySettings.tsx`,
`Account/Preferences/DashboardSettingsToggles.tsx`) by dropping the
manual `groups: { organization: ... }` and letting `useTrack`
auto-inject. Verified `useSelectedProjectQuery` is disabled on org
routes (gates on URL `[ref]`).
- Migrated pre-auth sites (`SignInForm.tsx`, `sign-in-mfa.tsx`,
`profile.tsx`) where neither project nor org is resolved.
- Bespoke handling:
- `execute-sql-mutation.ts` and `table-row-create-mutation.ts`: pass `{
project: projectRef }` via `groupOverrides` since the mutation can
target a non-selected project ref.
- `useStudioCommandMenuTelemetry.ts`: kept a direct `sendTelemetryEvent`
call because studio groups must override pre-built event groups
(opposite of `useTrack`'s override direction).
- `AIAssistantOption.tsx`: passes sentinel-aware `groupOverrides` so
`NO_PROJECT_MARKER`/`NO_ORG_MARKER` continue to suppress group emission.
- `SidePanelEditor.utils.tsx`: utility functions `createTable` and
`updateTable` now take a `track: Track` parameter (threaded from
`SidePanelEditor.tsx`); dropped the `organizationSlug` arg since groups
are no longer assembled manually.
- Branch-event attribution: preserved `parentProjectRef` overrides on
`branch_updated`, `branch_merge_completed`, `branch_merge_failed`,
`branch_merge_submitted`, `branch_delete_button_clicked`,
`branch_review_with_assistant_clicked`, and
`branch_*_merge_request_button_clicked`. Original code grouped these
under the parent (production) project, not the branch ref;
auto-injection would have shifted them onto the branch.
- Switched 4 test mocks from `@/data/telemetry/send-event-mutation` to
`@/lib/telemetry/track`. Removed obsolete tests around manual groups and
`try/catch` on telemetry rejection.
- Deleted `apps/studio/data/telemetry/send-event-mutation.ts`. The
deleted module is its own guardrail: any reintroduction of the import
fails at TypeScript module resolution before lint runs.
## Testing
Tested on preview deploy:
- [x] SQL editor `CREATE TABLE` fires `table_created` with method
`sql_editor` and `groups.project` set to the mutation's `projectRef`.
- [x] Table editor creates a table from the side panel; `table_created`
fires from `SidePanelEditor.utils` via threaded `track`.
- [x] Help button (`/project/[ref]/...`) fires `help_button_clicked`
with auto-injected project + org groups.
- [x] Sign-in form fires `sign_in` with empty groups (pre-auth,
expected).
- [x] Org documents page (`/org/[slug]/documents`) fires
`document_view_button_clicked` with org group only, no stale project
ref.
- [x] Command menu (`Cmd+K`) inside a project still fires
`command_menu_opened` with studio's project/org overriding any
event-supplied groups.
- [x] Support form "Ask the Assistant" without selected org fires
`ai_assistant_in_support_form_clicked` with no project/org groups
(sentinels suppress).
- [x] On a branch, "Update branch" / "Merge branch" / "Close merge
request" events fire with `groups.project` set to the parent project
ref, not the branch ref.
Local checks:
- [x] 22/22 tests pass across the 4 updated test files
(`SidePanelEditor.utils.createTable`, `EdgeFunctionRenderer`,
`LayoutSidebar`, `PlanUpdateSidePanel`).
- [x] `rg useSendEventMutation apps/studio` returns 0 hits.
## Linear
- fixes GROWTH-860
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Standardized telemetry across the Studio to a unified tracking system;
events now send simplified payloads with less contextual/grouping data.
* No user-facing flows changed; UI behavior, permissions, and
interactions remain the same.
* **Tests**
* Updated telemetry mocks and tests to align with the new tracking
approach.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46140?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 -->
## Problem
Organization settings still uses the deprecated `Modal` for:
- downgrading subscription
- requesting feedback after downgrading
- showing an alert about members limit
- requesting feedback after upgrading
- deleting a published OAuth app
- showing preview of a new OAuth app
- Revoking an OAuth app
## Solution
- use `Dialog` instead
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Replaced legacy modal UI with the app's modern dialog/alert-dialog
components across billing and OAuth settings (upgrade/downgrade, exit
survey, members-limit, delete/revoke, preview), keeping existing content
and flows.
* Confirm/cancel flows updated for more reliable async handling and
clearer loading/disabled states during actions.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46332?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 -->
## Problem
The `_Shadcn_` suffix isn't needed anymore on `Command` components
## Solution
- Remove the `_Shadcn_` suffix
- Simplify UI package exports
- Apply prettier
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Simplified command component imports and exports across the UI library
by removing internal naming aliases and adopting direct component
references. Updated the public UI package barrel export to use wildcard
re-exports for cleaner API surface.
<!-- review_stack_entry_start -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46153?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 -->
## 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 -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45988)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
- 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 -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45886)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## 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 -->
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45980)
<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Related PR: https://github.com/supabase/supabase/pull/45803
Opting for a simpler way to prevent requesting billing owners for
downgrading of plan as such:
<img width="933" height="258" alt="image"
src="https://github.com/user-attachments/assets/604b8c2f-9341-4aec-885c-e2d9d2861b9f"
/>
Currently we're incorrectly showing a "Request to upgrade to Free" CTA
## To test
- [ ] For a pro plan or above organization, and a user that has a
"Developer" role, ensure that you're not able to downgrade the org nor
send a upgrade request
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Clarified CTA behavior for users without billing update permission:
downgrade actions now show a disabled button with an explicit tooltip,
while non-downgrade upgrade attempts prompt a request to billing owners.
Tooltip messaging has been refined across enterprise, free-tier, and
marketplace-managed plans for clearer guidance.
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45823)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem
We have multiple `Collapsible` components.
## Solution
Reduce their number by using only the one from shadcn.
I haven't noticed any visual nor functional changes.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Migrated expandable/collapsible UI to a unified shadcn-based
implementation for more consistent expand/collapse behavior across the
app.
* **Style**
* Updated listbox check icon sizing and removed obsolete collapsible
open/close animations.
* **Chores**
* Removed deprecated collapsible variants and consolidated UI component
surface for simpler maintenance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Show notice when plan fee is prepaid for the upcoming invoice
When a subscription's plan fee has already been billed for the current
period (e.g. transitioning to in-arrears billing), the upcoming invoice
no longer contains a plan line item. Previously this rendered as an
empty plan row with a `-`, which was confusing.
<img width="2178" height="538" alt="image"
src="https://github.com/user-attachments/assets/1fa289d9-60ae-48b1-b779-34770bc2c242"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Billing breakdown now detects when the plan fee was already paid
upfront, hides the redundant plan line, and notes only usage will be
invoiced; shows the organization plan name when available.
* Backup restoration: added an optional recovery time target for
physical backups.
* Expanded supported AWS instance types for deployments.
* **UI**
* Compute and Replica Compute docs links now use inline linking for a
smoother in-app experience.
[](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45765)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
## Summary
- Display a "Prepaid Credits" line in the upcoming invoice breakdown,
shown directly below Current Costs when the upcoming invoice contains
a `Prepaid Credits` line item
- Surfaces the credit amount being applied (e.g. `-$300`) so users can
see how prepaid credits offset their projected bill
- Consolidates the projected tax items into the tooltip for `Projected
Costs`
<img width="1416" height="426" alt="image"
src="https://github.com/user-attachments/assets/b3455e82-d03b-40c3-ad5f-493a56004ddf"
/>
## Test plan
- [x] On an org with prepaid credits applied, verify the "Prepaid
Credits" row appears below Current Costs with the negative amount and a
tooltip showing the backend description
- [x] On an org without prepaid credits, verify the row is not rendered
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Summary by CodeRabbit
* **Improvements**
* Clarified the "Upcoming Invoice" explanatory copy for non–AWS
Marketplace-managed organizations: it now notes the invoice will
continue updating until the end of your billing cycle.
* Improved invoice breakdown: compute charges and compute credits are
distinguished, and a dedicated "Prepaid Credits" row is shown before
projected costs for clearer billing totals.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## 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 — copy + visibility logic on the org Usage page.
## What is the current behavior?
On `/org/<slug>/usage` during a grace period, customers see two banners
that read as contradictory:
1. *"Organization plan has exceeded its quota — grace period until
{date}."*
2. *"You have not exceeded your Pro Plan quota in this billing cycle."*
<img width="1680" height="372" alt="image"
src="https://github.com/user-attachments/assets/13826260-55dd-4b55-a3dc-5afc51e6436e"
/>
Both are individually correct. The first is sticky from the previous
cycle's overage (`org.restriction_status`); the second is a live scan
over the current cycle. Neither anchors to which cycle it's talking
about, so together they read like the dashboard contradicting itself.
Surfaced by support off SU-368527 and SU-368395.
## What is the new behavior?
- Top chrome banner copy: *"Organization exceeded its quota in the
previous billing cycle / You have a grace period until {date} to bring
usage back under quota."*
- Inline `<Restriction />` grace-period alert switches from "is over its
quota" to "went over its quota in the previous billing cycle." Same
temporal anchor.
- The "…in this billing cycle" summary line in `<TotalUsage>` is hidden
whenever `restriction_status` is set. Mirrors the precedence rule
`<Restriction />` already applies internally — backend status flag wins
over the live cycle scan.
<img width="1678" height="937" alt="CleanShot 2026-05-06 at 12 58 02"
src="https://github.com/user-attachments/assets/df55eaed-1029-4f39-bea0-df77bcc5151e"
/>
## Additional context
Left the `gracePeriodOver` copy alone on purpose — it doesn't make a
current-overage claim, so there's nothing to contradict, and adding
"previous cycle" would muddy which cycle "previous" refers to.
**Verified**
- Lint and typecheck pass on `apps/studio`.
**Before merge**
- [ ] Load a grace-period org locally: confirm new copy on top banner
and inline `<Restriction />`, and that the "not exceeded in this billing
cycle" line is gone.
- [ ] Copy review with support — happy to workshop wording.
GROWTH-823
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Updates**
* Updated grace period alert messaging to clarify organization quota
status
* Refined date formatting in billing restriction notifications
* Modified usage display to conditionally hide certain information when
account restrictions are active
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
## Context
Main fix is to ensure that the tooltip here is scrollable - but also
adding some refactors
This is the org billing page when downgrading an org
### Before
<img width="400" alt="image"
src="https://github.com/user-attachments/assets/6094c2e6-c1bb-460f-a2d2-347c1d7d2e77"
/>
### After
<img width="400" alt="image"
src="https://github.com/user-attachments/assets/9d0ac9a6-6e89-4758-af14-8144a8a86469"
/>
## Changes involved
- Use HoverCard for invoice estimate in plan confirmation dialog
- Also nudge the UI a little, e.g use a separate column for the compute
prices + adjust text color to improve clarity
- Refactor usage of `any` for some of the TS declarations
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added an invoice estimate tooltip in subscription settings showing
monthly charges with plan fees, combined compute rows, per-project
compute costs, optional compute credits, and a total monthly estimate.
* **Refactor**
* Simplified the plan update flow by consolidating subscription preview
handling and extracting the invoice UI into the new tooltip component.
* **Chores**
* Improved internal type definitions for subscription preview data and
pricing tier identifiers.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- **Subscription downgrade dialog**: The plan name row was being hidden
in the charge breakdown when `changeType === 'downgrade'`, so users
downgrading (e.g. Team → Pro) couldn't see which plan the cost referred
to. Removed the downgrade exclusion so the plan name row renders
consistently across upgrade/downgrade flows.
- **Credit Top Up dialog**: The submit button only
reflected `executingTopUp`/`paymentConfirmationLoading`, but
the `onSubmit` handler runs several async steps first (hCaptcha, billing
profile validation, Stripe `createPaymentMethod`) before the mutation
flips `isPending`. That left a clickable window where users could
trigger multiple top-ups. Added `form.formState.isSubmitting` to
both `loading` and `disabled` so the button is locked for the full
submit lifecycle.
## Test plan
- [ ] Downgrade from Team → Pro and confirm the Pro plan row appears in
the charge breakdown
- [ ] Open Credit Top Up, submit, and rapidly click the Top Up button —
verify only one charge is initiated
- [ ] Verify Top Up button shows a loading state immediately on click
(before the mutation starts)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Consistently show subscription plan cost during billing adjustments,
including downgrades.
* Improve Top Up button to reflect form submission state and prevent
duplicate submissions.
* **Style**
* Enhanced text contrast for better readability in billing information
displays.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
This PR migrates the whole monorepo to use Tailwind v4:
- Removed `@tailwindcss/container-queries` plugin since it's included by
default in v4,
- Bump all instances of Tailwind to v4. Made minimal changes to the
shared config to remove non-supported features (`alpha` mentions),
- Migrate all apps to be compatible with v4 configs,
- Fix the `typography.css` import in 3 apps,
- Add missing rules which were included by default in v3,
- Run `pnpm dlx @tailwindcss/upgrade` on all apps, which renames a lot
of classes
- Rename all misnamed classes according to
https://tailwindcss.com/docs/upgrade-guide#renamed-utilities in all
apps.
---------
Co-authored-by: Jordi Enric <jordi.err@gmail.com>
This PR preps the monorepo for a migration to Tailwind v4:
- Bump all Tailwind dependencies and libraries to the latest possible
version, while still compatible with Tailwind 3.
- Cleans up obsolete Tailwind 3 specific options and configs.
- Cleans up unused CSS files and fixes the CSS imports.
- Migrates all `important` uses in `@apply` lines to using the `!`
prefix.
- Move `typography.css` to the `config` package and import it from the
apps.
- Migrated all occurrences of `flex-grow`, `flex-shrink`,
`overflow-clip` and `overflow-ellipsis` since they're deprecated and
will be removed in Tailwind 4.
- Make the default theme object typesafe in the `ui` package.
- Migrate all `bg-opacity`, `border-opacity`, `ring-opacity` and
`divider-opacity` to the new format where they're declared as part of
the property color.
- Bump and unify all imports of `postcss` dependency.
## What kind of change does this PR introduce?
UI changes for Stripe-managed billing surfaces.
- Resolves DEPR-537
- Related to DEPR-538
## What is the current behaviour?
Stripe-connected organisations still look too self-serve in Studio.
- Payment Methods still reads mostly like ordinary Supabase card
management, even though billing is handled through a Shared Payment
Token via Stripe Projects
- invoice messaging still implies support is the path to changing
payment methods, even for Stripe-managed orgs
- the Subscription Plan flow still needs Stripe-specific guardrails so
users are redirected to the correct upgrade path rather than trying to
self-serve everything in Studio
- the base branch now correctly separates `integration_source` from
`billing_partner`, but this stacked work still needs to carry that split
through the Stripe billing-token surfaces
## What is the new behaviour?
This PR makes the Stripe-managed billing surfaces behave like
Stripe-managed billing surfaces, while leaving AWS and Vercel on the
existing `billing_partner` path.
- Payment Methods now keeps the familiar saved-card row, but augments
Stripe-managed rows with Shared Payment Token context, token status, and
Stripe Projects affordances
- Stripe-managed invoice messaging now points users to Stripe Projects
rather than to support for payment-method changes
- the Subscription Plan flow keeps the existing managed-billing shape,
with Stripe-specific guardrails layered in where plan changes should be
handled outside Studio
- AWS and Vercel continue to use the existing partner-managed alerts and
CTAs driven by `billing_partner` / `billing_via_partner`
| Subscription plan sheet |
| --- |
| <img width="1780" height="448" alt="CleanShot 2026-04-24 at 17 21
43@2x"
src="https://github.com/user-attachments/assets/34c0f3ba-fc42-4d07-97a2-0e4f4cefc55e"
/> |
| _Upgrade instructions_ |
| <img width="1786" height="460" alt="CleanShot 2026-04-24 at 17 20
12@2x"
src="https://github.com/user-attachments/assets/bb67c835-b9b2-4648-b0e1-9c2f8d2317d3"
/> |
| _Downgrade instructions_ |
> [!NOTE]
> The below screenshots are outdated. The _Shared Payment Token_
terminology has been removed in favour of more generic copy such as
_Stripe Projects token_.
| Stripe payment method states |
| --- |
| <img width="1436" height="234" alt="CleanShot 2026-04-23 at 19 03
49@2x"
src="https://github.com/user-attachments/assets/52ed7a00-dfba-4b66-9a07-a6346692d3c8"
/> |
| _Healthy_ |
| <img width="1434" height="224" alt="CleanShot 2026-04-23 at 19 04
50@2x"
src="https://github.com/user-attachments/assets/94efd943-b7bf-4da2-9e1b-1828aae97126"
/> |
| _Card expiring soon_ |
| <img width="1436" height="236" alt="CleanShot 2026-04-23 at 19 06
51@2x"
src="https://github.com/user-attachments/assets/272cb707-c724-4629-890e-853972e53a18"
/> |
| _Card expired_ |
| <img width="1308" height="238" alt="CleanShot 2026-04-23 at 19 07
21@2x"
src="https://github.com/user-attachments/assets/3eadd2a9-def3-4f43-850e-7d82adfb0b57"
/> |
| _Token expired_ |
## Dependencies
This PR is stacked on:
- #44328
It also depends on the private platform work that exposes Stripe project
connection state and SPT details:
- https://github.com/supabase/platform/pull/31874
- https://github.com/supabase/platform/pull/31940
## Platform dependency status
Most of the remaining platform work for this stack is now covered by the
private dependency below:
- https://github.com/supabase/platform/pull/31940
That PR is expected to provide the SPT details and paid-flow fixes this
Studio work depends on. In practice, the main caveat here is less
“Studio still needs a bunch of new platform work” and more “do not merge
this until `platform#31940` has landed and the end-to-end Stripe-managed
flow has been rechecked”.
## Local testing
Use the same local Stripe setup as the base branch, with
`integration_source: 'stripe_projects'` returned consistently for:
- `/platform/organizations`
- `/platform/organizations/:slug/projects`
- `/platform/projects/:ref`
For payment method demos, the temporary local mock currently lives in
private `platform` on:
- `/platform/organizations/:slug/payments`
That mock can be flipped between:
- healthy token + healthy underlying card
- healthy token + card expiring soon
- healthy token + expired card
- expired token
Then verify:
- the org and project connection affordances from #44328 still render
correctly
- Payment Methods shows Stripe-managed token context rather than
implying ordinary self-serve card management
- regression test ordinary non-Stripe payment methods too, to confirm
the standard saved-card row still renders with the existing `Expires:`
copy and no Shared Payment Token affordances
- invoice messaging points Stripe-managed orgs to Stripe Projects rather
than support
- Subscription Plan keeps the managed-billing guardrails for Stripe
- AWS and Vercel orgs still show the existing partner-managed messaging
rather than the Stripe-specific notices
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Stripe-managed organizations show Stripe Projects billing guidance,
replace in-app payment management with Stripe links, and adjust billing
copy.
* Payment methods support Shared Payment Tokens (SPTs): token
expiry/status badges with tooltips, “Handled via Stripe Projects”
indicator, token last4/expiry display, and disabled local update/delete
actions for SPTs.
* **API**
* Payments response now includes optional shared payment token details
for payment methods.
* **Documentation**
* Added links to Stripe Projects billing docs in relevant flows.
* **Tests**
* Updated and added tests covering Stripe-managed and SPT behaviors.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Raúl Barroso <code@raulb.dev>
## Summary
- Show the plan name row in the monthly invoice estimate tooltip even
when the organization has no projects, so the section no longer appears
headerless next to the tax line.
## Test plan
- [ ] Open an org with no projects → Subscription plan update dialog →
hover the "Monthly invoice estimate" tooltip → verify the plan name +
price row is visible.
- [ ] Repeat on an org with projects → verify plan, Compute row, and
project breakdown all still render as before.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Improved rendering of the Monthly invoice estimate table in the
subscription plan update dialog, with reorganized display logic for plan
and project billing rows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem
With #45211 and #45218 merged, we don't need the `_Shadcn_` suffix
anymore
## Solution
- [x] Remove the `_Shadcn_` suffix
- [x] Update exports and imports
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Standardized UI component exports by removing legacy naming
conventions and providing direct imports for checkbox and radio group
components throughout the design system.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Problem
We used to have a `_Shadcn_` suffix for all the shadcn form components
because we also had `formik` form components.
This is not needed anymore.
## Solution
- Remove the suffix
- Update all usages
### Summary
This PR updates the logic to include `prepaid_credits_balance` while
showing the existing customer balance.
This changes the credit balance shown in:
- Billing Settings > Credit Balance
- Credit code redemption modal
The displayed amount now reflects the total credit balance across
prepaid credits and the customer balance.
### Testing
- Open an org billing page with prepaid credits and verify Credit
Balance includes both sources.
- Open the credit redemption modal and verify Current Balance matches
the combined credit amount.
- Verify an org with only customer balance still shows the same credit
amount as before.
- Verify an org with only prepaid credits balance and no customer
balance now shows credits correctly.
- Verify an org with no credits shows 0.00 and does not show /credits.
- Verify an org where net balance is debt still shows a negative amount
without the /credits suffix.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Improvements**
* Credit balance display now includes purchased and prorated credits for
a complete account view.
* Credit redemption and current-balance screens now show combined credit
totals (prepaid + existing) for clearer availability.
* UI descriptive text clarified to explain how credits are applied and
how charges occur once credits are exhausted.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Summary
Mirrors the tax-ID-clearing behavior already present in
`NewPaymentMethodElement` (used by `AddPaymentMethodForm`) over to
`BillingCustomerDataForm`. When a user changes their billing country,
the previously selected tax ID (type, value, name) is now cleared so a
stale tax ID from the previous country doesn't silently persist under
the new one.
### Test plan
- [x] Open **Organization Settings → Billing → Billing Address** for an
org with a saved billing address + tax ID
- [x] Verify the saved tax ID is shown on initial load (not cleared)
- [x] Change the country in the address element to a different country
- [x] Verify the tax ID combobox resets to "Select tax ID" and the tax
ID value input disappears
- [x] Change the country back to the original country → tax ID still
cleared (does not re-populate)
- [x] Pick a new tax ID for the new country, enter a value, save →
confirm it persists
- [x] Reload the page → saved tax ID shows correctly and is not cleared
on mount
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Tax ID fields in organization billing settings are now automatically
cleared when the billing address country is changed, preventing
country-specific tax ID mismatches.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->