chore: CSS cleanup (#47443)

## Problem

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

## Solution

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

## Notes

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

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

## Summary by CodeRabbit

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

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

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Gildas Garcia authored and GitHub committed 2026-06-30 18:06:38 +02:00
1 parent 1edcd311dc
commit 70c3bafe63
23 files changed
+15 -372

No files matched your search

@@ -1,3 +1,3 @@
export const DefaultValue = () => {
return <span className="sb-grid-default-value opacity-50">DEFAULT</span>
return <span className="opacity-50">DEFAULT</span>
}
@@ -30,8 +30,8 @@ export const DropdownControl = ({
<DropdownMenu>
<DropdownMenuTrigger className={className}>{children}</DropdownMenuTrigger>
<DropdownMenuContent side={side} align={align}>
<div className="dropdown-control" style={{ maxHeight: '30vh' }}>
{options.length === 0 && <p className="dropdown-control__empty-text">No more items</p>}
<div className="overflow-auto" style={{ maxHeight: '30vh' }}>
{options.length === 0 && <p>No more items</p>}
{options.map((x) => {
return (
<DropdownMenuItemTooltip
@@ -1,3 +1,3 @@
export const EmptyValue = () => {
return <span className="sb-grid-empty-value opacity-50">EMPTY</span>
return <span className="block opacity-50">EMPTY</span>
}
@@ -1,3 +1,3 @@
export const NullValue = () => {
return <span className="null-value opacity-50">NULL</span>
return <span className="block opacity-50">NULL</span>
}
@@ -165,7 +165,7 @@ export const JsonEditor = <TRow, TSummaryRow = unknown>({
<div
className={`${
!!value && jsonString.trim().length == 0 ? 'sb-grid-fill-container' : ''
} sb-grid-json-editor__trigger`}
} text-grid overflow-hidden text-ellipsis px-2`}
onClick={() => setIsPopoverOpen(!isPopoverOpen)}
>
{value === null || value === '' ? <NullValue /> : jsonString}
@@ -25,7 +25,7 @@ export function NumberEditor<TRow, TSummaryRow = unknown>({
return (
<input
className="sb-grid-number-editor"
className="h-full w-full px-2"
ref={autoFocusAndSelect}
value={value ?? ''}
onChange={onChange}
@@ -119,7 +119,7 @@ export const TextEditor = <TRow, TSummaryRow = unknown>({
<div
className={cn(
!!value && value.toString().trim().length === 0 && 'sb-grid-fill-container',
'sb-grid-text-editor__trigger'
'text-grid overflow-hidden text-ellipsis px-2'
)}
onClick={() => setIsPopoverOpen(!isPopoverOpen)}
>
@@ -42,7 +42,7 @@ function BaseEditor<TRow, TSummaryRow = unknown>({
return (
<input
className="sb-grid-time-editor"
className="h-full w-full px-2"
ref={autoFocusAndSelect}
defaultValue={value ?? ''}
onChange={onChange}
@@ -56,8 +56,8 @@ export const ForeignKeyFormatter = (props: Props) => {
foreignKeyColumn?.format === 'bytea' && !!value ? convertByteaToHex(value) : value
return (
<div className="sb-grid-foreign-key-formatter flex justify-between">
<span className="sb-grid-foreign-key-formatter__text">
<div className="flex w-full items-center justify-between flex justify-between">
<span className="m-0 grow overflow-hidden text-ellipsis">
{formattedValue === null ? <NullValue /> : formattedValue}
</span>
{isLoading && formattedValue !== null && (
@@ -290,7 +290,7 @@ export const SortPopoverPrimitive = ({
asChild
variant="dashed"
iconRight={<ChevronDown size="14" className="text-foreground-light" />}
className="sb-grid-dropdown__item-trigger"
className="my-1"
data-testid="table-editor-pick-column-to-sort-button"
>
<span>Pick {localSorts.length > 1 ? 'another' : 'a'} column to sort by</span>
@@ -249,15 +249,7 @@ const TableNodeComponent = ({
)}
>
{column.isPrimary && (
<Key
size={8}
strokeWidth={1}
className={cn(
// 'sb-grid-column-header__inner__primary-key'
'shrink-0',
'text-light'
)}
/>
<Key size={8} strokeWidth={1} className={cn('shrink-0', 'text-light')} />
)}
{column.isNullable && (
<DiamondIcon size={8} strokeWidth={1} className="shrink-0 text-light" />
@@ -235,7 +235,7 @@ export const UserImpersonationSelector = () => {
<InputGroup>
<InputGroupInput
size="tiny"
className="table-editor-search border-none"
className="pr-10 border-none"
placeholder="Search by id, email, phone, or name..."
onChange={(e) => setSearchText(e.target.value)}
value={searchText}
@@ -182,7 +182,7 @@ export const GridHeaderActions = ({ table, isRefetching }: GridHeaderActionsProp
}
return (
<div className="sb-grid-header__inner">
<div className="flex items-center space-x-2">
{showHeaderActions && (
<div className="flex items-center gap-x-2">
{isReadOnly && (
-1
View File
@@ -1,5 +1,4 @@
import '@/styles/code.css'
import '@/styles/editor.css'
import '@/styles/focus.css'
import '@/styles/globals.css'
import '@/styles/graphiql-base.css'
-1
View File
@@ -2,7 +2,6 @@
import 'react-data-grid/lib/styles.css'
import '@/styles/code.css'
import '@/styles/editor.css'
import '@/styles/focus.css'
// Vite-only: defines @font-face for the custom fonts. The Next pipeline
// (pages/_app.tsx) loads these via next/font instead, so this import has no
-14
View File
@@ -108,20 +108,6 @@
padding: 4px 8px;
}
}
&.codeBlockWrapper .sbui-btn-container {
position: absolute;
top: 2px;
right: 3px;
visibility: hidden;
opacity: 0;
}
&.codeBlockWrapper:hover .sbui-btn-container {
visibility: visible;
opacity: 1;
}
}
.CustomCodeBlock {
-28
View File
@@ -1,28 +0,0 @@
@reference "./globals.css";
.table-editor-columns .sbui-formlayout--responsive {
gap: 0rem !important;
}
.table-editor-column-type .sbui-listbox-option-container {
width: 400px;
}
.table-editor-column-type .sbui-listbox {
@apply px-2;
}
.column-type-disabled {
@apply pointer-events-none;
}
.column-type-disabled .sbui-listbox-label {
@apply opacity-50;
}
/* This fix should ideally be in the UI library */
.table-editor-search {
input {
@apply pr-10;
}
}
-208
View File
@@ -298,106 +298,6 @@
color: inherit;
}
/*
DropdownControl
*/
.dropdown-control {
@apply overflow-auto;
}
.dropdown-control .sbui-typography {
@apply block px-2 py-4;
}
/*
NullValue
*/
.null-value {
@apply block;
}
/*
CheckboxEditor
*/
.sb-grid-checkbox-editor {
@apply flex h-full w-full;
}
.sb-grid-checkbox-editor__input {
@apply h-4 w-4;
outline: 4px auto -webkit-focus-ring-color;
}
/*
JsonEditor
*/
.sb-grid-json-editor__trigger {
@apply text-grid overflow-hidden text-ellipsis px-2;
}
/*
NumberEditor
*/
.sb-grid-number-editor {
@apply h-full w-full px-2;
}
/*
SelectEditor
*/
.sb-grid-select-editor {
button {
@apply border-none rounded-none shadow-none;
box-shadow: none !important;
}
}
/*
TextEditor
*/
.sb-grid-text-editor__trigger {
@apply text-grid overflow-hidden text-ellipsis px-2;
}
/*
TimeEditor
*/
.sb-grid-time-editor {
@apply h-full w-full px-2;
}
/*
Footer
*/
.sb-grid-footer {
@apply bg-surface-100 flex h-10 items-center justify-between px-2;
}
.sb-grid-footer__inner {
@apply flex items-center;
}
/*
ForeignKeyFormatter
*/
.sb-grid-foreign-key-formatter {
@apply flex w-full items-center justify-between;
}
.sb-grid-foreign-key-formatter__text {
@apply m-0 grow overflow-hidden text-ellipsis;
}
/*
ColumnHeader
*/
@@ -432,22 +332,6 @@
@apply border-brand text-brand;
}
/*
Grid
*/
.sb-grid-grid--loading {
@apply flex justify-center bg-transparent;
}
.sb-grid-grid--loading__inner {
@apply flex items-center;
}
.sb-grid-grid--loading__inner__text {
@apply m-8;
}
/*
SelectColumn
*/
@@ -464,95 +348,3 @@
/* @apply focus:ring-brand-300; */
@apply border-background-surface-100;
}
/*
Header
*/
.sb-grid-header {
@apply bg-surface-100 flex h-10 justify-between px-2;
}
.sb-grid-header__inner {
@apply flex items-center space-x-2;
}
.sb-grid-header__inner__divider {
@apply py-2;
}
.row_header__selected-rows {
@apply ml-2 mr-2;
}
/*
StatusLabel
*/
.sb-grid-status-label {
@apply text-grid text-white;
}
.sb-grid-status-label__no-msg {
@apply flex h-5 w-5;
}
.sb-grid-status-label__no-msg > div {
@apply m-auto h-2 w-2 rounded-full bg-green-900;
}
/*
Empty value
*/
.sb-grid-empty-value {
@apply block;
}
/*
header/sort/SortDropdown
*/
.sb-grid-sort-popover {
@apply w-96;
}
.sb-grid-dropdown__empty {
@apply py-2;
}
.sb-grid-dropdown__empty__text {
@apply block;
}
.sb-grid-dropdown__item-trigger {
@apply my-1;
}
/*
header/sort/SortRow
*/
.sb-grid-sort-row {
@apply flex justify-between space-x-3;
}
.sb-grid-sort-row__item {
@apply flex items-center space-x-3;
}
.sb-grid-sort-row__item__remove {
@apply bg-transparent p-0 hover:bg-transparent;
}
.sb-grid-sort-row__item__label {
@apply flex items-center space-x-2;
}
.sb-grid-sort-row__item_toogle {
@apply flex w-28 items-center gap-0 space-x-3;
}
.sb-grid-sort-row__item__move {
@apply flex cursor-move;
}
-41
View File
@@ -1,42 +1,5 @@
@reference "./globals.css";
.storage-container {
.sbui-space-col {
@apply grow;
#files {
@apply h-full;
}
}
.sbui-btn {
@apply focus:outline-hidden;
}
.sbui-btn-default {
@apply border;
border-color: transparent !important;
}
.sbui-checkbox-container {
@apply w-auto;
}
.sbui-input-container {
input {
@apply text-sm;
}
.sbui-btn-container {
.sbui-btn {
@apply py-1;
}
}
}
.sbui-menu__item {
span {
@apply text-sm;
}
}
.sbui-overlay-container {
@apply z-10;
}
}
/* May need to just comment this out, the smooth scrolling looks weird */
/* .file-explorer { */
/* scroll-behavior: smooth; */
@@ -53,7 +16,3 @@ button[aria-haspopup='menu']:focus-visible {
.sql-editor-container {
@apply p-0;
}
.sbui-dropdown__trigger:focus {
outline: none;
}
-27
View File
@@ -265,11 +265,6 @@ h6:not(.overwrite) {
@apply text-foreground-lighter text-xs;
}
.sbui-border-fix select {
@apply border-solid;
border-width: 1px;
}
.section--masked {
/* overflow: hidden; */
}
@@ -313,20 +308,6 @@ h6:not(.overwrite) {
@apply border border-strong;
}
.sbui-tabs--alt div[role='tablist'] .sbui-btn-primary {
@apply bg-border-stronger text-white;
text-shadow: none;
font-weight: 400;
}
.sbui-tabs--alt div[role='tablist'] .sbui-btn-text {
@apply text-border-muted;
font-weight: 400;
shadow: none;
}
.sbui-tabs--underline-alt div[role='tablist'] .sbui-tab-button-underline--active {
@apply border-foreground-muted;
}
/* override position of tabs */
.dashboard-tabs > div > div {
justify-content: center;
@@ -351,14 +332,6 @@ table {
border-collapse: collapse;
}
.sbui-typography-container thead {
@apply text-border;
}
.sbui-typography a {
@apply wrap-break-word;
}
/*
* sets the image in @Next/Image components to respect the height of the content
*/
-8
View File
@@ -762,14 +762,6 @@
"import": "./src/form/Layout/FormLayout.tsx",
"types": "./src/form/Layout/FormLayout.tsx"
},
"./form/Layout/InputIconContainer.module.css": {
"import": "./src/form/Layout/InputIconContainer.module.css",
"types": "./src/form/Layout/InputIconContainer.module.css"
},
"./form/Layout/InputIconContainer": {
"import": "./src/form/Layout/InputIconContainer.tsx",
"types": "./src/form/Layout/InputIconContainer.tsx"
},
"./form/utils": {
"import": "./src/form/utils.tsx",
"types": "./src/form/utils.tsx"
@@ -1,6 +0,0 @@
.sbui-input-icon-container {
@apply absolute inset-y-0 left-0 pl-2 flex items-center pointer-events-none;
/* set the default color of the icon */
@apply text-gray-600;
@apply dark:text-white;
}
@@ -1,15 +0,0 @@
import { cn } from 'ui'
import styleHandler from 'ui/src/lib/theme/styleHandler'
export default function InputIconContainer({
icon,
className,
size,
}: {
icon: React.ReactNode
className?: string
size: 'tiny' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge' | 'xxxlarge' | null
}) {
const __styles = styleHandler('inputIconContainer')
return <div className={cn(__styles.base, __styles.size[size ?? 'small'], className)}>{icon}</div>
}