mirror of
https://github.com/supabase/supabase.git
synced 2026-10-07 18:35:07 +03:00
## What kind of change does this PR introduce? bug fix to stop sidebar jump on scroll within docs ## What is the current behavior? the docs sidebar shifts up by 1px as soon as scrolling start as the top bar height include bottom border causing the jump as height token differ from the whole height ## What is the new behavior? favor box shadow instead of a border for the bottom line, so height matches the token and nothing needs to compensate any more which allows to remove some `+1px` elsewhere + also drops a nested `lg:sticky` in the sidebar that did nothing inside an already-sticky parent | state | preview | | -------|------| | before | <video src="https://github.com/user-attachments/assets/b4bbfa2d-6595-4711-bb2b-bd2bf3aded8a" /> | | after | <video src="https://github.com/user-attachments/assets/f044aebc-ef14-42c1-8564-3b290399d00b" /> | ## Additional context - header now uses the existing `subhighlight-border` utility, which was not used anywhere else it seems, could also be renamed? - could be down the other way by keeping border and fixing the jump <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved documentation navigation alignment by removing unnecessary spacing from sticky sidebars, table of contents, and section headings. * Updated desktop navigation behavior for more consistent scrolling and viewport layout. * Refined the top navigation bar’s border styling for a cleaner appearance. <!-- 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 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
|