design system: text color contrast (#38343)

* Refactor Drawer component and add date-fns dependency

Refactored the Drawer component for improved slot-based structure, updated styles, and added 'use client' directive. Added 'date-fns' as a dependency in design-system, updated tsconfig paths for icons, and marked ToggleGroup as a client component.

* nit: add env for svg path

* fix: instructions

* accent color docs and basic tidy

* copy value feature

* improve color contrast

* increase contrast on text-warning in light mode

* update changelog

* replace outdated text-warning utility classes

* remove redundant warning-600

* minor design-system docs updates

* docs updates

* remove unused brand-button class

* update docs

* fix: restore brand default

* update docs brand text color

* low hanging branded text fruit

* Nit refactor and clean  up

* re-add Kemal’s README instructions for hot reload

---------

Co-authored-by: Jonathan Summers-Muir <MildTomato@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
This commit is contained in:
authored and GitHub committed 2025-09-09 11:45:08 +10:00
1 parent 54760cdad3
commit 65b962e771
45 files changed
+148 -237

No files matched your search

+12 -27
View File
@@ -1,46 +1,31 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
# Supabase Design System
Design resources for building consistent user experiences at Supabase.
## Getting Started
First, run the development server:
First, make a copy of _.env.local.example_ and name it _env.local_. Then run the development server as described below.
From within this _design-system_ directory, run:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
Or from the root directory run:
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
```bash
pnpm dev:design-system
```
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
Open [http://localhost:3003](http://localhost:3003) with your browser to see the result.
### Watching for MDX changes
If you would like to watch for changes to MDX files with hot reload, you can run the following command in a separate Terminal shell:
If you would like to watch for changes to MDX files with hot reload, you can run the following command in a separate terminal shell:
```
pnpm content:dev
```
This runs Contentlayer concurrently and watches for any changes.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
+1 -1
View File
@@ -8,7 +8,7 @@ const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Supabase Design System',
description: 'Generated by create next app',
description: 'Design resources for building consistent user experiences at Supabase.',
}
interface RootLayoutProps {
+17 -89
View File
@@ -1,13 +1,26 @@
import { cn } from 'ui/src/lib/utils/cn'
// import { Card } from '@ui/components/shadcn/ui/card'
import color from 'ui/src/lib/tailwind-demo-classes'
import { Grid, GridItem } from './grid'
import { useState } from 'react'
const Colors = ({
definition,
}: {
definition: 'background' | 'border' | 'text' | 'colors' | 'palletes'
}) => {
const [copiedIndex, setCopiedIndex] = useState<number | null>(null)
const handleCopy = async (value: string, index: number) => {
try {
await navigator.clipboard.writeText(value)
setCopiedIndex(index)
setTimeout(() => {
setCopiedIndex(null)
}, 2000)
} catch (err) {
console.error('Failed to copy text: ', err)
}
}
const Example = ({ x }: { x: string }) => {
switch (definition) {
case 'background':
@@ -53,10 +66,11 @@ const Colors = ({
<GridItem
key={i}
className={cn(x.includes('contrast') && 'bg-foreground hover:bg-foreground-light')}
onClick={() => handleCopy(x, i)}
>
<Example x={x} />
<span className="bg-surface-100 rounded-full border px-2 font-mono text-xs text-foreground-lighter group-data-[state=open]:text-foreground">
{x}
<span className="bg-surface-100 rounded-full border px-2 font-mono text-xs text-foreground-lighter group-data-[state=open]:text-foreground text-center">
{copiedIndex === i ? 'Copied!' : x}
</span>
</GridItem>
)
@@ -66,90 +80,4 @@ const Colors = ({
)
}
{
/* <div className="flex flex-col gap-12 py-20">
<div className="flex flex-row gap-12">
<div>
<h5 className="mb-3">Background</h5>
<div className="flex flex-col gap-3">
{color.background.map((x: string, i) => {
return (
<div className="flex gap-3 items-center" key={i}>
<div className={cn(x, 'relative w-12 h-12 border border-overlay shadow')}></div>
<div className="font-mono text-sm bg-surface-100 px-2 py-0.5 rounded-full">
{x}
</div>
</div>
)
})}
</div>
</div>
<div>
<h5 className="mb-3">Border</h5>
<div className="flex flex-col gap-3">
{color.border.map((x, i) => {
return (
<div className="flex gap-3 items-center" key={i}>
<div className={cn(x, 'relative w-12 h-12 border-4')}></div>
<div className="font-mono text-sm bg-surface-100 px-2 py-0.5 rounded-full">
{x}
</div>
</div>
)
})}
</div>
</div>
<div>
<h5 className="mb-3">texts</h5>
<div className="flex flex-col gap-3">
{color.text.map((x, i) => {
return (
<div className="flex gap-3 items-center" key={i}>
<span className={cn(x, 'relative w-12 h-12 flex items-center justify-center')}>
###
</span>
<div className="font-mono text-sm bg-surface-100 px-2 py-0.5 rounded-full">
{x}
</div>
</div>
)
})}
</div>
</div>
</div>
<div className="flex flex-row gap-12">
<div>
<h5 className="mb-3">Colors</h5>
<div className="flex flex-col gap-3">
{color.colors.map((x: string, i) => {
return (
<div className="flex gap-3 items-center" key={i}>
<div className={cn(x, 'relative w-12 h-12 border border-overlay shadow')}></div>
<div className="font-mono text-sm bg-surface-100 px-2 py-0.5 rounded-full">
{x}
</div>
</div>
)
})}
</div>
</div>
<div>
<h5 className="mb-3">Palletes</h5>
<div className="flex flex-col gap-3">
{color.palletes.map((x, i) => {
return (
<div className="flex gap-3 items-center" key={i}>
<div className={cn(x, 'relative w-12 h-12 border border-overlay shadow')}></div>
<div className="font-mono text-sm bg-surface-100 px-2 py-0.5 rounded-full">
{x}
</div>
</div>
)
})}
</div>
</div>
</div>
</div> */
}
export { Colors }
+4 -4
View File
@@ -38,13 +38,13 @@ export const docsConfig: DocsConfig = {
items: [],
},
{
title: 'Color usage',
href: '/docs/color-usage',
title: 'Tailwind Classes',
href: '/docs/tailwind-classes',
items: [],
},
{
title: 'Tailwind classes',
href: '/docs/tailwind-classes',
title: 'Color Usage',
href: '/docs/color-usage',
items: [],
},
{
@@ -4,6 +4,13 @@ description: Latest updates and announcements.
toc: false
---
## 1st Sep 2025 - Update button styles
- [`Color usage`](/design-system/docs/color-usage) page updated
- Color tokens improved for accessibility
[PR](https://github.com/supabase/supabase/pull/38343)
## 18th Oct 2024 - Update multi-select
Improved Multi Select with combobox, badge limit, and more examples.
@@ -1,11 +1,15 @@
---
title: Color usage
description: Colors system breakdown with best practice
description: Colors system breakdown with best practices.
---
Colors available in the Supabase Design System
The shorthand utility classes below simplify our full color palette by providing sensible, contrast-checked defaults. Use them whenever possible to ensure accessible text colors and balanced background fills.
These are examples of using colors with shorthands.
## Text
Use accent text colors (e.g. text-destructive, text-warning) sparingly to avoid visual overload.
<Colors definition={'text'} />
## Background
@@ -60,15 +64,8 @@ This is not to be confused with `Dialogs`, they require to use the same app back
<Colors definition={'border'} />
## Text
These can also be accessed with `foreground`. Like `text-foreground-light`.
<Colors definition={'text'} />
## Other Colors
These can also be accessed with `foreground`. Like `text-foreground-light`.
<Colors definition={'colors'} />
```
@@ -1,37 +1,37 @@
---
title: Tailwind Classes
description: Icons system breakdown. Copy values of Icons.
description: Theming support for Tailwind classes.
---
Supabase is migrating to use tailwind classes that use CSS properties.
Supabase uses Tailwind classes that in turn use CSS properties.
This is to support the concept of theming, so that:
1. It is easy for the team to update the theme without changing 100s of files.
2. We could offer custom or additional themes in future.
1. We can update themes from one place.
2. We can offer custom or additional themes in the future.
## Primitives
We (the Supabase Design team ✨) define primitive color values using Figma Variables.
We define primitive color values using these tokens:
- `background`
- `foreground`
- `border`
- `brand`
- `destructive`
- `warning`
- `destructive`
These values are exported from Figma as a .json file and transformed into tailwind utilities through some scripts under `packages/ui/internals/tokens`.
These values are exported from Figma as a .json file and transformed into Tailwind utilities through some scripts under `packages/ui/internals/tokens`.
Any of these colors are available on any tailwind utility that accepts color. For example:
Any of these colors are available on any Tailwind utility that accepts color. For example:
```jsx
// this uses the default foreground color
// this uses the default foreground color for this theme
<span className="text-foreground"></span>
// this uses the 'light' foreground color
// this uses the 'light' foreground color for this theme (one notch 'softer' than the default)
<span className="text-foreground-light"></span>
// this uses the default warning color
// this uses the default warning color for this theme
<span className="text-warning"></span>
// this uses the '500' warning color
@@ -48,12 +48,12 @@ We support shorthand classes for `background`, `foreground` and `border`. For ex
This will stop you from needing to 'double type' the same utility name.
You might notice we use `foreground` and `background` as prefixes, this is only because it is a Design Token standard, where as tailwind uses `bg` and `text`.
You might notice we use `foreground` and `background` as prefixes, this is only because it is a Design Token standard, where as Tailwind uses `bg` and `text`.
## Mixing colors
Even with shorthands, remember you can use any color. For example, `foreground-light` can also be applied on borders and backgrounds as `border-foreground-light` and `bg-foreground-light`, if needed.
Similarly, background and border primitives can be used on other tailwind utilities.
Similarly, background and border primitives can be used on other Tailwind utilities.
```jsx
// use the text light color for some text
@@ -61,13 +61,13 @@ Similarly, background and border primitives can be used on other tailwind utilit
// we can use the same color for a background
<div className="bg-foreground-light">
<span>I have the same color background as the left example</span>
<span>I have the same background color as the above example</span>
</div>
```
## Opacity support
All the colors are generated using tailwind opacity, like `hsl(--background-default) / var(--tw-bg-opacity)`.
All colors are generated using Tailwind opacity, like `hsl(--background-default) / var(--tw-bg-opacity)`.
This means all the color options in our themes can support opacity rules. For example:
```jsx
@@ -82,7 +82,9 @@ This means all the color options in our themes can support opacity rules. For ex
## Usage
The following tailwind classes are a combination of tailwind utilities and our primitives. They're under development and are likely to change but most are now in use and will probably be permanent fixtures.
The following Tailwind classes are a combination of Tailwind utilities and our primitives.
Note that the shade of the `DEFAULT` value on each scale pattern is variable. Sometimes it is fixed at a particular shade (such as `500` or `600`), but only when contrast is sufficient.
### Foreground (Text)
@@ -118,7 +120,7 @@ Examples:
| `background-control` | Inputs, Radios, Checkboxes |
| `background-button-{DEFAULT}` | Button default |
The `background` part can be omitted when used on the `bg` tailwind utility.
The `background` part can be omitted when used on the `bg` Tailwind utility.
Examples:
+2 -2
View File
@@ -268,7 +268,7 @@ const HomePage = () => (
<TextLink
label="Explore more resources"
url="/guides/resources"
className="no-underline text-brand text-sm"
className="no-underline text-brand-link text-sm"
/>
</div>
@@ -328,7 +328,7 @@ const HomePage = () => (
<TextLink
label="More on Self-Hosting"
url="/guides/self-hosting"
className="no-underline text-brand text-sm"
className="no-underline text-brand-link text-sm"
/>
</div>
</div>
+1 -1
View File
@@ -161,7 +161,7 @@ function Feedback({ className }: { className?: string }) {
'[transition-property:opacity,transform,color] [transition-duration:150ms,250ms,250ms]',
'motion-reduce:[transition-duration:150ms,1ms,300ms]',
'[transition-timing-function:cubic-bezier(.76,0,.23,1)]',
!isNo && 'hover:text-warning-600 hover:border-warning-500',
!isNo && 'hover:text-warning hover:border-warning-500',
isNo && `bg-warning text-warning-200 !border-warning disabled:opacity-100`,
!showNo && 'opacity-0 invisible'
)}
@@ -58,7 +58,7 @@ function FeedbackModal({ visible, page, onCancel, onSubmit }: FeedbackModalProps
href="https://supabase.com/dashboard/support/new"
target="_blank"
rel="noopener noreferrer"
className="text-brand hover:underline"
className="text-brand-link hover:underline"
>
support request
</a>
+1 -1
View File
@@ -20,7 +20,7 @@ function AiPrompt({ className }: { className?: string }) {
className={cn(
'group',
'w-fit rounded-full border px-3 py-1 flex gap-2 items-center text-foreground-light text-sm',
'hover:border-brand hover:text-brand focus-visible:text-brand',
'hover:border-brand hover:text-brand-link focus-visible:text-brand-link',
'transition-colors',
className
)}
@@ -22,7 +22,7 @@ const NavigationMenuCliList = ({ currentLevel, setLevel, id }) => {
<li key={id} className="function-link-item text-foreground-lighter leading-3">
<Link
href={`#${id}`}
className="cursor-pointer transition text-foreground-lighter text-sm hover:text-brand flex gap-3"
className="cursor-pointer transition text-foreground-lighter text-sm hover:text-brand-link flex gap-3"
>
{icon && <img className="w-3" src={`${BASE_PATH}${icon}`} />}
{title}
@@ -99,7 +99,7 @@ const NavigationMenuCliList = ({ currentLevel, setLevel, id }) => {
href={`${menu.parent ?? '/'}`}
className={[
'flex items-center gap-1 text-xs group mb-3',
'text-base transition-all duration-200 text-brand hover:text-brand-600 hover:cursor-pointer ',
'text-base transition-all duration-200 text-brand-link hover:text-brand-600 hover:cursor-pointer ',
].join(' ')}
>
<div className="relative w-2">
@@ -19,7 +19,7 @@ const HeaderLink = React.memo(function HeaderLink(props: {
className={[
' ',
!props.title && 'capitalize',
props.url === pathname ? 'text-brand' : 'hover:text-brand text-foreground',
props.url === pathname ? 'text-brand-link' : 'hover:text-brand-link text-foreground',
].join(' ')}
>
{props.title ?? props.id}
@@ -75,7 +75,7 @@ const ContentAccordionLink = React.memo(function ContentAccordionLink(props: any
'flex items-center gap-2',
'cursor-pointer transition text-sm',
activeItem
? 'text-brand font-medium'
? 'text-brand-link font-medium'
: 'hover:text-foreground text-foreground-lighter',
].join(' ')}
parent={props.subItem.parent}
@@ -104,8 +104,8 @@ const ContentAccordionLink = React.memo(function ContentAccordionLink(props: any
className={[
'cursor-pointer transition text-sm',
subSubItem.url === pathname
? 'text-brand'
: 'hover:text-brand text-foreground-lighter',
? 'text-brand-link'
: 'hover:text-brand-link text-foreground-lighter',
].join(' ')}
>
{subSubItem.name}
+4 -4
View File
@@ -105,7 +105,7 @@ const SideBar = ({ menuItems = [] }: { menuItems: any }) => {
size={14}
strokeWidth={2}
/>
<span className="text-foreground text-sm group-hover:text-brand transition">
<span className="text-foreground text-sm group-hover:text-brand-link transition">
{group.label}
</span>
</Accordion.Trigger>
@@ -119,7 +119,7 @@ const SideBar = ({ menuItems = [] }: { menuItems: any }) => {
'py-1.5 px-5 rounded text-sm transition',
`${
section.url === pathname
? 'bg-background text-brand'
? 'bg-background text-brand-link'
: 'text-foreground-light hover:text-foreground'
}`,
].join(' ')}
@@ -144,7 +144,7 @@ const SideBar = ({ menuItems = [] }: { menuItems: any }) => {
size={14}
strokeWidth={2}
/>
<span className="text-foreground text-sm group-hover:text-brand transition">
<span className="text-foreground text-sm group-hover:text-brand-link transition">
{section.name}
</span>
</Accordion.Trigger>
@@ -157,7 +157,7 @@ const SideBar = ({ menuItems = [] }: { menuItems: any }) => {
'py-1.5 ml-4 px-5 rounded text-sm transition',
`${
item.url === pathname
? 'bg-background text-brand'
? 'bg-background text-brand-link'
: 'text-foreground-light hover:text-foreground'
}`,
].join(' ')}
+1 -1
View File
@@ -40,7 +40,7 @@ function ClientLibHeader({ menuData, className }: ClientLibHeaderProps) {
href={menuData.pkg.repo}
target="_blank"
rel="noreferrer noopener"
className="hover:text-brand focus-visible:text-brand transition-colors"
className="hover:text-brand-link focus-visible:text-brand-link transition-colors"
>
<span className="sr-only">View on GitHub</span>
<Github size={18} />
+2 -2
View File
@@ -221,7 +221,7 @@ function ParamOrTypeDetails({ paramOrType }: { paramOrType: object }) {
/>
{/* @ts-ignore */}
{paramOrType?.comment?.tags?.some((tag) => tag.tag === 'deprecated') && (
<span className="text-xs text-warning-600">Deprecated</span>
<span className="text-xs text-warning">Deprecated</span>
)}
<span className="text-xs text-foreground-muted">{getTypeName(paramOrType)}</span>
</div>
@@ -353,7 +353,7 @@ export function ApiSchemaParamDetails({ param }: { param: IApiEndPoint['paramete
{param.name}
</span>
<RequiredBadge isOptional={!param.required} />
{param.schema?.deprecated && <span className="text-xs text-warning-600">Deprecated</span>}
{param.schema?.deprecated && <span className="text-xs text-warning">Deprecated</span>}
{param.schema && (
<span className="text-xs text-foreground-muted">
{getTypeDisplayFromSchema(param.schema)?.displayName ?? ''}
@@ -1,13 +1,14 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import dayjs from 'dayjs'
import { useMemo, useRef } from 'react'
import { ReactNode, useMemo, useRef } from 'react'
import { useParams } from 'common'
import AlertError from 'components/ui/AlertError'
import { FormHeader } from 'components/ui/Forms/FormHeader'
import { APIKeysData, useAPIKeysQuery } from 'data/api-keys/api-keys-query'
import useLogsQuery from 'hooks/analytics/useLogsQuery'
import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { Card, CardContent, EyeOffIcon, Skeleton, WarningIcon, cn } from 'ui'
import { Card, CardContent, EyeOffIcon, Skeleton, cn } from 'ui'
import {
Table,
TableBody,
@@ -52,8 +53,9 @@ export const SecretAPIKeys = () => {
const { ref: projectRef } = useParams()
const {
data: apiKeysData,
isLoading: isLoadingApiKeys,
error,
isLoading: isLoadingApiKeys,
isError: isErrorApiKeys,
} = useAPIKeysQuery({ projectRef, reveal: false })
const { can: canReadAPIKeys, isLoading: isLoadingPermissions } = useAsyncCheckProjectPermissions(
@@ -90,14 +92,14 @@ export const SecretAPIKeys = () => {
</TableRow>
)
const TableContainer = ({ children }: { children: React.ReactNode }) => (
const TableContainer = ({ children, className }: { children: ReactNode; className?: string }) => (
<div className="pb-30">
<FormHeader
title="Secret keys"
description="These API keys allow privileged access to your project's APIs. Use in servers, functions, workers or other backend components of your application."
actions={<CreateSecretAPIKeyDialog />}
/>
<Card className={cn('w-full overflow-hidden', !empty && 'bg-surface-100')}>
<Card className={cn('w-full overflow-hidden', !empty && 'bg-surface-100', className)}>
<CardContent className="p-0">
<Table className="p-5 table-auto">
<TableHeader>
@@ -147,14 +149,10 @@ export const SecretAPIKeys = () => {
)
}
if (error) {
if (isErrorApiKeys) {
return (
<TableContainer>
<div className="!rounded-b-md overflow-hidden py-12 flex flex-col gap-1 items-center justify-center">
<WarningIcon />
<p className="text-sm text-warning-600">Error loading Secret API Keys</p>
<p className="text-warning/75">{error.message}</p>
</div>
<TableContainer className="border-0">
<AlertError error={error} subject="Failed to load secret API keys" />
</TableContainer>
)
}
@@ -127,10 +127,7 @@ export const UserLogs = ({ user }: UserLogsProps) => {
)}
>
{(is400 || is500) && (
<CriticalIcon
hideBackground
className={cn(is400 && 'text-warning-600')}
/>
<CriticalIcon hideBackground className={cn(is400 && 'text-warning')} />
)}
{status}
</div>
@@ -52,24 +52,24 @@ export const PipelineStatus = ({
if (requestStatus === PipelineStatusRequestStatus.RestartRequested) {
return {
label: 'Restarting',
dot: <Loader2 className="animate-spin w-3 h-3 text-warning-600" />,
color: 'text-warning-600',
dot: <Loader2 className="animate-spin w-3 h-3 text-warning" />,
color: 'text-warning',
tooltip: stateMessages.message,
}
}
if (requestStatus === PipelineStatusRequestStatus.StartRequested) {
return {
label: 'Starting',
dot: <Loader2 className="animate-spin w-3 h-3 text-warning-600" />,
color: 'text-warning-600',
dot: <Loader2 className="animate-spin w-3 h-3 text-warning" />,
color: 'text-warning',
tooltip: stateMessages.message,
}
}
if (requestStatus === PipelineStatusRequestStatus.StopRequested) {
return {
label: 'Stopping',
dot: <Loader2 className="animate-spin w-3 h-3 text-warning-600" />,
color: 'text-warning-600',
dot: <Loader2 className="animate-spin w-3 h-3 text-warning" />,
color: 'text-warning',
tooltip: stateMessages.message,
}
}
@@ -86,8 +86,8 @@ export const PipelineStatus = ({
case PipelineStatusName.STARTING:
return {
label: 'Starting',
dot: <Loader2 className="animate-spin w-3 h-3 text-warning-600" />,
color: 'text-warning-600',
dot: <Loader2 className="animate-spin w-3 h-3 text-warning" />,
color: 'text-warning',
tooltip: stateMessages.message,
}
case PipelineStatusName.STARTED:
@@ -108,7 +108,7 @@ export const PipelineStatus = ({
return {
label: 'Unknown',
dot: <div className="w-2 h-2 bg-warning-600 rounded-full" />,
color: 'text-warning-600',
color: 'text-warning',
tooltip: stateMessages.message,
}
default:
@@ -11,7 +11,7 @@ export const getStatusConfig = (state: TableState['state']) => {
return {
badge: <Badge variant="warning">Queued</Badge>,
description: 'Waiting to start replication',
color: 'text-warning-600',
color: 'text-warning',
}
case 'copying_table':
return {
@@ -41,7 +41,7 @@ export const getStatusConfig = (state: TableState['state']) => {
return {
badge: <Badge variant="warning">Unknown</Badge>,
description: 'Unknown status',
color: 'text-warning-600',
color: 'text-warning',
}
}
}
@@ -16,7 +16,7 @@ import { calculateDiskSizePrice } from '../DiskManagement.utils'
import { BillingChangeBadge } from '../ui/BillingChangeBadge'
import { DiskType, PLAN_DETAILS } from '../ui/DiskManagement.constants'
import { DiskManagementDiskSizeReadReplicas } from '../ui/DiskManagementReadReplicas'
import DiskSpaceBar from '../ui/DiskSpaceBar'
import { DiskSpaceBar } from '../ui/DiskSpaceBar'
import { DiskTypeRecommendationSection } from '../ui/DiskTypeRecommendationSection'
import FormMessage from '../ui/FormMessage'
import { InputPostTab } from '../ui/InputPostTab'
@@ -19,7 +19,7 @@ interface DiskSpaceBarProps {
form: UseFormReturn<DiskStorageSchemaType>
}
export default function DiskSpaceBar({ form }: DiskSpaceBarProps) {
export const DiskSpaceBar = ({ form }: DiskSpaceBarProps) => {
const { ref } = useParams()
const { resolvedTheme } = useTheme()
const { formState, watch } = form
@@ -94,7 +94,7 @@ export default function DiskSpaceBar({ form }: DiskSpaceBarProps) {
<div
className={cn(
'h-[35px] relative border rounded-sm w-full transition',
showNewSize ? 'bg-selection border border-brand-button' : 'bg-surface-300'
showNewSize ? 'bg-selection border border-brand' : 'bg-surface-300'
)}
>
<AnimatePresence>
@@ -103,7 +103,7 @@ const LintPageTabs = ({
tab.id === LINTER_LEVELS.ERROR
? 'text-destructive-600'
: tab.id === LINTER_LEVELS.WARN
? 'text-warning-600'
? 'text-warning'
: 'text-brand-500'
}
>
@@ -87,7 +87,7 @@ export const RegionSelector = ({
<>
<p>Select the region closest to your users for the best performance.</p>
{showNonProdFields && (
<div className="mt-2 text-warning-600">
<div className="mt-2 text-warning">
<p>Only these regions are supported for local/staging projects:</p>
<ul className="list-disc list-inside mt-1">
<li>East US (North Virginia)</li>
@@ -25,17 +25,15 @@ export const ColumnRenderer: Column<LogData, unknown>[] = [
<div
className={cn(
'flex justify-center items-center min-w-[24px]',
isErrorLog(data.row) ? 'text-warning-600' : 'text-green-900'
isErrorLog(data.row) ? 'text-warning' : 'text-green-900'
)}
>
{ICONS[type]}
</div>
<span className={cn('font-mono', isErrorLog(data.row) ? '!text-warning-600' : '')}>
<span className={cn('font-mono', isErrorLog(data.row) ? '!text-warning' : '')}>
{new Date(data.row.timestamp).toISOString()}
</span>
<span
className={cn('truncate font-mono', isErrorLog(data.row) ? '!text-warning-600' : '')}
>
<span className={cn('truncate font-mono', isErrorLog(data.row) ? '!text-warning' : '')}>
{JSON.stringify(data.row.metadata)}
</span>
</RowLayout>
@@ -86,7 +86,7 @@ export const GitHubStatus = () => {
{hasGitBranchSync ? (
<CheckCircle2 size={12} className="text-brand-600" />
) : (
<AlertCircle size={12} className="text-warning-600" />
<AlertCircle size={12} className="text-warning" />
)}
<span>
{hasGitBranchSync
@@ -98,7 +98,7 @@ export const GitHubStatus = () => {
{hasAutomaticBranching ? (
<CheckCircle2 size={12} className="text-brand-600" />
) : (
<AlertCircle size={12} className="text-warning-600" />
<AlertCircle size={12} className="text-warning" />
)}
<span>
{hasAutomaticBranching
@@ -252,7 +252,7 @@ const VercelIntegrationConnectionForm = ({
</div>
{form.formState.isDirty ? (
<p className="mt-2 text-sm text-warning-600">
<p className="mt-2 text-sm text-warning">
Note: Changing these settings will <strong>not</strong> trigger a resync of
environment variables.
</p>
@@ -391,7 +391,7 @@ export const LogsDatePicker = ({
/>
</div>
{isLargeRange && !hideWarnings && (
<div className="text-xs px-3 py-1.5 border-y bg-warning-300 text-warning-foreground border-warning-500 text-warning-600">
<div className="text-xs px-3 py-1.5 border-y bg-warning-300 text-warning-foreground border-warning-500 text-warning">
Large ranges may result in memory errors for <br /> big projects.
</div>
)}
@@ -107,8 +107,8 @@ export function getStatusColor(value?: number | string): Record<'text' | 'bg' |
case 'warning':
case 'redirect':
return {
text: 'text-warning-600 dark:text-warning',
bg: 'bg-warning-300 dark:bg-waning-200',
text: 'text-warning',
bg: 'bg-warning-300 dark:bg-warning-200',
border: 'border border-warning-400/50 dark:border-warning-400/50',
}
case '5':
+1 -1
View File
@@ -58,7 +58,7 @@ const Footer = (props: Props) => {
<SectionContainer className="grid grid-cols-2 md:flex items-center justify-between text-foreground md:justify-center gap-8 md:gap-16 xl:gap-28 !py-6 md:!py-10 text-sm">
<div className="flex flex-col md:flex-row gap-2 md:items-center">
We protect your data.
<Link href="/security" className="text-brand hover:underline">
<Link href="/security" className="text-brand-link hover:underline">
More on Security
</Link>
</div>
@@ -76,7 +76,7 @@ const CustomerQuotesSection = (props: Props) => {
{customer.author}, {customer.role}
</p>
{customer.url && (
<div className="text-brand border-t mt-4 pt-4 cursor-pointer text-sm flex items-center justify-between">
<div className="text-brand-link border-t mt-4 pt-4 cursor-pointer text-sm flex items-center justify-between">
<span>Read Customer Story</span>
<ArrowUpRight />
</div>
+2 -2
View File
@@ -22,7 +22,7 @@ const DPA = () => {
href="https://supabase.com/downloads/docs/Supabase+DPA+250805.pdf"
target="_blank"
rel="noopener noreferrer"
className="text-brand hover:underline"
className="text-brand-link hover:underline"
onClick={() =>
sendTelemetryEvent({
action: 'dpa_pdf_opened',
@@ -42,7 +42,7 @@ const DPA = () => {
href="https://supabase.com/dashboard/org/_/documents"
target="_blank"
rel="noopener noreferrer"
className="text-brand hover:underline"
className="text-brand-link hover:underline"
>
request it from the legal documents page
</a>{' '}
@@ -248,7 +248,7 @@ const PartnerDetails = ({ partner }: { partner: Partner }) => {
<span className="text-lighter">Category</span>
<Link
href={`/partners/integrations#${partner.category.toLowerCase()}`}
className="text-brand hover:underline transition-colors"
className="text-brand-link hover:underline transition-colors"
>
{partner.category}
</Link>
@@ -260,7 +260,7 @@ const PartnerDetails = ({ partner }: { partner: Partner }) => {
href={partner.website}
target="_blank"
rel="noreferrer"
className="text-brand hover:underline transition-colors"
className="text-brand-link hover:underline transition-colors"
>
{new URL(partner.website).host}
</a>
@@ -273,7 +273,7 @@ const PartnerDetails = ({ partner }: { partner: Partner }) => {
href={partner.docs}
target="_blank"
rel="noreferrer"
className="text-brand hover:underline transition-colors"
className="text-brand-link hover:underline transition-colors"
>
<span className="flex items-center space-x-1">
<span>Learn</span>
@@ -119,7 +119,7 @@ export const GlassPanel = ({
</div>
{children && <span className="text-sm text-foreground-light flex-grow">{children}</span>}
{showLink && <span className="text-brand justify-end text-sm">Learn more</span>}
{showLink && <span className="text-brand-link justify-end text-sm">Learn more</span>}
</div>
</div>
)
+1 -1
View File
@@ -102,7 +102,7 @@ export const IconPanel = ({
{children && (
<span className="text-sm text-foreground-light not-prose">{children}</span>
)}
{showLink && <span className="text-brand justify-end text-sm">Learn more</span>}
{showLink && <span className="text-brand-link justify-end text-sm">Learn more</span>}
</div>
</div>
</div>
@@ -10,7 +10,6 @@
--secondary-400: 0deg 0% 100%;
--secondary-200: 0deg 0% 100%;
--brand-link: 153.1deg 60.2% 52.7%;
--brand-button: 151.8deg 47.1% 40.8%;
--brand-default: 153.1deg 60.2% 52.7%;
--brand-600: 153deg 59.5% 70%;
--brand-500: 153.5deg 61.8% 21.6%;
@@ -10,7 +10,6 @@
--secondary-400: 20deg 93.2% 40.4%;
--secondary-200: 17.7deg 78.9% 27.8%;
--brand-link: 163.9deg 53.2% 15.1%;
--brand-button: 175.6deg 61.8% 21.6%;
--brand-default: 163.9deg 53.2% 15.1%;
--brand-600: 156.3deg 59.5% 70%;
--brand-500: 175.6deg 61.8% 21.6%;
@@ -14,7 +14,6 @@
--secondary-400: 248.3deg 54.5% 25.9%;
--secondary-200: 248deg 53.6% 11%;
--brand-link: 155deg 100% 38.6%;
--brand-button: 154.9deg 100% 19.2%;
--brand-default: 153.1deg 60.2% 52.7%;
--brand-600: 154.9deg 59.5% 70%;
--brand-500: 154.9deg 100% 19.2%;
+1 -2
View File
@@ -12,14 +12,13 @@
--secondary-400: 248.3deg 54.5% 25.9%;
--secondary-200: 248deg 53.6% 11%;
--brand-link: 155deg 100% 38.6%;
--brand-button: 154.9deg 100% 19.2%;
--brand-default: 153.1deg 60.2% 52.7%;
--brand-600: 154.9deg 59.5% 70%;
--brand-500: 154.9deg 100% 19.2%;
--brand-400: 155.5deg 100% 9.6%;
--brand-300: 155.1deg 100% 8%;
--brand-200: 162deg 100% 2%;
--warning-default: 38.9deg 100% 42.9%;
--warning-default: 38.9deg 100% 42.9%; /* warning-600 */
--warning-600: 38.9deg 100% 42.9%;
--warning-500: 34.8deg 90.9% 21.6%;
--warning-400: 33.2deg 100% 14.5%;
+1 -2
View File
@@ -10,14 +10,13 @@
--secondary-400: 248.3deg 54.5% 25.9%;
--secondary-200: 248deg 53.6% 11%;
--brand-link: 153.4deg 100% 36.7%;
--brand-button: 151.8deg 47.1% 40.8%;
--brand-default: 152.9deg 60% 52.9%;
--brand-600: 156.5deg 86.5% 26.1%;
--brand-500: 155.3deg 78.4% 40%;
--brand-400: 151.3deg 66.9% 66.9%;
--brand-300: 147.5deg 72% 80.4%;
--brand-200: 147.6deg 72.5% 90%;
--warning-default: 38.9deg 100% 57.1%;
--warning-default: 30.3deg 80.3% 47.8%; /* warning-600 */
--warning-600: 30.3deg 80.3% 47.8%;
--warning-500: 36.3deg 85.7% 67.1%;
--warning-400: 41.9deg 100% 81.8%;
-4
View File
@@ -603,10 +603,6 @@ module.exports = {
cssVariable: 'var(--brand-default)',
value: 'hsl(153.10000000000002, 60.2%, 52.7%)',
},
'brand-button': {
cssVariable: 'var(--brand-button)',
value: 'hsl(154.89999999999998, 100%, 19.2%)',
},
'brand-link': {
cssVariable: 'var(--brand-link)',
value: 'hsl(155, 100%, 38.6%)',
+2 -2
View File
@@ -177,7 +177,7 @@ const IconContainerVariants = cva('', {
link: 'text-brand-600',
text: 'text-foreground-lighter',
danger: 'text-destructive-600',
warning: 'text-warning-600',
warning: 'text-warning',
},
},
})
@@ -195,7 +195,7 @@ const loadingVariants = cva('', {
link: 'text-brand-600',
text: 'text-foreground-muted',
danger: 'text-destructive-600',
warning: 'text-warning-600',
warning: 'text-warning',
},
loading: {
default: '',
+3 -3
View File
@@ -91,7 +91,7 @@ const WarningIcon: React.FC<SVGProps<SVGSVGElement> & StatusIconProps> = ({
className={cn(
!hideBackground
? 'w-4 h-4 p-0.5 bg-warning-600 text-warning-200 rounded'
: 'w-3 h-3 text-warning-600',
: 'w-3 h-3 text-warning',
props.className
)}
>
@@ -151,7 +151,7 @@ const EyeIcon: React.FC<SVGProps<SVGSVGElement> & StatusIconProps> = ({
className={cn(
!hideBackground
? 'w-4 h-4 p-0.5 bg-warning-600 text-warning-200 rounded'
: 'w-3 h-3 text-warning-600',
: 'w-3 h-3 text-warning',
props.className
)}
>
@@ -180,7 +180,7 @@ const EyeOffIcon: React.FC<SVGProps<SVGSVGElement> & StatusIconProps> = ({
className={cn(
!hideBackground
? 'w-4 h-4 p-0.5 bg-foreground-light text-background rounded'
: 'w-3 h-3 text-warning-600',
: 'w-3 h-3 text-warning',
props.className
)}
>
@@ -9,7 +9,7 @@ const badgeVariants = cva(
variants: {
variant: {
default: 'bg-surface-200 text-foreground-light border border-strong',
warning: 'bg-warning text-warning-600 border border-warning-500',
warning: 'bg-warning text-warning border border-warning-500',
success: 'bg-brand text-brand-600 border border-brand-500',
destructive: 'bg-destructive text-destructive-600 border border-destructive-500',
brand: 'bg-brand text-brand-600 border border-brand-500',
+10 -2
View File
@@ -31,7 +31,16 @@ export default {
'border-button',
'border-button-hover',
],
text: ['text', 'text-light', 'text-lighter', 'text-muted', 'text-contrast'],
text: [
'text',
'text-light',
'text-lighter',
'text-muted',
'text-contrast',
'text-destructive',
'text-warning',
'text-brand',
],
colors: [
'bg-destructive-200',
'bg-destructive-300',
@@ -51,7 +60,6 @@ export default {
'bg-brand-500',
'bg-brand-600',
'bg-brand',
'bg-brand-button',
'bg-brand-link',
'bg-_secondary-200',
'bg-_secondary-400',