mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 18:05:11 +03:00
## What kind of change does this PR introduce? Bug fix / design-system alignment for the legacy `Button` from `ui`. ## What is the current behavior? Omitting `variant` on the legacy `Button` falls back to brand-green `primary`. That makes accidental greens easy, and it is hard to spot the real main action on busy pages. ## What is the new behavior? - Legacy `Button` now defaults to neutral `default` - Intentional primary CTAs (create, save, submit, marketing CTAs, and matching `ButtonTooltip` usages) now set `variant="primary"` so their appearance is unchanged - Neutral actions that previously relied on the old fallback (cancel, close, back, dashboard nav, and similar) become grey/white - Design-system docs updated; regression tests cover the new default `Button_Shadcn_` is unchanged. It already uses its own CVA default. This is PR 1 of 2 in a stack. PR 2 drops now-redundant `variant="default"` props. ## To test Studio (http://localhost:8082): - `/sign-in`: Sign in stays green - Open a project → Database → Tables: New table stays green - Auth → Users → Invite: Invite user stays green; Cancel / dismiss controls stay neutral - Project Settings → General: edit a field so Cancel and Save appear. Cancel is neutral, Save is green Design system (http://localhost:3003): - Components → Button: default demo is neutral; primary demo is green; featured preview is the default variant Marketing (optional): - www header: Start your project stays green; logged-in Dashboard is neutral <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Style** - Buttons now default to a neutral style, while primary actions across Studio, documentation, marketing pages, forms, dialogs, and error states use prominent primary styling. - Updated button examples and previews clarify the distinction between default and primary variants. - Event registration now includes a directional arrow icon. - **Tests** - Added coverage confirming default button styling and explicit primary styling behave as expected. - Updated related test fixtures to use primary styling where appropriate. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
131 lines
4.7 KiB
TypeScript
131 lines
4.7 KiB
TypeScript
// End of third-party imports
|
|
|
|
import { useIsLoggedIn, useIsUserLoading, useUser } from 'common'
|
|
import { isFeatureEnabled } from 'common/enabled-features'
|
|
import { DevToolbarTrigger } from 'dev-tools'
|
|
import { Command, Menu, Search } from 'lucide-react'
|
|
import dynamic from 'next/dynamic'
|
|
import Image from 'next/image'
|
|
import Link from 'next/link'
|
|
import type { FC } from 'react'
|
|
import { memo, useState } from 'react'
|
|
import { Button, buttonVariants, cn } from 'ui'
|
|
import { AuthenticatedDropdownMenu } from 'ui-patterns/AuthenticatedDropdownMenu'
|
|
import { CommandMenuTriggerInput } from 'ui-patterns/CommandMenu'
|
|
|
|
import { getCustomContent } from '../../../lib/custom-content/getCustomContent'
|
|
import GlobalNavigationMenu from './GlobalNavigationMenu'
|
|
import useDropdownMenu from './useDropdownMenu'
|
|
|
|
const GlobalMobileMenu = dynamic(() => import('./GlobalMobileMenu'))
|
|
const TopNavDropdown = dynamic(() => import('./TopNavDropdown'))
|
|
|
|
const largeLogo = isFeatureEnabled('branding:large_logo')
|
|
|
|
const TopNavBar: FC = () => {
|
|
const isLoggedIn = useIsLoggedIn()
|
|
const isUserLoading = useIsUserLoading()
|
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
|
const user = useUser()
|
|
const menu = useDropdownMenu(user)
|
|
|
|
return (
|
|
<>
|
|
<nav
|
|
aria-label="top bar"
|
|
className="w-full z-40 flex flex-col subhighlight-border backdrop-blur-sm backdrop-filter bg-default/75"
|
|
>
|
|
<div className="w-full px-5 lg:pl-10 flex justify-between h-(--header-height) gap-3">
|
|
<div className="hidden lg:flex h-full items-center justify-center gap-2">
|
|
<HeaderLogo />
|
|
<GlobalNavigationMenu />
|
|
</div>
|
|
<div className="w-full grow lg:w-auto flex gap-3 justify-between lg:justify-end items-center h-full">
|
|
<div className="lg:hidden">
|
|
<HeaderLogo />
|
|
</div>
|
|
|
|
<div className="flex gap-2 items-center">
|
|
<DevToolbarTrigger />
|
|
<CommandMenuTriggerInput
|
|
className="[&>div>p]:text-foreground-lighter"
|
|
placeholder={
|
|
<>
|
|
Search
|
|
<span className="hidden xl:inline ml-1"> docs...</span>
|
|
</>
|
|
}
|
|
/>
|
|
<button
|
|
tabIndex={0}
|
|
title="Menu dropdown button"
|
|
className={cn(
|
|
buttonVariants({ variant: 'default' }),
|
|
'flex lg:hidden border-default bg-surface-100/75 text-foreground-light rounded-md min-w-[30px] w-[30px] h-[30px] data-open:bg-overlay-hover/30'
|
|
)}
|
|
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
|
>
|
|
<Menu size={18} strokeWidth={1} />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div className="hidden lg:flex items-center justify-end gap-3">
|
|
{!isUserLoading && (
|
|
<Button variant="primary" asChild>
|
|
<a href="/dashboard" className="h-[30px]" target="_blank" rel="noreferrer noopener">
|
|
{isLoggedIn ? 'Dashboard' : 'Sign up'}
|
|
</a>
|
|
</Button>
|
|
)}
|
|
{process.env.NEXT_PUBLIC_DEV_AUTH_PAGE === 'true' && (
|
|
<Button asChild>
|
|
<Link href="/dev-secret-auth">Dev-only secret sign-in</Link>
|
|
</Button>
|
|
)}
|
|
{isLoggedIn ? (
|
|
<AuthenticatedDropdownMenu menu={menu} user={user} site="docs" />
|
|
) : (
|
|
<TopNavDropdown />
|
|
)}
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<GlobalMobileMenu open={mobileMenuOpen} setOpen={setMobileMenuOpen} />
|
|
</>
|
|
)
|
|
}
|
|
|
|
const HeaderLogo = memo(() => {
|
|
const { navigationLogo } = getCustomContent(['navigation:logo'])
|
|
|
|
return (
|
|
<Link href="/" className="flex shrink-0 items-center gap-1.5 w-fit">
|
|
<Image
|
|
className={cn('hidden dark:block m-0!', largeLogo && 'h-[36px]')}
|
|
src={navigationLogo?.dark ?? '/docs/supabase-dark.svg'}
|
|
priority={true}
|
|
loading="eager"
|
|
width={navigationLogo?.width ?? 96}
|
|
height={navigationLogo?.height ?? 18}
|
|
alt="Supabase wordmark"
|
|
/>
|
|
<Image
|
|
className={cn('block dark:hidden m-0!', largeLogo && 'h-[36px]')}
|
|
src={navigationLogo?.light ?? '/docs/supabase-light.svg'}
|
|
priority={true}
|
|
loading="eager"
|
|
width={navigationLogo?.width ?? 96}
|
|
height={navigationLogo?.height ?? 18}
|
|
alt="Supabase wordmark"
|
|
/>
|
|
<span className="font-mono text-sm font-medium text-brand-link mb-px">DOCS</span>
|
|
</Link>
|
|
)
|
|
})
|
|
|
|
HeaderLogo.displayName = 'HeaderLogo'
|
|
|
|
TopNavBar.displayName = 'TopNavBar'
|
|
|
|
export default TopNavBar
|