## Problem
The design-system Sidebar page was mostly an upstream shadcn paste:
first-person voice, a broken `/blocks` link, missing structure images,
CLI install steps that do not match this monorepo, and a long changelog
/ data-fetching tutorial that do not apply here.
Separately, it still taught classic shadcn **HSL channel** variables
plus `hsl(var(--sidebar-*))`. In this monorepo those tokens are **full
colours**. Mixing the two patterns produces invalid CSS.
Related call-site cleanup:
https://github.com/supabase/supabase/pull/51161
## Solution
- Rewrite the Sidebar docs as a shorter monorepo guide: import from
`'ui'`, structure, theming, provider / sidebar props, menu building
blocks, controlled mode, state styling.
- Move Studio’s `--sidebar-*` aliases into shared `packages/ui` compat
CSS so every app on the shared theme gets working `bg-sidebar`
utilities.
- Drop the duplicate definitions from Studio `globals.css`.
Left alone on purpose: brand / destructive channel tokens and docs that
correctly use `hsl(var(--brand-…))`.
## Review instructions
Design-system preview:
[design-system](https://design-system-git-dnywh-docssidebar-full-colour-tokens-supabase.vercel.app/)
1. [Live Sidebar
docs](https://supabase.com/design-system/docs/components/sidebar) ·
[Preview Sidebar
docs](https://design-system-git-dnywh-docssidebar-full-colour-tokens-supabase.vercel.app/design-system/docs/components/sidebar).
Confirm the page is no longer the upstream essay: no broken images, no
`/blocks` link, imports from `'ui'`, theming shows full-colour aliases.
2. Smoke Studio: left nav should look unchanged (same aliases, now from
compat.css).
3. Optional: in DevTools, confirm `--sidebar-background` resolves to a
full `oklch(...)` colour.
## 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 applies the docs
[style
guide](https://github.com/supabase/supabase/tree/master/apps/docs/style-guide)
## Problem
The theme's primary hue can change in CSS, but Appearance had no way to
try other spot colours. That makes it hard to find controls whose colour
still depends on the fixed Supabase brand palette.
## Solution
Add a **Spot color** control under Appearance → Theme colors
(employee-only via ConfigCat `appearanceSpotColor`, targeted to Supabase
Team Email).
### Spot color UX
- Rainbow spectrum track with a thin outline so pale tracks stay visible
- Live trifecta swatches for `--primary-solid`, `--primary`, and
`--primary-bright` (darkest → lightest) next to the degree readout
- Drag updates are rAF-batched so React paint and CSS preview stay to
one frame
### Canvas tint coupling
- `--surface-hue` is derived in CSS as `calc(var(--primary-hue) +
var(--surface-hue-offset))`
- Dark: offset `0` (same hue as spot)
- Light: offset `180` (complementary canvas tint; brand green ≈157.5° →
rose ≈337.5°)
- No JS override of `--surface-hue`. Changing Spot color moves primary
controls and the low-chroma canvas tint together
### Other theme sliders
- Renamed **Color intensity** → **Surface tint** (it only drives the
neutral ramp via `--chroma`, not spot chroma)
- Meaning-shaped tracks for every knob (spectrum, grey→tint, soft→hard,
dark→light, flat→lift)
- Same outline treatment on those tracks
| Before | After |
| --- | --- |
| <img width="1476" height="2174" alt="CleanShot 2026-10-05 at 15 02
21@2x"
src="https://github.com/user-attachments/assets/d08b0fa8-32af-450e-adce-861f59c9d6ca"
/> | <img width="1474" height="2354" alt="CleanShot 2026-10-05 at 14 56
35@2x"
src="https://github.com/user-attachments/assets/9a1e6183-a4ba-4c8e-a458-bb0eea946db8"
/> |
| _Anyone else_ | _With staff flag, custom settings_ |
## Review instructions
1. Confirm ConfigCat flag `appearanceSpotColor` is on for your staff
account (or flip it in the Dev Toolbar).
2. Open `/account/me` → **Appearance → Theme colors**.
3. Without the flag: Spot color is hidden; other theme sliders still
work.
4. With the flag: drag Spot color in light and dark. Primary controls
and canvas tint should move together; Supabase brand assets should stay
fixed.
5. Raise Surface tint and confirm the canvas hue follows the
complementary (light) or same-hue (dark) offset.
6. Refresh, switch modes, and use **Reset** to check persistence and
defaults.
## What kind of change does this PR introduce?
UI polish / design system: refreshed button styles, related token
tweaks, and a shared floating-button plate.
Resolves DEPR-652.
## What is the current behavior?
Default, primary, and secondary buttons use older fills, borders, and
hover treatments. Primary still leans on brand scale utilities. Default
fills don’t always read as raised chrome across surfaces, and floating
copy / expand / scroll controls can let busy content show through
translucent fills. Call sites hand-roll `rounded-* bg-background`
wrappers for that.
## What is the new behavior?
Refreshes primary, default, and secondary buttons with medium-weight
labels, subtle shadows and inset edges, and smoother transitions.
Light-mode default buttons use a raised fill with an accent hover state,
primary text is brighter, and inline keyboard shortcuts inherit the
button’s colour.
Adds `FloatingPlate`: an opaque `bg-popover` shell for floating default
buttons (and small clusters). Migrates Studio, Docs-related patterns,
www, and `ui-patterns` floaters onto it so busy content no longer shows
through translucent fills. Positioning, z-index, and hover/focus reveal
stay on the plate’s `className`. Use `rounded="full"` for pills.
Also:
- Moves primary onto semantic `--primary` / `--primary-hover` (with a
light-theme override) instead of brand utility fills
- Tokenises button shadows as `--button-shadow-drop` /
`--button-shadow-raised` / `--button-shadow-default` on the Button base
- Aligns hover direction: darken on light mode, lighten on dark mode for
both default and primary
- Default fill stays opaque `bg-card` in light (occlusion) and
translucent `bg-muted` in dark (adapts to the local surface)
- Documents fills and `FloatingPlate` on the design-system Button page
(with a live example)
- Scales shared radius tokens in Studio and www; medium+ Button sizes
use a proportionally softer radius
- Fixes www nav CTA centering (`lg:inline-flex` instead of `lg:block`)
- Query detail Expand/Collapse wires `aria-expanded` / `aria-controls`
| Before | After |
| --- | --- |
| <img width="1074" height="438" alt="CleanShot 2026-09-18 at 15 52
51@2x"
src="https://github.com/user-attachments/assets/ef43da21-b053-4b7e-9ac4-ab8b428228ab"
/> | <img width="1090" height="464" alt="CleanShot 2026-09-18 at 15 50
59@2x"
src="https://github.com/user-attachments/assets/2ddc55fc-4c8d-499c-a280-f3db3d99023c"
/> |
| <img width="1082" height="446" alt="CleanShot 2026-09-18 at 15 52
35@2x"
src="https://github.com/user-attachments/assets/3dd5452d-325a-4e4a-a79d-26c6c6950a31"
/> | <img width="1078" height="446" alt="CleanShot 2026-09-18 at 15 51
13@2x"
src="https://github.com/user-attachments/assets/93666385-3e6e-42e0-9891-9cd6bb935b67"
/> |
## To test
### Design system
- [Button
page](https://design-system-git-chore-button-styles-supabase.vercel.app/design-system/docs/components/button):
default / primary in light and dark; hover should darken on light,
lighten on dark
- Same page: [Floating over
content](https://design-system-git-chore-button-styles-supabase.vercel.app/design-system/docs/components/button#floating-over-content)
/ [Floating
plate](https://design-system-git-chore-button-styles-supabase.vercel.app/design-system/docs/components/button#floating-plate)
example; Copy over SQL should stay opaque
- Spot-check hover on a code preview Copy control
### Docs
[Docs deploy
preview](https://docs-git-chore-button-styles-supabase.vercel.app/docs):
- [Docs
homepage](https://docs-git-chore-button-styles-supabase.vercel.app/docs):
top-right **Sign up** / **Dashboard** primary; menu icon beside it
(default icon button)
- Shrink below `lg` and open the hamburger drawer: bottom **Sign in**
(default) + **Start your project** (primary) medium block buttons
- Tab once for **Skip to content** (FloatingPlate)
- [MCP
guide](https://docs-git-chore-button-styles-supabase.vercel.app/docs/guides/ai-tools/mcp):
project picker
- [Apple
login](https://docs-git-chore-button-styles-supabase.vercel.app/docs/guides/auth/social-login/auth-apple):
**Generate Secret Key** button in the Apple Secret Generator
- Optional opacity check: any guide code block Copy control (e.g. at the
bottom of [Import data into
Supabase](https://docs-git-chore-button-styles-supabase.vercel.app/docs/guides/database/import-data))
### Studio
[Studio deploy
preview](https://studio-staging-git-chore-button-styles-supabase.vercel.app/):
- **Observability → Query Performance**: open a query detail →
Expand/Collapse pill + SQL Copy chip (dark: no bleed-through)
- **Observability → Query Insights**: select a query → Clear query pill
- **Table Editor → any table → Definition** → floating **Open in SQL
Editor**
- **Connect → Framework → Add files**: Copy on the code tabs
(FloatingPlate; light hover follow-up is DEPR-694)
- Tab once for **Skip to content**
### WWW
- [www deploy
preview](https://zone-www-dot-com-git-chore-button-styles-supabase.vercel.app/):
nav Sign in / Start your project vertical centering; hero medium CTAs
radius
---------
Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
## What kind of change does this PR introduce?
Bug fix / design-system token hygiene for form and selector chrome.
## What is the current behavior?
After opaque default-button fills, text fields, selects, and selector
tiles drifted apart: inputs and selects mixed ad-hoc washes, hover
borders bounced between `border-stronger` / `border-foreground-muted`,
invalid fields had no hover step, and composites like InputGroup leaked
inner hover borders.
Follow-up to #48837 (opaque button fills) where Select rest still felt
darker than Input on forms such as scoped access tokens.
## What is the new behavior?
Named control roles and one interactive border:
| Role | Fill | Rest border | Hover / focus / open |
| --- | --- | --- | --- |
| Field (sunk) | `bg-field` | `border-control` | `border-control-hover`
|
| Raised control | `bg-control-raised` | `border-strong` |
`border-control-hover` |
| Overlaying action | card → popover | `border-strong` |
`border-control-hover` |
| Invalid field | `bg-destructive-200` | `border-destructive-400` |
`border-destructive` |
- `--field` / `--control-raised` / `--border-control-hover` live in
`semantic.css` (source of truth for roles; README points there)
- Input / Textarea / InputGroup / legacy TextArea use the field ladder
(incl. invalid hover)
- Select and empty MultiSelect use raised; filled MultiSelect sinks to
field
- Default + dashed Button, CommandMenu trigger, and radio
card/stacked/large use `border-control-hover`
- Studio selector tiles aligned: Connect mode, role impersonation,
DuckLake modes, compute “Contact us”
| Before and After |
| --- |
| <img width="1576" height="759" alt="Access Tokens Account Supabase"
src="https://github.com/user-attachments/assets/4bbe8b2b-a31a-4d63-80ba-04a1a8a5609d"
/> |
| <img width="1576" height="759" alt="Access Tokens Account Supabase"
src="https://github.com/user-attachments/assets/92271223-4103-4cc6-a7c0-9e4ff71cce30"
/> |
## Additional context
`--control-raised` aliases `--card` today (role name so fill can diverge
later). Rest `border-control` / `border-strong` both still map to
`--input` via compat; the shared interactive step is
`--border-control-hover`.
## To test
1. **[Account → Access
Tokens](https://studio-staging-git-dnywh-fixcontrol-surface-tokens-supabase.vercel.app/dashboard/account/tokens)**
Open Generate / New scoped token. Side-by-side Input, Select,
RadioGroupStacked, MultiSelect. Confirm sunk vs raised fills, shared
hover border, MultiSelect flips to sunk once a value is selected. Leave
a required field empty to check invalid rest → hover → focus.
2. **[Org →
Projects](https://studio-staging-git-dnywh-fixcontrol-surface-tokens-supabase.vercel.app/dashboard/org/_)**
Hover the dashed Status filter. Hover default / filled filter buttons
when active. Confirm hover/open borders match.
3. **[Project →
Connect](https://studio-staging-git-dnywh-fixcontrol-surface-tokens-supabase.vercel.app/dashboard/project/_)**
Open Connect from the header. Mode grid tiles: hover + selected borders
match radio cards (no old muted-foreground ring).
4. **[Project →
Compute](https://studio-staging-git-dnywh-fixcontrol-surface-tokens-supabase.vercel.app/dashboard/project/_/settings/infrastructure)**
(optional)
Compute size radios + “Contact us” tile hover.
Replaces abs and from for foreground colours to potentially improve
browser compatibility
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Style**
* Improved semantic color calculations for broader browser
compatibility.
* Refined foreground, muted, and tertiary text colors for more
consistent theme rendering.
* Improved surface overlay contrast across different tones.
* Fine-tuned the light theme’s link color brightness for better visual
balance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
## What kind of change does this PR introduce?
Bug fix
## What is the current behavior?
`text-contrast` / `text-foreground-contrast` resolve to
`--primary-foreground`, which is always the darker of surface /
foreground lightness (text for the green primary fill).
In light mode that is near-black, so contrast text on inverted fills is
wrong: on true black (`bg-black`) it disappears; on dark fills like
`bg-red-900` it shows as a black icon instead of white. Visible
regression on the design-system colour usage page: the `text-contrast`
swatch only shows "Postgres" on hover.
Regression from the colour system rewrite (#47288), which aliased
`--foreground-contrast` → `--primary-foreground`.
## What is the new behavior?
`--foreground-contrast` is defined again as a surface-based inverse of
`--foreground` (light in light mode, dark in dark mode). Tailwind
utilities `text-contrast` and `text-foreground-contrast` map to it.
`--primary-foreground` is unchanged and still used for text on the
primary fill.
## Additional context
### Callsites to test (light mode especially)
| Where to look | What to check |
|---|---|
| [Design system → Colour
usage](https://design-system-git-fix-text-contrast-token-supabase.vercel.app/design-system/docs/color-usage)
| Under **Text**, the `text-contrast` swatch shows "Postgres" without
hovering |
| [Studio staging → Auth
Users](https://studio-staging-git-fix-text-contrast-token-supabase.vercel.app/project/_/auth/users)
→ open any user | Boolean fields (e.g. confirmed): check/X on the black
circle should be **white** (not missing) |
| [Studio staging → Support
new](https://studio-staging-git-fix-text-contrast-token-supabase.vercel.app/support/new)
→ upload a file | Red remove (`X`) badge should be a **white** X (prod
currently shows black) |
| [www →
Contribute](https://zone-www-dot-com-git-fix-text-contrast-token-supabase.vercel.app/contribute)
→ apply at least one filter | Filter count badge: **white** number on
black |
| [Studio staging → Support
link](https://studio-staging-git-fix-text-contrast-token-supabase.vercel.app/support/link)
success state (after linking a ticket) | Check on the brand badge should
use contrast text (light on brand in light mode) |
`Announcement` (`text-foreground-contrast` dismiss icon) is not
currently mounted in any app — covered by the design-system / token
check above.
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES/NO
## What kind of change does this PR introduce?
Bug fix, feature, docs update, ...
## What is the current behavior?
Please link any relevant issues here.
## What is the new behavior?
Feel free to include screenshots if it includes visual changes.
## Additional context
Add any other context or screenshots.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Refreshed theming across the UI to use modern color expressions and
shared theme variables (including OKLCH-based gradients), improving
consistency for charts, code blocks, overlays, icons, and decorative
backgrounds.
* **Bug Fixes**
* Improved light/dark color and gradient consistency across axis/grid
styling, reference lines, buttons/badges, sidebar accents, loaders, and
other visual components.
* **Documentation**
* Updated styling/theming guidance to align with the revised semantic
token system and the updated theme variable usage patterns.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>