mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 20:05:06 +03:00
Finishes the `*-opacity-*` → slash-modifier conversion that the
`@tailwindcss/upgrade` tool couldn't complete because the paired
color/opacity classes weren't always adjacent (intervening tokens,
variant prefixes, or absent base color).
Mechanical same-line paired rewrites (perl):
bg-{color} bg-opacity-N → bg-{color}/N
bg-opacity-N bg-{color} → bg-{color}/N (reversed order)
bg bg-opacity-N → bg/N (bare `bg` alias)
(analogous for border-, ring-, divide-)
Hand-edited ambiguous stragglers:
- Rewrote `{variant}:{prefix}-opacity-N` to `{variant}:{prefix}-{base-color}/N`
where a base color was present on the same element (TriggerSheet,
ExitSurveyModal, UpgradeModal, DeleteProjectModal, CommandMenu,
MultiSelectDeprecated).
- Dropped no-op `bg-opacity-100` / `hover:bg-opacity-100` where the
companion rule already implied full opacity (BillingChangeBadge,
SupportAccessToggle, MobileNavigationBar, Announcement/Badge,
LWAnnouncement, Button link variant).
- Rewrote `hover:border-opacity-30` paired with a later base color to
`hover:border-foreground-muted/30` in Announcement/Badge.
- Reworked ComputeBadge state-open styles: `group-data-[state=open]:
bg-opacity-20` / `ring-2/20` (invalid) → `group-data-[state=open]:
bg-{color}/20 ring-{color}/20` mapped per `smallCompute` branch.
- Migrated `defaultTheme.ts` badge theme: dropped `bg-opacity-10` from
base, applied `/10` to each color variant's bg. Deleted dead `utils`
block (declared but never referenced/exported). Fixed stray `bg-200`
typo → `bg-gray-200/10`.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> (+16 squashed commits)
Squashed commits:
[3f18aa64d5] chore(packages/marketing): run @tailwindcss/upgrade v4 codemods
Automated output from `pnpm dlx @tailwindcss/upgrade --force` executed
within `packages/marketing/`, using the same temporary
`_upgrade-entry.css` pattern. Spurious tailwindcss dep addition was
reverted.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[dfd9039173] chore(packages/dev-tools): run @tailwindcss/upgrade v4 codemods
Automated output from `pnpm dlx @tailwindcss/upgrade --force` executed
within `packages/dev-tools/`, using the same temporary `_upgrade-entry.css`
pattern as the other shared packages. The spurious tailwindcss dep
addition was reverted — this package is a consumer, not a Tailwind
owner.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[f815ff2905] chore(packages/ui-patterns): run @tailwindcss/upgrade v4 codemods
Automated output from `pnpm dlx @tailwindcss/upgrade --force` executed
within `packages/ui-patterns/`. Same temporary `_upgrade-entry.css`
pattern as the `packages/ui` run — added to give the tool a CSS entry
to scan templates against, removed before committing.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[999168249a] chore(packages/ui): run @tailwindcss/upgrade v4 codemods
Automated output from `pnpm dlx @tailwindcss/upgrade --force` executed
within `packages/ui/`. A temporary `_upgrade-entry.css` was added during
the run (with `@import "tailwindcss"` + `@config` bridge to the shared
config) so the tool could discover a CSS entry and drive template
migration across `src/**/*.tsx`; it's removed before committing.
Per-app upgrade runs skip `packages/ui` as "outside repository", so this
is the only way to cover it without running the tool at the workspace
root.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[32cdf2253a] chore(ui-library): run @tailwindcss/upgrade v4 codemods
Automated output from `pnpm dlx @tailwindcss/upgrade --force` executed
within `apps/ui-library/`. Also bundles minor `pnpm-lock.yaml` churn
(peer-dep reshuffling triggered by the tool's install pass).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[bf54bac2f1] chore(lite-studio): run @tailwindcss/upgrade v4 codemods
Automated output from `pnpm dlx @tailwindcss/upgrade --force` executed
within `apps/lite-studio/`. The first attempt failed on an unknown
utility (`text-foreground-light`) because `typography.css` loaded its
own Tailwind context without access to the shared plugin. After
switching to `@reference './app.css'` (the same pattern used in
`apps/studio/styles/typography.css`), the tool ran cleanly.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[e7373cf938] chore(www): run @tailwindcss/upgrade v4 codemods
Automated output from `pnpm dlx @tailwindcss/upgrade --force` executed
within `apps/www/`. Also:
- Bumps `apps/www/package.json` tailwindcss from `^3.4.1` to `^4.2.4`
(www had an explicit dep rather than the catalog reference).
- Fixes a double-slash path glitch the tool emitted in
`apps/www/styles/index.css` (`@config '..//tailwind.config.js'` →
`@config '../tailwind.config.js'`).
- `pnpm-lock.yaml` bundled here as it reflects cumulative dep changes
from www plus the earlier `apps/learn` addition.
The tool warned that `apps/www/postcss.config.js` contains dynamic
JavaScript and was not auto-migrated — that file needs a manual pass
in a follow-up.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[9fcbb5f28c] chore(studio): run @tailwindcss/upgrade v4 codemods
Automated output from `pnpm dlx @tailwindcss/upgrade --force` executed
within `apps/studio/`. Biggest diff of any single app.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[e77b3b9a27] chore(learn): run @tailwindcss/upgrade v4 codemods
Automated output from `pnpm dlx @tailwindcss/upgrade --force` executed
within `apps/learn/`. Also adds `tailwindcss: ^4.2.4` to the app's
package.json (the upgrade tool injects this when the app didn't
previously declare tailwindcss directly).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[5ad834d688] chore(docs): run @tailwindcss/upgrade v4 codemods
Automated output from `pnpm dlx @tailwindcss/upgrade --force` executed
within `apps/docs/`.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[f3101bf306] chore(design-system): run @tailwindcss/upgrade v4 codemods
Automated output from `pnpm dlx @tailwindcss/upgrade --force` executed
within `apps/design-system/`. Handles deprecated-class renames, `@apply`
prefix-bang → suffix-bang syntax, gradient utility renames, and related
v4-aware rewrites. Only files under `apps/design-system/` are touched;
shared packages are skipped by the tool when run from a single app.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[f60e5d01d1] chore: pin tailwindcss to 4.2.4 in all package.json files
Replace `"tailwindcss": "catalog:"` and `"@tailwindcss/postcss": "catalog:"`
with explicit `4.2.4` pins so `@tailwindcss/upgrade` can run without a
catalog-vs-node_modules version mismatch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[0676c22a12] chore: rename deprecated Tailwind utility classes
Apply the non-opacity class renames from Tailwind v3.4 → v4, across all
source files (`*.tsx`, `*.ts`, `*.jsx`, `*.js`, `*.css`, `*.mdx`),
excluding `examples/` and the vendored `apps/studio/public/monaco-editor`
bundle.
- `flex-grow` → `grow`
- `flex-shrink` → `shrink`
- `overflow-ellipsis` → `text-ellipsis`
- `shadow-sm` → `shadow-xs`
- `rounded-sm` → `rounded-xs`
- `blur-sm` → `blur-xs`
- `outline-none` → `outline-hidden` (preserves v3's accessibility-friendly
behavior; v4's `outline-none` now means `outline-style: none` only)
CSS property syntax (`flex-grow: 1;`, `outline: none;`, etc.) was
protected with a negative lookahead for `\s*:` so raw CSS is untouched.
Opacity utilities (`bg-opacity-*`, `border-opacity-*`, `ring-opacity-*`,
`divide-opacity-*`) and `ring` → `ring-3` are context-dependent and are
deferred to a follow-up commit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
[3d8e96069e] Bunch of fixes.
[9dadccf323] Migrate studio.
Co-authored-by: Copilot <copilot@github.com>
[9e706b3092] chore(config): bump Tailwind to v4 via @config bridge
- Bump catalog `tailwindcss` from 3.4.1 to 4.2.3 and add
`@tailwindcss/postcss` 4.2.3.
- Swap shared PostCSS config to `@tailwindcss/postcss` and drop
`tailwindcss/nesting` (v4 handles nesting internally via Lightning
CSS).
- Replace `@tailwind base/components/utilities` with
`@import "tailwindcss"` + `@config "../../packages/config/tailwind.config.js"`
in the 10 app-level CSS entry files (studio, www, docs, design-system,
ui-library, learn, lite-studio). Skips `examples/*` which aren't part
of the monorepo build.
- Remove `<alpha-value>` placeholders from
`packages/config/tailwind.config.js` (4 occurrences) and from
`apps/www/tailwind.config.js` (purple-sos color scale, 9 occurrences).
Trade-off: opacity modifiers like `bg-studio/50` no longer work for
these theme colors — they're used with static classes today.
- Remove `@tailwindcss/container-queries` — it's built into v4. Dropped
from `apps/studio`, `apps/design-system`, `apps/docs` package.jsons and
their Tailwind configs.
Custom plugins (`hit-area`, `motion-safe-transition`), `tailwindcss-radix`,
`@mertasan/tailwindcss-variables`, and `tailwindcss-animate` are kept
as-is; the v3-style `plugin()` / `matchUtilities()` / `addVariant()` APIs
still work under v4. Swapping `hit-area` to the v4-native CSS `@utility`
version and replacing `tailwindcss-radix` with native `data-[state=*]:`
variants is deferred to follow-up PRs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
204 lines
7.5 KiB
TypeScript
204 lines
7.5 KiB
TypeScript
import { getCustomContent } from '~/lib/custom-content/getCustomContent'
|
|
import { useIsLoggedIn, useIsUserLoading } from 'common'
|
|
import { AnimatePresence, domAnimation, LazyMotion, m } from 'framer-motion'
|
|
import { X } from 'lucide-react'
|
|
import Image from 'next/image'
|
|
import Link from 'next/link'
|
|
import { usePathname } from 'next/navigation'
|
|
import { Dispatch, Fragment, SetStateAction, useEffect } from 'react'
|
|
import { useKey } from 'react-use'
|
|
import { Accordion, Button, cn } from 'ui'
|
|
import { ThemeToggle } from 'ui-patterns/ThemeToggle'
|
|
|
|
import type { DropdownMenuItem } from '../Navigation.types'
|
|
import { MenuItem, useActiveMenuLabel } from './GlobalNavigationMenu'
|
|
import { GLOBAL_MENU_ITEMS } from './NavigationMenu.constants'
|
|
|
|
const DEFAULT_EASE = [0.24, 0.25, 0.05, 1]
|
|
|
|
const container = {
|
|
hidden: { opacity: 0 },
|
|
show: { opacity: 1, transition: { duration: 0.15, staggerChildren: 0.05, ease: DEFAULT_EASE } },
|
|
exit: { opacity: 0, transition: { duration: 0.15 } },
|
|
}
|
|
|
|
const listItem = {
|
|
hidden: { opacity: 0, y: 10 },
|
|
show: { opacity: 1, y: 0, transition: { duration: 0.25, ease: DEFAULT_EASE } },
|
|
exit: { opacity: 0, transition: { duration: 0.05 } },
|
|
}
|
|
|
|
const itemClassName =
|
|
'block py-2 pl-2 pr-3.5 text-sm text-foreground-light hover:bg-surface-200 focus-visible:ring-2 focus-visible:outline-hidden focus-visible:ring-foreground-lighter focus-visible:rounded-sm'
|
|
|
|
const AccordionMenuItem = ({ section }: { section: DropdownMenuItem[] }) => {
|
|
const activeLabel = useActiveMenuLabel(GLOBAL_MENU_ITEMS)
|
|
|
|
return (
|
|
<m.div
|
|
variants={listItem}
|
|
className="border-b border-muted [&>div]:rounded-none! [&_div[data-state=open]>div]:py-1"
|
|
key={section[0].label}
|
|
>
|
|
{section[0].menuItems ? (
|
|
<Accordion.Item
|
|
header={section[0].label}
|
|
id={section[0].label}
|
|
className={cn(
|
|
'relative',
|
|
activeLabel === section[0].label && 'text-foreground!',
|
|
itemClassName
|
|
)}
|
|
>
|
|
{section[0].menuItems?.map((menuItem, menuItemIndex) => (
|
|
<Fragment key={`desktop-docs-menu-section-${menuItemIndex}`}>
|
|
{menuItem
|
|
.filter((item) => item.enabled !== false)
|
|
.map((item) =>
|
|
!item.href ? (
|
|
<div className="font-mono tracking-wider flex items-center text-foreground-muted text-xs uppercase rounded-md p-2 leading-none">
|
|
{item.label}
|
|
</div>
|
|
) : (
|
|
<MenuItem
|
|
href={item.href}
|
|
title={item.label}
|
|
community={item.community}
|
|
icon={item.icon}
|
|
/>
|
|
)
|
|
)}
|
|
</Fragment>
|
|
))}
|
|
</Accordion.Item>
|
|
) : (
|
|
<Link
|
|
href={section[0].href || '#'}
|
|
className={cn(activeLabel === section[0].label && 'text-foreground!', itemClassName)}
|
|
>
|
|
{section[0].label}
|
|
</Link>
|
|
)}
|
|
</m.div>
|
|
)
|
|
}
|
|
|
|
const Menu = () => (
|
|
<Accordion
|
|
type="default"
|
|
openBehaviour="multiple"
|
|
size="small"
|
|
className="space-y-1 mt-2.5"
|
|
justified
|
|
chevronAlign="right"
|
|
>
|
|
{GLOBAL_MENU_ITEMS.filter((section) => section[0].enabled !== false).map((section) => (
|
|
<AccordionMenuItem section={section} />
|
|
))}
|
|
</Accordion>
|
|
)
|
|
interface Props {
|
|
open: boolean
|
|
setOpen: Dispatch<SetStateAction<boolean>>
|
|
}
|
|
|
|
const GlobalMobileMenu = ({ open, setOpen }: Props) => {
|
|
const isLoggedIn = useIsLoggedIn()
|
|
const isUserLoading = useIsUserLoading()
|
|
const pathname = usePathname()
|
|
|
|
const { navigationLogo } = getCustomContent(['navigation:logo'])
|
|
|
|
// Close mobile menu on route change
|
|
useEffect(() => {
|
|
setOpen(false)
|
|
}, [pathname])
|
|
|
|
useKey('Escape', () => setOpen(false))
|
|
|
|
return (
|
|
<LazyMotion features={domAnimation}>
|
|
<AnimatePresence mode="wait">
|
|
{open && (
|
|
<m.div
|
|
variants={container}
|
|
initial="hidden"
|
|
animate="show"
|
|
exit="exit"
|
|
className="bg-overlay fixed overflow-hidden inset-0 z-50 h-screen max-h-screen w-screen supports-[height:100cqh]:h-[100cqh] supports-[height:100svh]:h-svh transform"
|
|
>
|
|
<div className="absolute px-5 h-(--header-height) flex items-center justify-between w-screen left-0 top-0 z-50 bg-overlay before:content[''] before:absolute before:w-full before:h-3 before:inset-0 before:top-full before:bg-linear-to-b before:from-background-overlay before:to-transparent">
|
|
<Link href="/" className="flex items-center gap-2">
|
|
<Image
|
|
className="cursor-pointer hidden dark:block"
|
|
src={navigationLogo?.dark ?? '/docs/supabase-dark.svg'}
|
|
priority
|
|
width={96}
|
|
height={24}
|
|
alt="Supabase Logo"
|
|
/>
|
|
<Image
|
|
className="cursor-pointer block dark:hidden"
|
|
src={navigationLogo?.light ?? '/docs/supabase-light.svg'}
|
|
priority
|
|
width={96}
|
|
height={24}
|
|
alt="Supabase Logo"
|
|
/>
|
|
<span className="font-mono text-sm font-medium text-brand-link mb-px">DOCS</span>
|
|
</Link>
|
|
<div className="flex gap-4 items-center">
|
|
<ThemeToggle contentClassName="bg-surface-200" />
|
|
<button
|
|
onClick={() => setOpen(false)}
|
|
type="button"
|
|
className="inline-flex items-center justify-center focus:ring-brand bg-surface-100 hover:bg-surface-200 focus:outline-hidden focus:ring-2 focus:ring-inset border border-default bg-surface-100/75 text-foreground-light rounded-sm min-w-[30px] w-[30px] h-[30px]"
|
|
>
|
|
<span className="sr-only">Close menu</span>
|
|
<X />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div className="max-h-screen supports-[height:100cqh]:h-[100cqh] supports-[height:100svh]:h-svh overflow-y-auto pt-12 pb-32 px-3">
|
|
<Menu />
|
|
</div>
|
|
<div className="absolute bottom-0 left-0 right-0 top-auto w-full bg-alternative flex items-stretch p-4 gap-4">
|
|
{!isUserLoading && (
|
|
<>
|
|
{isLoggedIn ? (
|
|
<Button block size="medium" asChild>
|
|
<Link href="https://supabase.com/dashboard/projects">Dashboard</Link>
|
|
</Button>
|
|
) : (
|
|
<>
|
|
<Button block size="medium" type="default" asChild>
|
|
<Link href="https://supabase.com/dashboard/sign-in">Sign in</Link>
|
|
</Button>
|
|
<Button block size="medium" asChild>
|
|
<Link href="https://supabase.com/dashboard/new">Start your project</Link>
|
|
</Button>
|
|
</>
|
|
)}
|
|
</>
|
|
)}
|
|
</div>
|
|
</m.div>
|
|
)}
|
|
</AnimatePresence>
|
|
<AnimatePresence mode="wait">
|
|
{open && (
|
|
<m.div
|
|
variants={container}
|
|
initial="hidden"
|
|
animate="show"
|
|
exit="exit"
|
|
className="bg-alternative fixed overflow-hidden inset-0 z-40 h-screen w-screen transform"
|
|
/>
|
|
)}
|
|
</AnimatePresence>
|
|
</LazyMotion>
|
|
)
|
|
}
|
|
|
|
export default GlobalMobileMenu
|