mirror of
https://github.com/supabase/supabase.git
synced 2026-10-11 04:15:04 +03:00
53e0e57ffee0afbcbc3a6883d00a9aed57f12e7d
320
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
53e0e57ffe |
fix(storage): keep the preview panel's URL button and row handles as they were
The redesign renamed the panel's "Get URL" button to "Copy URL" while the row context menu kept "Get URL", leaving one action with two names, and gave the panel's file name a `title` — the attribute the explorer rows use as their handle, so `getByTitle` matched two elements once a preview was open. Also snap five off-token sizes to the scale the ratchet enforces, and point the E2E delete helper at the confirmation's real label now that it says what it does instead of ConfirmationModal's "Submit" default. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn |
||
|
|
183d5f2114 |
fix(storage): say the version matched the policy and will be deleted
Leads with what happened and that it is permanent, then bounds the wait. The previous wording blamed a missing schedule; the real reason there is no exact timestamp is that the cleanup spans several systems. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn |
||
|
|
fdd935c05f |
fix(storage): say cleanup can take up to 24 hours
There is no computable expiry timestamp: cleanup runs at no fixed moment and removal can lag by a day, so the tooltip says so rather than implying the next pass is imminent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn |
||
|
|
88f2609670 |
feat(storage): say a version is queued to expire, not expiring now
"Expiring now" claimed a moment that does not exist: cleanup is a periodic pass, so a version that has met the policy stays listed until it runs. The tooltip says why, within a max width. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn |
||
|
|
42a0ced1de |
fix(storage): refresh the row after restoring a version
Restoring a noncurrent version invalidated the version list but left the explorer row showing the old size, type and modified date, since the live listing is the explorer's own state rather than a React Query cache. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn |
||
|
|
ffc1ab56e6 |
refactor(storage): trim comments to one line where they earn their place
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn |
||
|
|
39f0406192 |
fix(storage): preview a version's own bytes, not the current ones
The version history rendered a generic mime-type icon per row, and the compare widget put that same icon on both sides — so every entry for a file looked identical and the comparison showed nothing to compare. The sign and public-url endpoints already accept `options.versionId`; nothing asked for it. `useFetchFileUrlQuery` now takes a `versionId` and keys on it, and the preview rendering moves out of `PreviewPane` into a `FilePreview` component both the pane and the compare widget use, so a version preview cannot silently fall back to the current bytes. Image rows in the history list render their own thumbnail under 5MB; larger files and other mime types keep the icon rather than pull a whole object down for a 28px box. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn |
||
|
|
e2cc696922 |
feat(storage): offer Archive and Delete permanently from the row menu
The file preview panel already splits the two on a versioned bucket, but the explorer's own row menu still offered a single "Delete" — which archives there, without saying so. The row menu now reads "Archive" on a versioned bucket and gains a "Delete permanently" entry beside it. `ConfirmPurgeModal` is mounted once by the explorer and driven by `itemToPurge` on the store, the same shape the row delete already uses. The preview panel routes its own permanent delete through it too, so the confirmation copy exists in one place rather than two. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn |
||
|
|
0b8ef6dad2 |
feat(storage): drive version history off the real endpoints
The preview panel now addresses versions by the object's full path, which is what the list, move and delete endpoints take, rather than by the leaf name the explorer renders. `VersionHistory` keeps `objectName` for copy and takes `path` separately. Expiry countdowns read the bucket's stored lifecycle policy instead of an empty placeholder, so a row's fate reflects the policy that governs it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3euXsz25sTybsGTcxCFfn |
||
|
|
0cd08c6b1a |
fix(storage): tell the truth in the empty version history
The empty state read "Overwriting this file will retain a recoverable copy here" regardless of whether the bucket was actually versioned. Since `getBucketVersioningState` reports `disabled` for every bucket until the API exposes the field, that promise was showing on every file in every bucket. Splits it: `disabled` now says versioning is off and points at the bucket settings; `enabled`/`suspended` keep the original copy. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
89e946acc2 | improve comments | ||
|
|
60d8c45f8e |
refactor(storage): drop the unreachable cap-only lifecycle branch
Follows the same change in the version-fate helper: a version cap always arrives
alongside an expiration age, so the policy summary only has three shapes to
describe (age alone, or age plus cap under either operator). Removes the
cap-only sentence and the "no age limit" chip, and `daysRemaining` on
`expires-on-next-upload` no longer needs an undefined guard.
Also adds the explicit `tabIndex={0}` that `supabase/require-explicit-tabindex`
wants on the four raw buttons in this feature. These were lint *errors*, not
warnings, so the ratchet never surfaced them.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
||
|
|
28b78001cb |
refactor(storage): say "retained" rather than "kept" for versions
Completes the rename in the version history rows, the lifecycle policy summary, and the delete confirmation copy. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
55fc610c2e |
feat(storage): add version history to the file preview panel
Rebuilds the file preview panel around object versioning: a collapsible Versions section listing every version with its removal outlook, an inline compare-and-restore widget, and delete actions that say what they actually do on a versioned bucket. - `VersionHistory` + `VersionHistoryPolicyRow` + `VersionThumbnail` — the version list, the inline lifecycle policy summary, and the row glyph - `VersionCompareWidget` — takes over the top of the panel when a noncurrent version is selected, so restoring is a visible comparison, not a modal - `PreviewSection` — the collapsible section wrapper - `PreviewPane` — new panel chrome, viewport-clamped thumbnail, and an Archive / Delete permanently split button on versioned buckets - `ConfirmDeleteModal` — on a versioned bucket a delete is a soft delete, so the copy no longer claims it cannot be undone Delete markers are surfaced as their own row type. They are the empty placeholders S3 writes on a soft delete, and they can outlive the delete (delete → upload → delete → restore leaves one mid-history), so a live file's history can contain them. There is nothing to preview or restore, so the row is non-interactive, dimmed, labelled "Delete marker", and its only action is removing the marker itself. Version data comes from the stubbed query added in the previous PR, so the Versions section renders its empty state until the Storage API lands. Fixes carried over from the prototype rather than ported: - Version rows were a clickable `<li>` whose `onKeyDown` passed a function reference instead of calling it, so keyboard activation did nothing. They are real `<button>`s now, which fixes activation and a11y together. - The policy summary put a `<Button>` inside tooltip content, unreachable by pointer or keyboard — now a `HoverCard`. - Permanent delete fired a bare `toast.success` with no mutation behind it. - Dropped the download and "Get version URL" menu items, which were toast stubs. - Deduplicated a double `filter` over versions and memoized the fate map. Also re-syncs `selectedBucket` in the explorer store when the bucket query refetches. It was only ever seeded once, so editing a bucket left consumers reading stale metadata — which is how Copy URL could sign a URL for the wrong visibility after a public/private toggle. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
78dc739901 |
fix(studio): show support inline and honour AlertError layouts (#51377)
## Problem AlertError forces a vertical layout whenever additional actions are supplied, even when the caller explicitly requests horizontal or responsive layout. Stripe Sync Engine's uninstall error is one affected call site, the other was Pipelines as demoed in #51311. ## Solution Honour an explicit layout. Preserve the existing defaults: vertical with additional actions, responsive otherwise. Replace the standalone Contact support action with an InlineLink in the contact support prose, preserving support form context and breadcrumb capture. Keep custom actions such as Retry. If instructions are hidden or custom prose omits contact support, retain a separate inline support link. With `hideContactSupport`, show no support link and shorten the default instructions to “Try refreshing your browser.” Custom descriptions remain unchanged. The local Pipelines configuration error explicitly hides support. Add the explicit responsive layout at the Pipelines call site. | Before | After | | --- | --- | | <img width="914" height="426" alt="CleanShot 2026-10-07 at 17 51 20@2x" src="https://github.com/user-attachments/assets/6cbddfee-97f5-4a7a-bafa-7b5dfd6ab8bf" /> | <img width="916" height="422" alt="CleanShot 2026-10-07 at 18 26 06@2x" src="https://github.com/user-attachments/assets/a21952a6-1c1a-437c-af73-c5736f33fd98" /> | | <img width="1566" height="384" alt="CleanShot 2026-10-07 at 18 28 07@2x" src="https://github.com/user-attachments/assets/bdc2a043-421f-4c22-9bd3-37859c6e85c7" /> | <img width="1568" height="308" alt="CleanShot 2026-10-07 at 18 26 58@2x" src="https://github.com/user-attachments/assets/da0f2c6a-6254-4196-944b-5665e87b3c3c" /> | ## Review instructions 1. In a fresh local test project with no existing `stripe` schema, run this in SQL Editor: ```sql begin; create schema stripe; comment on schema stripe is '{"status":"uninstall error","errorMessage":"Local layout test: uninstallation failed"}'; commit; ``` 2. Open **Integrations → Stripe Sync Engine → Overview** and reload. Check **Failed to uninstall Stripe Sync Engine** at wide and narrow widths, including **Retry uninstallation** and the inline **contact support** link. Do not click Retry: it invokes the real uninstall operation. 3. Remove the empty fixture with `drop schema stripe restrict;`. 4. Block the Pipelines source-status request and resize the page: Retry uses the responsive layout. 5. AlertError callers without an explicit layout should retain their existing presentation. Confirm default and custom contact support prose use an inline link, with no standalone support action. Hidden instructions and custom prose without contact support retain an inline fallback. With `hideContactSupport`, the default prose is “Try refreshing your browser.” and no support link appears; custom descriptions remain unchanged. 6. Automated regression coverage checks that an explicit responsive layout survives additional actions, and that hiding support removes the default support wording while preserving custom descriptions. --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
2d0bd7af69 |
feat(storage): add object versions data layer (#49207)
| # | Branch | Base | | - | ------ | ---- | | 1 | `feat/storage-versioning-private-alpha` — merged | `master` | | 2 | `feat/storage-versioning/002-bucket-form-fields` | `master` | | 3 | `feat/storage-versioning/003-bucket-modals` | 2 | | 4 | `feat/storage-versioning/004-object-versions-data` ◀ | 3 | | 5 | `feat/storage-versioning/005-file-preview-versions` | 4 | | 6 | `feat/storage-versioning/006-billing-storage-retention` | 5 | | 7 | `feat/storage-versioning/007-archived-objects-data` | 6 | | 8 | `feat/storage-versioning/008-archived-rows` | 7 | | 9 | `feat/storage-versioning/009-archived-preview-pane` | 8 | | 10 | `feat/storage-versioning/010-replace-file` | 9 | ## [4/10] Storage object versioning: object versions data layer **Base:** `feat/storage-versioning/003-bucket-modals` (PR 3) ### This PR The query and mutation hooks for the version history UI, written to `queryOptions` using the real Storage endpoints. - `object-versions-query.ts` — the version list, plus `ObjectVersion` and `LifecyclePolicy` - `object-version-restore-mutation.ts` — promote a noncurrent version to current - `object-version-delete-mutation.ts` — remove one specific version - `object-purge-mutation.ts` — delete an object and every version, bypassing versioning - `VersionHistory.utils.ts` — `computeVersionFate`, the pure rule deciding what removal outlook each version row shows - `BroomSparklesIcon.tsx` — inline SVG for a glyph absent from lucide-react 0.436 Easier to test directly from next PR in the stack #49208 which wires the queries to the real file preview panel ui. --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
6ef729cb5c |
feat(storage): versioning bucket modals (FE-4161) (#49205)
| # | Branch | Base | | - | ------ | ---- | | 1 | `feat/storage-versioning-private-alpha` — merged | `master` | | 2 | `feat/storage-versioning/002-bucket-form-fields` | `master` | | 3 | `feat/storage-versioning/003-bucket-modals` ◀ | 2 | | 4 | `feat/storage-versioning/004-object-versions-data` | 3 | | 5 | `feat/storage-versioning/005-file-preview-versions` | 4 | | 6 | `feat/storage-versioning/006-billing-storage-retention` | 5 | | 7 | `feat/storage-versioning/007-archived-objects-data` | 6 | | 8 | `feat/storage-versioning/008-archived-rows` | 7 | | 9 | `feat/storage-versioning/009-archived-preview-pane` | 8 | | 10 | `feat/storage-versioning/010-replace-file` | 9 | ## [3/10] Storage object versioning: wire into the bucket modals **Base:** `feat/storage-versioning/002-bucket-form-fields` (PR 2) ### This PR Mounts the object-versioning form section in the create and edit bucket modals behind the feature preview, and saves it. - create and edit bucket modals spread `bucketVersioningFormFields` into their existing form schema - lifecycle defaults to 30 days / 10 versions - edit adds a confirmation before suspending an actively versioned bucket ## Enabling object versioning on a new bucket and setting lifecycle policies https://github.com/user-attachments/assets/194f8319-4929-432e-8a50-206f180a77a8 ## Edit and suspend object-versioning https://github.com/user-attachments/assets/f31e1d34-9840-4f5a-a269-6a911214742d ## To reproduce 1. Make sure storage versioning is enabled under feature previews > Storage Versioning 2. Open Storage Bucket File explorer 3. create new bucket and enable Object Versioning 4. set lifecycle policy - Noncurrent version expiration: can be either empty or >1 - Retained noncurrent versions: can be either empty or between 1 and 100 and can't exist without "Noncurrent version expiration" 5. Open new bucket with object versioning and test changing lifecycle policies 6. Disabling object-versioning shows proper warning and updates `versioning_status` to SUSPENDED (it can never go back to DISABLED once it has been enabled on a bucket) --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
9d1661dec1 |
chore: Reorganize the Files buckets code (#51350)
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> |
||
|
|
089133cc2c |
feat(storage): add bucket object versioning form fields (FE-4161) (#49203)
| # | Branch | Base | | - | ------ | ---- | | 1 | `feat/storage-versioning-private-alpha` — merged | `master` | | 2 | `feat/storage-versioning/002-bucket-form-fields` ◀ | `master` | | 3 | `feat/storage-versioning/003-bucket-modals` | 2 | | 4 | `feat/storage-versioning/004-object-versions-data` | 3 | | 5 | `feat/storage-versioning/005-file-preview-versions` | 4 | | 6 | `feat/storage-versioning/006-billing-storage-retention` | 5 | | 7 | `feat/storage-versioning/007-archived-objects-data` | 6 | | 8 | `feat/storage-versioning/008-archived-rows` | 7 | | 9 | `feat/storage-versioning/009-archived-preview-pane` | 8 | | 10 | `feat/storage-versioning/010-replace-file` | 9 | ## [2/10] Storage object versioning: bucket form fields The object versioning + lifecycle policy form section for the create and edit bucket modals. Mounted onto the ui in PR 3 #49205 - `BucketVersioningFields` — the versioning switch and the suspension / public-bucket / retention-tightening warnings - `LifecyclePolicySection` — the retention window and version cap inputs - `ExpirationModeToggle` — how the two conditions combine (and / or) - `BucketVersioningFields.schema.ts` — zod fields the parent modals spread into their own schema, plus `superRefineBucketVersioning` - `BucketVersioningFields.utils.ts` — retention-tightening detection - `StorageVersioning.constants.ts` — versioning state and expiration mode types, the prefill defaults, and `getBucketVersioningState` Note: a single s3 lifecycle policy expects both `version_expiry_days` and `max_noncurrent_versions` and always evaluate the two fields within the same policy with an AND logic. To enable both AND and OR/EITHER logic, we save two distinct s3 policies so we can enforce the OR logic. See demos and how to reproduce in #49205 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary * **New Features** * Eligible projects with the preview enabled can configure object versioning for storage buckets, including version expiration, retained-version limits, and “and/or” lifecycle conditions. * Settings default to 30 days and 10 retained versions, with validation for retention values and requirements for setting a version limit. * Notices highlight public buckets, missing lifecycle conditions, suspending existing versioning, and changes that tighten retention limits. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
838fcaaa89 |
Joshenlim/fe 4509 fdw general UI consolidation and refactor (#51079)
## Context Stacks on top of https://github.com/supabase/supabase/pull/51074 PR's just mainly refactoring, no visual differences: - `CreateWrapperSheet` + `EditWrapperSheet` use the same UI components for the foreign tables section - Can be consolidated into one reusable component - `WrapperTableEditor` is still using `SidePanel` component - Can be swapped to use new `Sheet` component - Refactor `WrapperTableEditor`'s layout a little - added separators for clarity between sections <img width="400" alt="image" src="https://github.com/user-attachments/assets/b1983bf2-cff5-43eb-8b31-40a7abb65038" /> - Update `getCreateFDWSql` to just use the Foreign Data Wrapper's name from `wrapperMeta` since its now standardized <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a shared foreign-table selector for wrapper setup and editing, with options to view columns, add or edit table definitions, and remove tables. * Updated the table editor to use a sheet layout with a fixed footer. * **Bug Fixes** * Wrapper creation now uses the wrapper’s configured name when creating the server. * Foreign-table targets display the table name when other target details are unavailable. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
521881a899 |
Joshenlim/fe 4480 fdw create wrapper to only init fdw once users to name the (#51074)
## Context PR here refactors the way we manage Foreign Data Wrappers in the dashboard (Under Project -> Integrations), as there's some DX problems with the current behaviour. Currently whenever a user creates a new wrapper, the dashboard is creating both the Foreign Data Wrapper (`create foreign data wrapper...`) + server (`create server ...`). The former is **_redundant_** to create multiples of given that it just handles the `handler` and `validator`, whereas what matters more is the server which holds the connection credentials. Hence standard practice is usually one Foreign Data Wrapper with multiple servers. (The former just needs to be created once if not done yet) This also led to some problems as well when users created their own wrappers via SQL and tried to manage them through the dashboard GUI, leading to us having to add some guard rails to prevent managing wrappers sharing the same Foreign Data Wrapper ([ref](https://github.com/supabase/supabase/pull/50785)) ## Changes involved - When creating a wrapper, if the Foreign Data Wrapper has yet to be set up for the wrapper type, the dashboard will initialize one and subsequently use that same Foreign Data Wrapper for any new wrappers - When creating / editing a wrapper, users will name the **server** instead of the **wrapper** <img width="500" alt="image" src="https://github.com/user-attachments/assets/b3e61204-0e16-4599-84ac-af2aab5b93c2" /> - When deleting a wrapper, the clean up for vault secrets are now deterministic by referencing the wrapper's server options - RE backwards compatibility: Existing wrappers will _not_ be affected by the changes here - they can be edited / deleted as per normal ## Unrelated fixes + UI refactors added - Fix Iceberg Wrapper not showing the right form when adding new wrapper - Adjust form layouts in side panel to be horizontal instead of vertical (Follows Database -> Pipelines) - Clean up to use newer UI components like `ButtonTooltip` - Opt to hide Docs + Create CTA under `WrappersTab` if marketplace feature preview is enabled (Since these actions are already in the header, will be duplicates) - Consolidate foreign tables configuration for create + edit wrapper sheet into one component `ForeignTablesSelector` ## To test - [ ] Verify that existing wrappers with their own Foreign Data Wrapper can be edited correctly - [ ] Verify that existing wrappers with their own Foreign Data Wrapper can be deleted - [ ] Verify that existing wrappers with shared Foreign Data Wrapper can be edited correctly - [ ] Verify that existing wrappers with shared Foreign Data Wrapper can be deleted - [ ] Verify that new wrappers can be created - [ ] Verify that newly created wrappers can be edited correctly - [ ] Verify that newly created wrappers can be deleted |
||
|
|
5de3666930 |
Fix: storage explorer ignore current filter after mutations (#51174)
## Problem When users trigger actions such as deleting an item, the storage explorer reloads the opened folders but ignore the currently applied filter. ## Solution Move the filter state in Valtio so that its other functions are aware of it. ## Review instructions 1. Create a Supabase project and upload objects in Storage with date prefixes (e.g., 202608XX) 2. Navigate to Storage, select a bucket with multi-dated/prefixed objects 3. Enter a filter in the search box (e.g., 20260820) to show only matching objects 4. Select one or more filtered objects and delete them Observe the file list after deletion - it should show filtered contents according to the search box value <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Storage search now stays in sync as you open folders and refresh their contents. * When restoring open folders, search results are filtered in the deepest open folder rather than hiding ancestor folders. * Deleting a file from filtered results keeps the search applied and displays the remaining matches correctly. * Search results remain consistent across folder navigation, refreshes, and file deletion. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
92952bf903 |
fix(studio): clarify S3 access key dialogs (#51070)
## Problem The S3 access key creation dialogs are wider than their contents, use plural titles for one key pair, and call the name field “Description” even though the table calls it “Name”. The save state also implies both values disappear, although only the secret does. ## Solution Use the small dialog size for both states. Use singular titles, label the field “Name”, shorten the create button to “Create”, and clarify when the secret must be copied. The API field remains `description`. ## Review instructions 1. Open a project’s **Storage > S3** page and select **New access key**. Check the dialog width, title, Name field, and Create button. 2. Create a key and check the save dialog width, singular title, and secret visibility guidance. | Before | After | | --- | --- | | <img width="1084" height="572" alt="CleanShot 2026-09-30 at 14 37 20@2x" src="https://github.com/user-attachments/assets/781706ee-0ecc-4535-abb5-f6ac65f02c71" /> | <img width="844" height="584" alt="CleanShot 2026-09-30 at 14 36 56@2x" src="https://github.com/user-attachments/assets/119df19f-2f39-4e23-94b4-26665583765c" /> | | <img width="1096" height="730" alt="CleanShot 2026-09-30 at 14 37 57@2x" src="https://github.com/user-attachments/assets/00481ed7-dc05-48b9-8cbc-e76d608aa4b1" /> | <img width="842" height="780" alt="CleanShot 2026-09-30 at 14 37 39@2x" src="https://github.com/user-attachments/assets/8c837101-250a-474f-a0fc-cf46ce491f83" /> | <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Updates** * The credential form now labels the field “Name” and uses “Create” for the submit button. * Confirmation text now clarifies that the access key is bucket-wide, bypasses RLS, and its secret is shown only once. It also refers to a single access key instead of using S3-specific wording. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
12894ddd2a |
feat(studio): migrate storage infinite-query hook to list-v2 (#50730)
## Problem Storage's `list` (v1) endpoint is being deprecated in favor of `list-v2`, which uses cursor pagination instead of numeric offset (which degrades on large buckets) and fixes folders that differ only by case not both being listable. This is PR 1 of the migration (parent: FE-4423); it covers the shared infinite-query hook and its two consumers. ## Solution Added `listBucketObjectsV2` alongside the existing v1 `listBucketObjects` (still used elsewhere, migrated in a later PR), and replaced the `useBucketObjectsInfiniteQuery` hook with `bucketObjectsInfiniteQueryOptions` built on `infiniteQueryOptions`, following the repo's preferred data-fetching pattern. Pagination now uses `hasNext`/`nextCursor` instead of an offset multiplier, and `queryFn` rejects a response that claims `hasNext` without advancing the cursor so a misbehaving backend can't send `fetchNextPage` into an infinite loop. v2 splits results into separate `folders`/`objects` arrays and has no `search` field, so the two consumers (`BucketFilePickerColumn`, `MoveItemsFolderPicker`) merge/sort those arrays themselves, and search is folded into a `prefix` match instead. Also removed "Time last accessed" from the picker's sort dropdown since v2's `sortBy.column` doesn't support it, with a defensive fallback to `name` in case the shared sort preference (still used by the v1 main file explorer) carries that value over. Added the missing self-hosted `list-v2` API proxy route (`pages/api` + the TanStack `routes/api` wrapper) using storage-js's `listV2()`, since self-hosted Studio only had a v1 route and every v2 request was 404ing there. ## Review instructions 1. Open the bucket file picker (e.g. via an OAuth app logo upload), confirm folders and files both render and paginate correctly, and that searching still filters as expected. 2. Open the "Move items" modal's folder picker, confirm you can navigate into and back out of subfolders, and that folder search still works. 3. Run `pnpm test:studio -- MoveItemsModal`. ## Checklist - [x] I have read [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) - [ ] 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 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Storage browsing loads large bucket listings in pages, helping keep navigation responsive. * Folder pickers display folders and files together across paginated results. * Moving items between folders uses the same paginated browsing experience. * Search remains available in the final folder level, and folder navigation shows the correct contents. * **Updates** * “Time last accessed” is no longer available as a sorting option in storage pickers. Sorting is available by name, creation time, or update time. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
05a45dd1ed |
feat(studio): rename Replication to Pipelines (#50637)
## What kind of change does this PR introduce? Feature and docs update. ## What is the current behavior? The Dashboard lists Pipelines destinations under Database > Replication. Read replicas have moved to Infrastructure, but the temporary notices remain on the destinations page and new destination sheet. Closes PIPE-1021. ## What is the new behavior? The canonical Dashboard routes are Database > Pipelines, while legacy Replication list and detail URLs permanently redirect to the equivalent Pipelines routes. Navigation, command palette, shortcuts, pipeline links, docs, and current marketing copy use Pipelines. Read-replica notices and their obsolete dismissal state are removed. | Before | After | | --- | --- | | <img width="1024" height="759" alt="Replication Database Agua Basket Supabase" src="https://github.com/user-attachments/assets/53f9f565-1ed1-43e9-a7d9-b66b2a47e948" /> | <img width="1024" height="759" alt="2540" src="https://github.com/user-attachments/assets/14ab2d61-d01c-483f-9d4f-0ac286dae159" /> | The Management API, pipeline behaviour, replication logs, and Postgres replication terminology remain unchanged. ## To test - Open `/project/<ref>/database/pipelines` and confirm the Database navigation, page header, and pipeline breadcrumb say Pipelines. - Open `/project/<ref>/database/replication?source=bookmark#destinations` and a legacy pipeline detail URL. Confirm each redirects to the matching Pipelines URL while preserving parameters and fragments. - From the Pipelines page, open Add destination. Confirm no read-replica migration notice appears. - Open the Pipelines guide and confirm its Dashboard steps lead to Database > Pipelines. ## Before merge - [ ] Get changelog entry reviewed https://github.com/supabase/changelog/pull/262 and prepare to merge simultaneously <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added dedicated **Database > Pipelines** pages for pipeline lists and details. - Added permanent redirects from legacy Replication URLs to their corresponding Pipelines pages. - Read replica management links now open **Settings > Infrastructure**. - **Documentation** - Updated Pipelines setup, monitoring, troubleshooting, and usage guidance to reference the current dashboard locations. - Updated Realtime guidance to use **Database > Publications**. - **Updates** - Renamed dashboard navigation, breadcrumbs, commands, and keyboard shortcuts from **Replication** to **Pipelines**. - Removed the “Read replicas have moved” notification. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
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 --> |
||
|
|
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> |
||
|
|
47a532eef7 |
feat(studio): add copy path and copy link row actions (#50480)
| | PR | Base | Branch | | --- | --- | --- | --- | | 1 | #50476 | `master` | pre-existing correctness fixes | | 2 | #50413 | `fix/storage-explorer-listing-and-scroll` | `?path`/`?preview` deep-linking | | 3 | #50478 | `feat/storage-nav-improvement` | end-to-end deep-link test | | 4 | **this PR** | `test/storage-deep-link-e2e` | copy path / copy link row actions | To read the whole change in one view: ```bash git diff master...feat/storage-copy-row-actions -- apps/studio e2e ``` ## What is the new behavior? Both row menus now offer two actions: - **Copy relative path** — the bucket-relative object key, i.e. what `storage.from(bucket)` takes - **Copy link** — the dashboard URL that reopens the item in the explorer **Copy path to folder** is replaced by **Copy relative path**. It produces the same value for a folder and now works for files too, so nothing is lost. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Storage Explorer now provides separate actions to copy a relative path or a direct link for files and folders. * Copied links open the relevant storage location, including folder navigation and file preview details. * Success notifications appear after clipboard copying completes. * **Tests** * Added coverage for file and folder copy actions, generated paths and links, URL encoding, and clipboard behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
d9cfdcd741 |
feat(studio): deep-link folders and files in the storage explorer (#50413)
| | PR | Base | Branch | | --- | --- | --- | --- | | 1 | #50476 | `master` | pre-existing correctness fixes | | 2 | **this PR** | `fix/storage-explorer-listing-and-scroll` | `?path`/`?preview` deep-linking | | 3 | #50478 | `feat/storage-nav-improvement` | end-to-end deep-link test | | 4 | #50480 | `test/storage-deep-link-e2e` | copy path / copy link row actions | ## What is the current behavior? The file explorer doesn't keep track of folder navigation. Files and folders paths aren't shareable ## What is the new behavior? With this PR: - nav state is stored via params - "path" to store folder path (if nested folder paths) - "preview" to store the selected filename - back/forward nav history - file url opens correct folder/file [https://github.com/user-attachments/assets/](https://github.com/user-attachments/assets/528d5c1d-a1b9-4061-9b67-a41dd98716e0)[0cfb7fcc-2c6e](https://github.com/user-attachments/assets/0cfb7fcc-2c6e-4f5a-950d-060c8eb2027b)[528d5c1d-a1b9](https://github.com/user-attachments/assets/528d5c1d-a1b9-4061-9b67-a41dd98716e0)[-](https://github.com/user-attachments/assets/528d5c1d-a1b9-4061-9b67-a41dd98716e0)[4f5a-950d](https://github.com/user-attachments/assets/0cfb7fcc-2c6e-4f5a-950d-060c8eb2027b)[4061-9b67](https://github.com/user-attachments/assets/528d5c1d-a1b9-4061-9b67-a41dd98716e0)[-](https://github.com/user-attachments/assets/528d5c1d-a1b9-4061-9b67-a41dd98716e0)[060c8eb2027b](https://github.com/user-attachments/assets/0cfb7fcc-2c6e-4f5a-950d-060c8eb2027b)[a41dd98716e0](https://github.com/user-attachments/assets/528d5c1d-a1b9-4061-9b67-a41dd98716e0) ## Steps to review - Open bucket in Storage File Explorer - navigate between files and folders and notice url params change - reload page, it should reopen where you left off - hitting back/forward on the browser history should follow file/folder navigation history --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Gildas Garcia <1122076+djhi@users.noreply.github.com> |
||
|
|
c8a9a7a630 |
fix(studio): correct storage explorer listing pagination and column scroll (#50476)
| | PR | Base | Branch | | --- | --- | --- | --- | | 1 | **this PR** | `master` | pre-existing correctness fixes | | 2 | #50413 | `fix/storage-explorer-listing-and-scroll` | `?path`/`?preview` deep-linking + copy row actions | | 3 | #50478 | `feat/storage-nav-improvement` | end-to-end deep-link test | | 4 | #50480 | `test/storage-deep-link-e2e` | copy path / copy link row actions | To read the whole change in one view: ```bash git diff master...test/storage-deep-link-e2e -- apps/studio e2e ``` ## What is the current behavior? Four independent bugs in the storage explorer, all pre-existing on `master`: - `hasMoreItems` is derived from the *formatted* listing, but `formatFolderItems` drops the `.emptyFolderPlaceholder` — so a full page can format to `LIMIT - 1` and stop pagination a page early. - A failed listing is indistinguishable from an empty folder, so a fetch error reads as "this folder has nothing in it". - `fetchFoldersByPath` commits its result against whichever bucket is selected when the requests resolve. Switching buckets mid-flight files the old bucket's items under the new bucket's name — and because `columns[0].name` then matches, nothing downstream notices and refetches. - The horizontal auto-scroll never runs its guard (`if (fileExplorerRef)` is always truthy), scrolls relatively so repeated runs drift, and depends on the `columns` array identity — so a background refetch yanks the view back to the right. It also scrolls in list view, where there is nothing to scroll. ## What is the new behavior? Each of the above is fixed at its source. Pagination and the exhaustiveness check now compare the raw page length; listings carry an `isComplete` flag; `fetchFoldersByPath` captures the bucket id at entry and discards a stale result; the scroll is absolute, guarded, keyed on `columns.length`, and skipped in list view. Two new test files cover the parts that were silently wrong before: `state/storage-explorer.test.ts` (MSW, the bucket race) and `FileExplorer.test.tsx` (scroll geometry, with the container's layout defined by hand since jsdom reports everything as zero-sized). Both were checked by reverting the fix and confirming they fail. ## Additional context `fetchFoldersByPath` also starts returning `{ missingPaths }` here. Nothing reads it yet — the first consumer is in PR 2 — but it shares a hunk with the `isComplete` work, so separating it would mean two PRs editing the same lines. It is backward-compatible: all three existing call sites ignore the return value. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Bug Fixes - Improved Storage Explorer column-view scrolling so the newest column remains visible, including when the preview pane opens. - Prevented folder results from a previously selected bucket from appearing after switching buckets during loading. - Improved handling of incomplete or partial folder listings to avoid incorrectly treating failed results as empty folders. - Preserved the correct scroll position when using list view. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
2db6fbf410 |
test(studio): add e2e coverage for the storage move picker (#50460)
## 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? Tests, plus one small test hook in Studio. ## What is the current behavior? The Storage file explorer's move dialog was recently reworked: the free-text "Path to new directory" input was replaced with an embedded folder picker (folder browsing, bucket-wide folder search, a responsive breadcrumb, and a confirm button that targets the folder currently open). That work shipped with unit and component tests, but nothing exercises it end to end against a real bucket. ## What is the new behavior? New `e2e/studio/features/storage-move.spec.ts` with seven tests: | Test | What it covers | | --- | --- | | moves a file into a folder picked from the explorer | The core path: open the picker, click a folder, confirm, and assert the file left the root and landed in the destination | | offers folders only, never files, as destinations | Files are excluded from the listing entirely | | blocks confirming a move into the folder the file already sits in | The confirm button reports `aria-disabled` when the destination matches the source | | finds a nested folder by search and moves into it | Bucket-wide folder search, including the "`<folder>` in `<location>`" row label | | reports when a search matches no folders | The empty-search message instead of a blank list | | collapses the middle of a deep path into a breadcrumb dropdown | The responsive breadcrumb: bucket and the two deepest folders stay inline, the middle collapses, and picking a collapsed folder navigates to it | | walks back up the path with the up-one-level button | Disabled at the bucket root, and drops the deepest folder otherwise | Supporting changes: - `utils/storage/queries.ts` gains `uploadObject` and `seedBucket`. Storage has no standalone folders — a folder exists because an object sits under that prefix — so seeding a folder tree means uploading objects at the paths a test needs. Doing this through the API keeps setup off the UI, which is both faster and less flaky than clicking through "Create folder" for each level. - `utils/storage/client.ts` accepts a string body so object uploads can send raw content alongside the existing JSON requests. - `utils/storage-helpers.ts` gains `openMoveDialog` and `confirmMove`. - `MoveItemsFolderPicker.tsx` gains `data-testid="folder-picker-list"` on its list container. ## Additional context **Why the `data-testid`.** Once a path is deep enough for the breadcrumb to collapse, the breadcrumb renders crumb buttons whose accessible names are folder names — so `getByRole('button', { name: 'beta' })` scoped to the dialog can match either a folder row or a breadcrumb crumb depending on depth. Scoping row lookups to the list container removes that ambiguity. This follows the e2e guidance about adding explicit test hooks where a component lacks an unambiguous accessible name. **These tests have not been executed.** They were written against the merged implementation and verified as far as the environment allows: - `npx playwright test --list` collects all seven - `tsc --noEmit` is clean for the new spec and helpers (the pre-existing errors in `column-editor-types.spec.ts`, `table-editor.spec.ts`, and `wait-for-response-with-timeout.ts` are untouched) - Studio's unit and component tests (82) still pass, and typecheck, eslint, prettier, the lint ratchet, and knip are all clean The suite needs Docker to bring up the local Supabase stack, which wasn't available where this was authored, so a real run in CI is the first actual execution. Selectors were all read off the merged source rather than guessed, but timing assumptions in particular deserve attention on the first CI run. **One thing this surfaced, not fixed here.** The success toast reads `Successfully moved 1 files to docs` — it doesn't singularize. The tests assert on `/Successfully moved/` rather than the full string so they don't encode that, but it's worth a follow-up. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01Q94G7pWso6vQn5FQz6TUns --- _Generated by [Claude Code](https://claude.ai/code/session_01Q94G7pWso6vQn5FQz6TUns)_ <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Tests** - Expanded end-to-end coverage for moving files between folders in Storage. - Validated folder selection, nested-folder search, empty search results, collapsed breadcrumbs, and navigation to parent folders. - Confirmed files are excluded from destination choices and moving to the current folder is prevented. - Added coverage for creating isolated test buckets, uploading fixture files, and confirming successful move operations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
ee3fbc4e61 |
Joshenlim/fe 4383 consolidate tablerow no search result state (#50389)
### Context Just some housekeeping/consolidate refactors. There's a number of places where we render the same "no result" empty state for tables. So this PR just consolidates that into a reusable component `TableRowNoResults` to reduce duplication. Opting to save this under `components/ui` instead of the `ui` package as this is more of a derivation of `TableRow` than a primitive <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **UI Improvements** - Standardized empty search-result messages across database, functions, storage, and vector bucket tables. - Search terms now appear consistently when no matching records are found. - Added an accessible label to the vector bucket row actions menu. - Improved the storage explorer loading layout so content expands to use available vertical space. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
92fdb1d3c5 |
feat: update storage move UI (#50346)
Update path selection as destination where to move files in the Storage File Explorer. ## What is the current behavior? Currently you need to write out the entire path by hand, which is error prone and quirky. <img width="727" height="436" alt="Screenshot 2026-09-14 at 15 49 11" src="https://github.com/user-attachments/assets/2bb8fc78-d973-4b17-9343-08df23b67d2a" /> ## What is the new behavior? This PR adds a ui that lets the user select any folder as the destination of the file move. <img width="923" height="606" alt="Screenshot 2026-09-15 at 11 40 00" src="https://github.com/user-attachments/assets/2f4c50f8-3c11-4896-832e-b1e99defc9af" /> https://github.com/user-attachments/assets/261ac24e-ec24-4bcf-ad47-72bc48e27bab To test: - go to Storage File explorer and pick a file to "move" (action in the dropdown menu) - mov file to any other folder in the same bucket selecting destination folder from the ui in the dialog - both empty folder or also a folder with sub-folders can be destinations, as any selected folder becomes the active destination (notice the cta changing when selecting a folder) - batch move multiple items via multi-select (already supported, but using the updated ui now) - only folders should appear in this ui - destination folders can be searched using the search input <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Replaced the move-items path field with an interactive folder browser. - Browse, select, and search folders by name or path, with pagination and loading or empty states. - Navigate using breadcrumbs, including collapsed-path menus for deeply nested folders. - Receive warnings when folder search results are incomplete for very large buckets. - See clearer destination labels and protection against moving items to their current location. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
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 |
||
|
|
1966209483 |
chore(deps): upgrade vitest to v5 (#49994)
Upgrades Vitest from 4.1.4 to 5.0.0 across the monorepo, fixes the handful of things v5 turned into hard errors, and drops the `vi.clearAllMocks()` boilerplate that v5's `clearMocks` default makes redundant. **Changed:** - `vitest`, `@vitest/ui`, `@vitest/coverage-v8` 4.1.4 → 5.0.0 (catalog) - `vi.mock` calls that lived inside `beforeAll`/`beforeEach`/test bodies moved to module scope (v5 throws on nested calls). Affects the Studio and docs setup files and four Studio tests. - `detectBrowser` test restores `navigator` via `vi.unstubAllGlobals()` instead of assigning `global.navigator`, which now reaches jsdom's getter-only property. - `RowEditor.utils.test.ts` restores its `JSON.stringify` spy. It used to leak a throwing mock for the rest of the file, which v5's coverage provider now trips over. A later test in the same file had been asserting the leak's side effect (valid JSON reported as invalid) and now asserts the correct behavior. - `@testing-library/jest-dom` 6.6 → 7.0.1. Its vitest type augmentation resolves through a peer now, so it lands on each package's own `vitest` instead of whichever copy pnpm hoisted. Fixes `toBeInTheDocument` type errors in dev-tools after the reshuffle. - `@testing-library/react` 16.0.0 → 16.3.3 for the React 19 peer range. - `vite: catalog:` added to dev-tools, www, and common. Without it they resolved a newer vite than the catalog pin, which forked a second vitest instance in the lockfile. There's now one. - ai-commands custom matcher types use v5's `Matchers<R, T>` form. - 110 test files: `vi.clearAllMocks()` removed from `beforeEach`/`afterEach` hooks, along with hooks that only did that and the imports they left unused. Calls that also reset/restore mocks are untouched. Second commit, mechanical. **Added:** - `.vitest/` to the root gitignore (v5 writes JSON/JUnit/HTML reporter output there) **Removed:** - `vite-tsconfig-paths` catalog entry and deps. Vitest 5 resolves tsconfig paths itself. Release-age note: this sat in draft with a temporary `minimumReleaseAgeExclude` entry for `vitest` and `@vitest/*` while 5.0.0 was inside the workspace's 3-day `minimumReleaseAge` window. That window has closed, so the exclusion is gone and nothing bypasses the release-age gate. **Perf** (local, medians of 3 runs, same machine): | Suite | v4.1.4 | v5.0.0 | |---|---|---| | studio | 144.1s | 141.7s (-2%) | | studio `--coverage` | 156.9s | 146.4s (-7%) | | ui-patterns | 6.27s | 5.07s (-19%) | | ui `--coverage` | 3.35s | 2.14s (-36%) | | www | 0.89s | 0.47s (-47%) | Studio is dominated by jsdom environment setup per file, which v5 doesn't change. `vitest doctor` recommends keeping the current pool config: the vm pools and `isolate: false` all break tests. ## To test - `pnpm install --frozen-lockfile` succeeds with no `minimumReleaseAgeExclude` entry for vitest. - CI: Studio unit tests, ui, ui-patterns, www, docs, and typecheck/lint should all be green. The lint ratchet was checked locally: warning counts on touched Studio files are identical to master. - `pnpm test:studio` locally passes with coverage (588 files, 6240 tests). - Open a Studio test that uses `toBeInTheDocument` in your editor and confirm no type errors on jest-dom matchers, in Studio and in `packages/dev-tools`. - Known pre-existing failures unrelated to this PR: one dev-tools test (`getEventCountBadge` capped pill) fails on master too. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Tests - Improved test coverage for JSON validation and mobile navigation behavior. - Updated test setup, cleanup, environment configuration, and matcher support across application and shared package suites. - Removed obsolete coverage for alternate MCP transport selection. ## Chores - Streamlined TypeScript path resolution and Vitest reporter output handling. - Updated testing libraries and Vitest tooling across documentation, Studio, website, and shared packages. - Added Vitest reporter output to ignored files. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com> |
||
|
|
1131e3e2ce |
fix(ui): default Button variant to default instead of primary (#50160)
## What kind of change does this PR introduce? Bug fix / design-system alignment for the legacy `Button` from `ui`. ## What is the current behavior? Omitting `variant` on the legacy `Button` falls back to brand-green `primary`. That makes accidental greens easy, and it is hard to spot the real main action on busy pages. ## What is the new behavior? - Legacy `Button` now defaults to neutral `default` - Intentional primary CTAs (create, save, submit, marketing CTAs, and matching `ButtonTooltip` usages) now set `variant="primary"` so their appearance is unchanged - Neutral actions that previously relied on the old fallback (cancel, close, back, dashboard nav, and similar) become grey/white - Design-system docs updated; regression tests cover the new default `Button_Shadcn_` is unchanged. It already uses its own CVA default. This is PR 1 of 2 in a stack. PR 2 drops now-redundant `variant="default"` props. ## To test Studio (http://localhost:8082): - `/sign-in`: Sign in stays green - Open a project → Database → Tables: New table stays green - Auth → Users → Invite: Invite user stays green; Cancel / dismiss controls stay neutral - Project Settings → General: edit a field so Cancel and Save appear. Cancel is neutral, Save is green Design system (http://localhost:3003): - Components → Button: default demo is neutral; primary demo is green; featured preview is the default variant Marketing (optional): - www header: Start your project stays green; logged-in Dashboard is neutral <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Style** - Buttons now default to a neutral style, while primary actions across Studio, documentation, marketing pages, forms, dialogs, and error states use prominent primary styling. - Updated button examples and previews clarify the distinction between default and primary variants. - Event registration now includes a directional arrow icon. - **Tests** - Added coverage confirming default button styling and explicit primary styling behave as expected. - Updated related test fixtures to use primary styling where appropriate. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
8dd97d75aa |
refactor(studio): use v2 replication publication APIs (#49844)
## What kind of change does this PR introduce? Studio data-layer migration. ## What is the current behavior? Studio loads complete publication details through the original bulk endpoint and creates publications by executing SQL against the source database. Publication and source-table data use names where stable table IDs are available. ## What is the new behavior? Uses the v2 publication-name, publication-detail, publication mutation, and source-table endpoints. The existing creation sheet continues to behave the same, including publishing partition changes through the parent table by default. Initial-sync selection and Analytics Bucket associations now consume the selected publication detail. Generated platform API types and their required nullability updates are included. The generated Platform contract accounts for roughly 10,000 changed lines in this PR. ## Dependency Depends on the v2 source table, table column, and publication endpoints from [supabase/platform#37505](https://github.com/supabase/platform/pull/37505), which are deployed to production. ## To test 1. Open the pipeline creation sheet and select an existing publication. 2. Create a publication with mixed-case schema and table names, then confirm the table names are shown while stable IDs are submitted. 3. Exercise all four initial-sync policies, including selecting individual tables. 4. Reopen the publication and table selectors and confirm they refresh without replacing populated options. 5. Edit and delete a publication. 6. Open an Analytics Bucket associated with a pipeline and confirm its publication tables resolve correctly. 7. Confirm unlimited WAL retention renders as Unlimited on pipeline status. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Improved replication publication setup with on-demand table loading, refresh controls, clearer table labels, and streamlined publication selection. - Publication creation and updates now use the latest replication API and table-based configurations. - Added clearer handling for tables removed from publications, including stale-selection warnings. - **Bug Fixes** - Prevented table selections from carrying over when switching publications. - Improved replication status displays when lag or WAL metrics are unavailable. - Updated replication deletion and table management for the latest API behavior. - **Tests** - Expanded coverage for publication creation, table selection, stale tables, loading states, and replication metrics. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> |
||
|
|
3146650a5a |
Fix FormItemLayout usages for a11y (#49761)
Follow up of #49637. Usages that impacted tests were fixed in the previous PR. This PR fixes the other usages so that label are correctly linked to their inputs. No visual changes ## How to test 1. Design system: [Form examples](https://design-system-git-fix-form-item-layout-usages-supabase.vercel.app/design-system/docs/ui-patterns/forms): moved `FormControl` around the `SelectTrigger` so that the label is linked to the button (It's actually done like this in the [Select Form example](https://design-system-git-fix-form-item-layout-usages-supabase.vercel.app/design-system/docs/components/select#form) and Radix recommend targeting the button too in their [documentation](https://www.radix-ui.com/primitives/docs/components/select#labelling)) 2. [Access tokens](https://studio-staging-463111oii-supabase.vercel.app/dashboard/account/tokens): updated usage to fallback on generated ids and fixed the select just like _1_ 3. [New TOTP factor](https://studio-staging-463111oii-supabase.vercel.app/dashboard/account/security): updated usage to fallback on generated ids 4. _Studio/Database/Extensions_ (`https://studio-staging-463111oii-supabase.vercel.app/dashboard/project/[PROJECT]/database/extensions`): updated the extension enabling modal to fallback on generated ids 5. _Studio/Integrations/Vault (`https://studio-staging-463111oii-supabase.vercel.app/dashboard/project/[PROJECT]/integrations/vault/secrets`): updated the secret edition modal to fallback on generated ids 6. _Studio/Observability(`https://studio-staging-463111oii-supabase.vercel.app/dashboard/project/[PROJECT]/observability`): updated the report creation and edition modals to fallback on generated ids 7. _Studio/SQL Editor(`https://studio-staging-463111oii-supabase.vercel.app/dashboard/project/[PROJECT]/sql/new`): updated the query renaming modal to fallback on generated ids 8. _Studio/Storage/Analytics(`https://studio-staging-463111oii-supabase.vercel.app/dashboard/project/[PROJECT]/storage/analytics`): updated the table creation sheet to fallback on generated ids (you must have a bucket first) 9. _Studio/Workers(`https://studio-staging-463111oii-supabase.vercel.app/dashboard/project/[PROJECT]/workers`): updated the worker creation modal to fallback on generated ids (you must have a bucket first) 10. Updated [Signup](https://studio-staging-463111oii-supabase.vercel.app/dashboard/sign-up?returnTo=%2Fnew), [Signin](https://studio-staging-463111oii-supabase.vercel.app/dashboard/sign-in) and [SSO Signin](https://studio-staging-463111oii-supabase.vercel.app/dashboard/sign-in-sso) forms to fallback on generated ids <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Improvements** - Standardized form field presentation across access tokens, authentication, reports, integrations, database extensions, SQL editor, storage, and worker deployment workflows. - Updated password fields and visibility toggles for more consistent input behavior. - Refined token expiration selection, verification code entry, and dropdown layouts. - Preserved existing labels, validation, options, and form functionality while simplifying the interface structure. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
02cf09212e |
chore: Remove tsconfig paths (#49770)
This PR removes all `paths` in `tsconfig.json` for all apps and packages. They were added previosly because some of the components had a `_Shadcn` suffix because of an ongoing migration. How that the migration is done, the paths can be removed. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Standardized shared UI component, utility, and icon imports across design-system examples and application screens. * Simplified shared component access and project configuration. * Added shared access to anchor-link helpers and animation styles. * **Compatibility** * Updated component exports and imports without changing existing behavior. * No changes to user-facing workflows, screens, or functionality. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
4f92790587 |
fix: FormItemLayout does not apply item id correctly (#49637)
## Problem `<FormItemLayout>` does not apply item id correctly. This can be seen on https://supabase.com/design-system/docs/ui-patterns/forms: open the devtool and check the form items labels. They have no `for` attribute. This makes it harder to correctly test and is an accessibility issue. Axe devtool actually report it ## Solution When inside React Hook Form, `<FormItemLayout>` actually generate an `id` (via `<FormItem>`). However, this `id` is overridden in `<FormLayout>` and read from context by `<FormLabel>`. Ensure we use the generated id unless one was provided. Also updated the paths filters for the CI check so that any changes in either `ui` or `ui-patterns` triggers the studio unit and e2e tests. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved form accessibility by ensuring labels consistently connect to their corresponding input fields. - React-based forms now correctly preserve field-specific identifiers when associating labels with inputs. - Added support for explicitly specifying a label’s input target, improving compatibility with customized form layouts. - Updated Studio forms to use consistent control identifiers and labeling behavior. - **Quality Improvements** - Automated validation now also runs when shared UI components and patterns are updated. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
14fe0c0cc8 |
fix(studio): slightly round split-button corners on focus (#49129)
## What kind of change does this PR introduce? UI polish for split buttons (primary action + dropdown chevron). Follow-up to #49055. ## What is the current behavior? The focus ring sits above the neighbouring half, but the inner edge stays square, so the ring has two sharp corners at the join. ## What is the new behavior? On keyboard focus, the squared-off edge uses a slight radius so the ring matches the outer corners more closely. Resting state is unchanged. Split-button callsites now share the same join classes as the design-system example. | Before | After | | --- | --- | | <img width="1030" height="296" alt="43471" src="https://github.com/user-attachments/assets/9df3bd72-c7ac-4419-ae18-a7e649dc2d66" /> | <img width="1056" height="276" alt="CleanShot 2026-08-17 at 10 45 09@2x" src="https://github.com/user-attachments/assets/52e8a4dc-9c52-45ce-b4d0-f0e7b1b75935" /> | ## To test Tab to each half (labelled button, then chevron). Inner corners of the focus ring should be slightly rounded, not square. 1. [Split with dropdown](https://design-system-git-fix-split-button-focus-radius-supabase.vercel.app/design-system/docs/components/button#split-with-dropdown) (no login) 2. [Access Tokens](https://studio-staging-git-fix-split-button-focus-radius-supabase.vercel.app/dashboard/account/tokens) → Generate new token 3. Any project on [studio staging](https://studio-staging-git-fix-split-button-focus-radius-supabase.vercel.app/dashboard/_/settings/general) → Settings → General → Restart project <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Accessibility** - Added accessible labels to dropdown and export controls. - Improved keyboard-focus visibility, layering, and rounded edge treatment across joined buttons and menus. - Removed misleading or redundant screen-reader text and titles. - **Bug Fixes** - Prevented split-button controls from shrinking or displaying awkward borders and corners. - Refined hover and focus behavior for action buttons throughout settings, database, storage, account, and documentation interfaces. - **Documentation** - Clarified guidance for using overflow menus and responsive split-button actions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
88e916a4c0 |
fix(studio): focus state for buttons with dropdown (#49055)
## 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? We've quite a few instances where some buttons have a dropdown appendage. The focus state for these were broken as well as visually regarding the separator. This first pass fixes the instances we have in studio, I've left potentially adding this to our design system fragment components as another PR. | Before | After | |--------|--------| | <img width="531" height="133" alt="Screenshot 2026-08-13 at 11 29 36" src="https://github.com/user-attachments/assets/70747fd0-11d4-4670-85fa-d76f3564837b" /> | <img width="519" height="130" alt="Screenshot 2026-08-13 at 11 40 15" src="https://github.com/user-attachments/assets/5920bebb-81ce-4962-908b-5f61526ca7ca" /> | | <img width="538" height="146" alt="Screenshot 2026-08-13 at 11 29 48" src="https://github.com/user-attachments/assets/f1c7018f-cd43-47fa-b4c0-045af350f80b" /> | <img width="515" height="148" alt="Screenshot 2026-08-13 at 11 39 56" src="https://github.com/user-attachments/assets/fee09113-433a-4b5d-ac68-3ab3f2565d34" /> | | <img width="538" height="143" alt="Screenshot 2026-08-13 at 11 29 52" src="https://github.com/user-attachments/assets/3063d391-99b2-4599-9cdf-edd0b2cdfdf0" /> | <img width="529" height="159" alt="Screenshot 2026-08-13 at 11 40 05" src="https://github.com/user-attachments/assets/4bdeb9e0-8324-45df-a211-8c7fd0ee11a6" /> | <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved keyboard focus visibility across Studio controls, including token management, email settings, replication, log drains, query insights, infrastructure, storage, and assistant actions. * Focused buttons in adjacent or split-button groups now appear above neighboring controls, preventing borders and overlays from obscuring the active selection. * Preserved existing button behavior, layout, and appearance while improving focus-state clarity. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
0f2f3e4eb7 |
fix: update storage size unit correctly after navigation (#48932)
Fixes FE-4128. ## What is the current behavior? When updating the global Storage file size limit using a unit other than MB, the selected unit displays an incorrect value after navigating away from the Storage settings page and returning. The updated file size is persisted correctly by the API, but the unit selector does not always reflect the value derived from the persisted configuration. The Save button also remains enabled after successfully saving the updated configuration. ## What is the new behavior? The file size unit selector now correctly reflects the unit derived from the persisted global file size limit after saving and navigating between pages. The form state is also correctly synchronized with the latest Storage configuration after an update, so the Save button returns to its disabled state once the changes have been persisted. ## Additional context The Storage API persists the global file size limit in bytes rather than persisting the selected display unit separately. The dashboard derives the appropriate unit (MB/GB) from the stored byte value when loading the configuration. The issue was caused by the unit Select retaining stale internal state when the form values were reset after the Storage configuration was loaded/refetched. Ensuring the Select is refreshed when the controlled unit changes keeps the displayed unit synchronized with the form state. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved storage settings form initialization when configuration and entitlements load. * Ensured storage unit selections and placeholders display consistently. * Improved form resetting to reflect the latest loaded settings. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
76257f164b |
fix(studio): align storage row icon weight (#48480)
## What kind of change does this PR introduce? Bug fix stacked on #48478. ## What is the current behavior? Storage Explorer renders the custom closed-folder icon at `1.5` but leaves the Lucide open-folder icon at its default `2`. The duplicated file-picker implementation also uses a different set of stroke-width overrides. ## What is the new behavior? A shared `StorageRowIcon` renders loading, open and closed folder, image, audio, video and generic file icons at `1.5` across Storage Explorer, row editing and the bucket file picker. Test by comparing open and closed folders and file-type rows in Storage Explorer and the bucket file picker. | Before | After | | --- | --- | | <img width="524" height="336" alt="CleanShot 2026-08-03 at 18 38 06@2x" src="https://github.com/user-attachments/assets/15eb8b9f-69fc-4eee-8428-d7ec26dce8dc" /> | <img width="522" height="328" alt="CleanShot 2026-08-03 at 18 39 20@2x" src="https://github.com/user-attachments/assets/17b7dddd-8d36-421c-8356-c9c1bd7456e8" /> | | _Thicker image and file icon compared to folder icon_ | _Every icon has the same stroke thickness_ | <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Standardized file, folder, media, and loading icons across storage views. * Improved visual consistency with unified icon sizing, styling, and stroke width. * **Tests** * Added coverage for loading, folder, media, and generic file icon states. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e7796315d2 |
fix sheets stealing focus (#48521)
## What kind of change does this PR introduce? Bug fix. Resolves DEPR-539. ## What is the current behavior? When a focused child unmounts, Radix can move focus to the Sheet wrapper and break the expected tab order. Several callsites suppress the wrapper's tabindex individually. ## What is the new behavior? Sheet still focuses its first interactive child when opened, but the wrapper itself is no longer focusable by default. Callers can opt in with an explicit `tabIndex` when needed. ## Additional context ### Testing Compare this Studio experience on both this branch and `master`: 1. Open any project with an Edge Function. 2. Go to **Edge Functions**, open the function, then click **Test**. 3. Under **Headers**, click **Add Headers**. Click the first header key input, then Tab slowly through the header inputs and remove buttons. On `master`, focus can jump to the whole Sheet. On this branch, focus stays on the controls in order. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved keyboard focus behavior across sheets and panels. * Sheets now focus the first available interactive element when opened, without adding unnecessary focus targets. * Preserved support for programmatic focus and prevented focus from unexpectedly moving to the sheet when focused content is removed. * Updated authentication, integrations, connection, logging, storage, and other sheet interfaces consistently. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
eef0f57309 |
fix(studio): clarify Storage columns keyboard focus and selection (#48222)
## What kind of change does this PR introduce? Accessibility / UX fix ([DEPR-630](https://linear.app/supabase/issue/DEPR-630)). ## What is the current behavior? In Storage **As columns** view, keyboard select is unclear: the checkbox stays hidden until hover, so Tab/Space selection is hard to see. The row actions (three dots) menu also shows a browser default blue outline on Tab. ## What is the new behavior? Same icon/checkbox swap as list/hover, but also on keyboard focus: - Checkbox replaces the icon on hover, `:focus-within`, and when selected (no layout shift) - Checkbox becomes visible when focused via keyboard (without needing hover) - Row gets an inset outline while the checkbox is focused - Folders have no checkbox (non-focusable spacer only) - Row actions trigger uses `focus-ring` instead of the browser blue outline | Before | After | | --- | --- | | <img width="1046" height="362" alt="CleanShot 2026-07-31 at 14 37 47@2x" src="https://github.com/user-attachments/assets/9b827627-17e6-49a6-87a3-1253b4cef1da" /> | <img width="1046" height="390" alt="CleanShot 2026-07-31 at 14 37 13@2x" src="https://github.com/user-attachments/assets/2fd2b426-a8e2-4fda-b1ba-4df728b7b2f1" /> | | _Checkbox focussed but not visually shown_ | _Checkbox focussed and visually shown_ | ## To test 1. Open the **Studio preview** for this PR. 2. Go to **Storage → Files** → open a bucket with several files. 3. Set view to **As columns**. 4. Tab until a **file** checkbox is focused. **Expect:** - Icon is replaced by the checkbox (same slot; neighbouring row icons should not look shifted) - Checkbox visible without hovering - Row shows an inset outline 5. Press **Space** to select. Checkbox stays in the icon slot; selection background applies. 6. Hover another file. Same icon to checkbox swap as before. 7. Tab to the three-dot actions control on a row. Expect the shared focus ring (not a blue browser outline); the menu icon should become visible. 8. Folders: no checkbox in the tab order; click icon/name still opens the folder. 9. Smoke **As list**. Same swap behaviour. ## Additional context From Kemal's DEPR-621 review. |
||
|
|
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 --> |
||
|
|
fcfb0f0222 |
Refactor all usage of form.watch to either useWatch or subscribe (#48436)
## Context Replaces all usage of `form.watch()` to use `useWatch` instead + follows the "name what you watch" convention as specified in the react-hook-form skills. There's also a small refactor in `SmtpForm.tsx` which removes the unnecessary use of a `useState` to track if SMTP is enabled or not <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Updated many Studio forms to watch specific fields more precisely, improving live UI updates for previews, warnings, conditional sections, and validation messages. * Enhanced responsiveness across settings, authentication, billing, storage, integrations, and support flows while keeping save/update behavior the same. * **Refined Experiences** * Improved the analytics table creation flow with tighter, enum-based column type validation and structured, type-specific column options. * **Preserved Behavior** * Maintained existing permission checks, submission flows, and account-management workflows. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ad203ae277 |
Merge compute and disk into Infrastructure (#48370)
## Summary This is the final step in merging compute and disk with infrastructure to become a single place to manage everything. This moves everything we've done in compute and disk over to infrastructure along with redirects. - Makes Infrastructure canonical for the completed compute and disk configuration and usage charts. - Moves Service Versions to General Project Settings. - Removes the legacy Infrastructure activity implementation and constants. - Updates settings navigation, shortcuts, banners, billing links, warning CTAs, usage pages, support suggestions, and other internal entry points. - Adds the permanent `/settings/compute-and-disk` redirect, removes its Next and TanStack routes, regenerates the route tree, and updates the migration checklist. - Preserves query parameters and legacy metric anchors, including `#cpu`. ## Stack 1. #48368 2. #48369 3. #48370 (this PR) ## How to test 1. Check out `chore/infra-compute-3-cutover`. 2. Test the Next implementation with `pnpm dev:studio`, then stop it and test TanStack with `STUDIO_FRAMEWORK=tanstack pnpm dev:studio`. 3. In each implementation, open `/project/<ref>/settings/infrastructure`. Confirm the page contains the usage charts and the Scaling, Compute, Disk, and Advanced configuration sections. 4. Open `/project/<ref>/settings/general`. Confirm Service Versions appears there with its existing name, content, and styling, and no longer appears on Infrastructure. 5. Open `/project/<ref>/settings/compute-and-disk?upgrade=micro#disk`. Confirm it permanently redirects to `/project/<ref>/settings/infrastructure?upgrade=micro#disk`, preserving the query string and hash. 6. Confirm the settings menu exposes Infrastructure and no longer exposes Compute and Disk. Repeat with platform and self-hosted settings. 7. Follow representative entry points from billing usage, resource warning CTAs, upgrade banners, shortcuts, and support suggestions. Confirm they land on Infrastructure and preserve any query parameters or metric anchors such as `#cpu`. 8. Smoke-test compute and disk updates from Infrastructure, including validation, the sticky review footer, and warning/critical chart states. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Consolidated compute and disk management under the **Infrastructure** project settings page. * Added a **Service versions** section to **General** project settings. * **Bug Fixes** * Updated links and upgrade CTAs across the product to route to the correct **Infrastructure** or **Service versions** destinations. * Added permanent redirects from legacy **Compute and Disk** to **Infrastructure**, preserving query/hash. * Improved resource warning upgrade routing for compute scenarios. * **Tests** * Expanded automated coverage for **Infrastructure**, **Service versions**, redirects, and warning-link routing. * **Chores** * Updated ESLint rule baseline configuration for the studio app. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com> |
||
|
|
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> |