From 502c098d90a4f2b41fbb035c6bef9030aa6ccbaf Mon Sep 17 00:00:00 2001 From: Gildas Garcia <1122076+djhi@users.noreply.github.com> Date: Fri, 24 Apr 2026 17:38:01 +0200 Subject: [PATCH] chore: migrate old `` usage to the new Shadcn component (#45211) ## Problem We want to reduce the code we ship and maintain. ## Solution Migrate old `` usage to the new Shadcn component. There's one visual change: no more green background or outline. ## Screenshots ### On `apps/www` Before: image After: image ## Summary by CodeRabbit * **Refactor** * Unified checkbox appearance and behavior across the app for consistent toggles, labels, and interactions. * **Bug Fixes** * Fixed selection issues including shift-select edge cases and click-propagation in lists; added ARIA labels for improved accessibility. * **Chores** * Removed legacy checkbox implementation, associated styles, tests, and deprecated theme entries. --- .../StorageExplorer/FileExplorerColumn.tsx | 53 +++-- .../StorageExplorer/FileExplorerRow.tsx | 12 +- .../StoragePolicies/StoragePoliciesEditor.tsx | 74 +++++-- .../DeleteConfirmationDialogs.tsx | 56 +++-- .../SidePanelEditor/TableEditor/Column.tsx | 7 +- .../TableEditor/TableEditor.tsx | 111 ++++++---- .../[slug]/deploy-button/new-project.tsx | 56 +++-- apps/www/pages/features.tsx | 22 +- packages/ui/index.tsx | 1 - .../components/Checkbox/Checkbox.module.css | 127 ----------- .../src/components/Checkbox/Checkbox.test.jsx | 17 -- .../ui/src/components/Checkbox/Checkbox.tsx | 201 ------------------ .../components/Checkbox/CheckboxContext.tsx | 10 - packages/ui/src/components/Checkbox/index.tsx | 4 - packages/ui/src/lib/theme/defaultTheme.ts | 59 ----- 15 files changed, 261 insertions(+), 549 deletions(-) delete mode 100644 packages/ui/src/components/Checkbox/Checkbox.module.css delete mode 100644 packages/ui/src/components/Checkbox/Checkbox.test.jsx delete mode 100644 packages/ui/src/components/Checkbox/Checkbox.tsx delete mode 100644 packages/ui/src/components/Checkbox/CheckboxContext.tsx delete mode 100644 packages/ui/src/components/Checkbox/index.tsx diff --git a/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerColumn.tsx b/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerColumn.tsx index ae5e9f25e73..97d76548bce 100644 --- a/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerColumn.tsx +++ b/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerColumn.tsx @@ -5,7 +5,7 @@ import { ChevronsDown, ChevronsUp, Copy, Eye, FolderPlus, Upload } from 'lucide- import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { toast } from 'sonner' import { - Checkbox, + Checkbox_Shadcn_ as Checkbox, cn, ContextMenu_Shadcn_, ContextMenuContent_Shadcn_, @@ -143,16 +143,6 @@ export const FileExplorerColumn = ({ } } - const SelectAllCheckbox = () => ( - onSelectAllItemsInColumn(index)} - /> - ) - const getItemKey = useCallback( (index: number) => { const item = columnItems[index] @@ -218,10 +208,24 @@ export const FileExplorerColumn = ({ > {columnFiles.length > 0 ? ( <> - -

- Select all {columnFiles.length} files -

+
+ onSelectAllItemsInColumn(index)} + /> + +
) : (

No files available for selection

@@ -233,7 +237,24 @@ export const FileExplorerColumn = ({ {view === STORAGE_VIEWS.LIST && (
- +
event.stopPropagation()}> + onSelectAllItemsInColumn(index)} + /> + +

Name

Size

diff --git a/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerRow.tsx b/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerRow.tsx index d206131f040..8b7caba93fd 100644 --- a/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerRow.tsx +++ b/apps/studio/components/interfaces/Storage/StorageExplorer/FileExplorerRow.tsx @@ -18,7 +18,7 @@ import { } from 'lucide-react' import type { CSSProperties } from 'react' import { - Checkbox, + Checkbox_Shadcn_ as Checkbox, cn, DropdownMenu, DropdownMenuContent, @@ -333,15 +333,15 @@ export const FileExplorerRow = ({
)} { - event.stopPropagation() - onCheckItem((event.nativeEvent as KeyboardEvent).shiftKey) + // use onClick instead of onCheckedChange to handle shift-key selection + onClick={(event) => { + onCheckItem(event.nativeEvent.shiftKey) }} + aria-label="Check to select this item" />

diff --git a/apps/studio/components/interfaces/Storage/StoragePolicies/StoragePoliciesEditor.tsx b/apps/studio/components/interfaces/Storage/StoragePolicies/StoragePoliciesEditor.tsx index 55b2a6e09cc..313cd71f426 100644 --- a/apps/studio/components/interfaces/Storage/StoragePolicies/StoragePoliciesEditor.tsx +++ b/apps/studio/components/interfaces/Storage/StoragePolicies/StoragePoliciesEditor.tsx @@ -1,5 +1,5 @@ import { noop } from 'lodash' -import { Button, Checkbox, cn, Modal } from 'ui' +import { Button, Checkbox_Shadcn_ as Checkbox, cn, Modal } from 'ui' import { STORAGE_CLIENT_LIBRARY_MAPPINGS } from '../Storage.constants' import { deriveAllowedClientLibraryMethods } from '../Storage.utils' @@ -52,26 +52,58 @@ const PolicyAllowedOperations = ({ allowedOperations = [], onToggleOperation = (

- onToggleOperation('SELECT')} - checked={allowedOperations.includes('SELECT')} - /> - onToggleOperation('INSERT')} - checked={allowedOperations.includes('INSERT')} - /> - onToggleOperation('UPDATE')} - checked={allowedOperations.includes('UPDATE')} - /> - onToggleOperation('DELETE')} - checked={allowedOperations.includes('DELETE')} - /> +
+ onToggleOperation('SELECT')} + checked={allowedOperations.includes('SELECT')} + /> + +
+
+ onToggleOperation('INSERT')} + checked={allowedOperations.includes('INSERT')} + /> + +
+
+ onToggleOperation('UPDATE')} + checked={allowedOperations.includes('UPDATE')} + /> + +
+
+ onToggleOperation('DELETE')} + checked={allowedOperations.includes('DELETE')} + /> + +
{hasUpdateOrDelete && (

diff --git a/apps/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx b/apps/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx index f160ac1833f..ce007312c22 100644 --- a/apps/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/DeleteConfirmationDialogs.tsx @@ -1,7 +1,13 @@ import { ExternalLink } from 'lucide-react' import Link from 'next/link' import { toast } from 'sonner' -import { Alert_Shadcn_, AlertDescription_Shadcn_, AlertTitle_Shadcn_, Button, Checkbox } from 'ui' +import { + Alert_Shadcn_, + AlertDescription_Shadcn_, + AlertTitle_Shadcn_, + Button, + Checkbox_Shadcn_ as Checkbox, +} from 'ui' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import { useTableFilter } from '@/components/grid/hooks/useTableFilter' @@ -216,12 +222,24 @@ const DeleteConfirmationDialogs = ({

Are you sure you want to delete the selected column? This action cannot be undone.

- snap.toggleConfirmationIsWithCascade()} - /> +
+ snap.toggleConfirmationIsWithCascade()} + /> +
+ +

+ Deletes the column and its dependent objects +

+
+
{isDeleteWithCascade && ( Are you sure you want to delete the selected table? This action cannot be undone.

- snap.toggleConfirmationIsWithCascade(!isDeleteWithCascade)} - /> +
+ snap.toggleConfirmationIsWithCascade(!isDeleteWithCascade)} + /> +
+ +

+ Deletes the table and its dependent objects +

+
+
{isDeleteWithCascade && ( diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx index 334cbd8a2b8..5db6e03a62d 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/Column.tsx @@ -5,7 +5,6 @@ import { useState } from 'react' import { Badge, Button, - Checkbox, Checkbox_Shadcn_, cn, Command_Shadcn_, @@ -284,10 +283,10 @@ export const Column = ({
- { + onCheckedChange={() => { const updatedValue = !column.isPrimaryKey onUpdateColumn({ isPrimaryKey: updatedValue, diff --git a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx index 4559ad46ad9..29206299ab1 100644 --- a/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx +++ b/apps/studio/components/interfaces/TableGridEditor/SidePanelEditor/TableEditor/TableEditor.tsx @@ -2,7 +2,7 @@ import type { PostgresTable } from '@supabase/postgres-meta' import { isEmpty, noop } from 'lodash' import { useContext, useEffect, useMemo, useState } from 'react' import { toast } from 'sonner' -import { Badge, Checkbox, Input, SidePanel } from 'ui' +import { Badge, Checkbox_Shadcn_, Input, SidePanel } from 'ui' import { Admonition } from 'ui-patterns' import { ConfirmationModal } from 'ui-patterns/Dialogs/ConfirmationModal' @@ -371,26 +371,31 @@ export const TableEditor = ({ - +
+ { + // if isEnabled, show confirm modal to turn off + // if not enabled, allow turning on without modal confirmation + tableFields.isRLSEnabled + ? setRlsConfirmVisible(true) + : onUpdateField({ isRLSEnabled: !tableFields.isRLSEnabled }) + }} + /> +
+
- } - description="Restrict access to your table by enabling RLS and writing Postgres policies." - checked={tableFields.isRLSEnabled} - onChange={() => { - // if isEnabled, show confirm modal to turn off - // if not enabled, allow turning on without modal confirmation - tableFields.isRLSEnabled - ? setRlsConfirmVisible(true) - : onUpdateField({ isRLSEnabled: !tableFields.isRLSEnabled }) - }} - size="medium" - /> + +

+ Restrict access to your table by enabling RLS and writing Postgres policies. +

+
+
{tableFields.isRLSEnabled ? ( { - track('realtime_toggle_table_clicked', { - newState: tableFields.isRealtimeEnabled ? 'disabled' : 'enabled', - origin: 'tableSidePanel', - }) - onUpdateField({ - isRealtimeEnabled: !tableFields.isRealtimeEnabled, - }) - }} - size="medium" - /> +
+ { + track('realtime_toggle_table_clicked', { + newState: tableFields.isRealtimeEnabled ? 'disabled' : 'enabled', + origin: 'tableSidePanel', + }) + onUpdateField({ + isRealtimeEnabled: !tableFields.isRealtimeEnabled, + }) + }} + /> +
+ +

+ Broadcast changes on this table to authorized subscribers. +

+
+
)} @@ -474,14 +489,24 @@ export const TableEditor = ({ )} {isDuplicating && ( <> - setIsDuplicateRows(!isDuplicateRows)} - size="medium" - /> +
+ setIsDuplicateRows(!isDuplicateRows)} + /> +
+ +

+ This will copy all the data in the table into the new table +

+
+
)} diff --git a/apps/studio/pages/integrations/vercel/[slug]/deploy-button/new-project.tsx b/apps/studio/pages/integrations/vercel/[slug]/deploy-button/new-project.tsx index 0cf3ead66a6..a7e68985006 100644 --- a/apps/studio/pages/integrations/vercel/[slug]/deploy-button/new-project.tsx +++ b/apps/studio/pages/integrations/vercel/[slug]/deploy-button/new-project.tsx @@ -3,7 +3,7 @@ import { useParams } from 'common' import { ChangeEvent, useEffect, useState } from 'react' import { AWS_REGIONS } from 'shared-data' import { toast } from 'sonner' -import { Alert, Button, Checkbox, Input, Listbox } from 'ui' +import { Alert, Button, Checkbox_Shadcn_, Input, Listbox } from 'ui' import { isVercelUrl } from '@/components/interfaces/Integrations/Vercel/VercelIntegration.utils' import { Markdown } from '@/components/interfaces/Markdown' @@ -306,22 +306,48 @@ const CreateProject = () => {
- setShouldRunMigrations(e.target.checked)} - /> +
+ setShouldRunMigrations(!!checked)} + /> +
+ +

+ To get you started quickly, we can create new tables for you with seed (sample) data. + You can delete these tables later. +

+
+
- setDataApiDefaultPrivileges(e.target.checked)} - /> +
+ setDataApiDefaultPrivileges(!!checked)} + /> +
+ +

+ Grants privileges to Data API roles by default, exposing new tables and functions. We + recommend disabling this to control access manually. +

+
+