mirror of
https://github.com/supabase/supabase.git
synced 2026-06-21 07:46:01 +08:00
## What kind of change does this PR introduce? UI polish. Updates sidebar and submenu navigation hover and active styling. ## What is the current behavior? Product submenu navigation items either lack a hover fill or use a hover fill that visually matches the active state. Adjacent hovered and selected rows can appear to touch. ## What is the new behavior? Primary sidebar buttons, sidebar sub-buttons, and product submenu pills now share a muted hover fill while preserving the full accent fill for active/selected states. Product submenu rows also get a small visual gap with slightly reduced vertical padding to keep the overall spacing compact. | After | | --- | | <img width="988" height="408" alt="CleanShot 2026-05-05 at 11 53 05@2x" src="https://github.com/user-attachments/assets/560ac8a5-1262-41af-a196-618c86580150" /> | <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Style** * Refined sidebar hover/active states with subtle accent alpha colors for a more polished visual experience. * Updated sidebar menu spacing and rounded corners for improved touch and visual clarity. * **UI Improvements** * Sidebar now only displays when sections exist and uses a streamlined submenu flow for more consistent, predictable navigation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
88 lines
2.5 KiB
TypeScript
88 lines
2.5 KiB
TypeScript
import { ArrowLeft } from 'lucide-react'
|
|
import Link from 'next/link'
|
|
import { PropsWithChildren, ReactNode } from 'react'
|
|
import { cn } from 'ui'
|
|
|
|
import type { SidebarSection } from './AccountLayout.types'
|
|
import { getActiveKey, toSubMenuSections } from './AccountLayout.utils'
|
|
import { SubMenu } from '@/components/ui/ProductMenu/SubMenu'
|
|
|
|
interface WithSidebarProps {
|
|
title?: string
|
|
sections: SidebarSection[]
|
|
header?: ReactNode
|
|
backToDashboardURL?: string
|
|
}
|
|
|
|
export const WithSidebar = ({
|
|
title,
|
|
header,
|
|
children,
|
|
sections,
|
|
backToDashboardURL,
|
|
}: PropsWithChildren<WithSidebarProps>) => {
|
|
const noContent = !sections
|
|
|
|
return (
|
|
<div className="flex flex-col md:flex-row h-full">
|
|
{!noContent && (
|
|
<SidebarContent
|
|
title={title}
|
|
header={header}
|
|
sections={sections}
|
|
backToDashboardURL={backToDashboardURL}
|
|
className="hidden md:flex"
|
|
/>
|
|
)}
|
|
<div className="flex flex-1 flex-col">
|
|
<div className="flex-1 grow overflow-y-auto">{children}</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export const SidebarContent = ({
|
|
header,
|
|
sections,
|
|
backToDashboardURL,
|
|
className,
|
|
}: PropsWithChildren<Omit<WithSidebarProps, 'breadcrumbs'>> & { className?: string }) => {
|
|
const page = getActiveKey(sections)
|
|
const subMenuSections = toSubMenuSections(sections)
|
|
|
|
return (
|
|
<>
|
|
<div
|
|
id="with-sidebar"
|
|
className={cn(
|
|
'h-full bg-dash-sidebar flex flex-col justify-between',
|
|
'hide-scrollbar w-full md:w-64 md:border-r border-default',
|
|
className
|
|
)}
|
|
>
|
|
<div className="flex-1 flex flex-col">
|
|
{backToDashboardURL && (
|
|
<div className="shrink-0 hidden md:block">
|
|
<div className="flex h-12 max-h-12 items-center border-b px-6 border-default">
|
|
<Link
|
|
href={backToDashboardURL}
|
|
className="flex text-sm flex-row gap-2 items-center text-foreground-lighter focus-visible:text-foreground hover:text-foreground"
|
|
>
|
|
<ArrowLeft strokeWidth={1.5} size={16} />
|
|
Back to dashboard
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
)}
|
|
{header && header}
|
|
<div className="flex-1 overflow-auto">
|
|
<div className="flex flex-col">
|
|
<SubMenu sections={subMenuSections} page={page} />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|