mirror of
https://github.com/supabase/supabase.git
synced 2026-05-20 20:41:03 +08:00
* refactor(docs): enhance NavigationMenuGuideListItems component * cleanup.. * Resolve formatting conflicts in NavigationMenuGuideListItems * Came up with a crazy recursive approach... * some changes. * More cleanups... * more cleanups.... * formatting the stuff * refactor(navigation): remove sample menu data and optimize icon rendering in RecursiveNavigation * cleanup... * feat: enhance navigation with recursive dropdown indicators and performance optimizations - Add visual chevron indicators for expandable sidebar items - Implement recursive navigation system using existing NavMenuSection types - Auto-expand accordion sections containing current active page on load/refresh - Extract LinkContainer as independent component to prevent recreation on renders - Fix React 19 compatibility issues with ref handling using useCallback pattern - Resolve duplicate key warnings with improved key generation strategy - Optimize accordion transition timing (500ms duration with ease-in-out) to prevent element overlap - Preserve existing icon logic with hasLightIcon support for theme variants - Maintain backward compatibility with existing navigation data structures Performance improvements: - Memoized recursive components to prevent unnecessary re-renders - Stable component references for better React reconciliation - Proper TypeScript interfaces with explicit prop definitions UX improvements: - Smooth accordion animations with physics-based easing - Clear visual indicators for expandable menu items - Automatic expansion of sections containing current page - Professional-grade transition animations Technical details: - Uses existing NavMenuSection recursive type structure - Implements containsActivePath helper for active page detection - Leverages Radix UI accordion with proper data-state attributes - Maintains all existing functionality including dynamic menu injection * Cleanup... * feat: implement cookie-based persisted state for navigation accordion - Replace localStorage with cookie-based persistence for SSR compatibility - Add proper cookie helpers with SameSite=Lax and 30-day expiration - Implement initialization state to prevent hydration mismatches - Maintain auto-expand functionality for active page sections - Preserve user's manual accordion state across page refreshes and sessions - Add debounced cookie updates (300ms) for performance optimization - Use proper cookie naming convention: 'supabase-docs-nav-state' Benefits: - SSR compatible: Works with server-side rendering - Cross-session persistence: Maintains state across browser sessions - Better security: Cookies are more secure than localStorage - Performance: Debounced updates prevent excessive cookie writes - User experience: Seamless navigation state preservation * refactor: implement individual item-based persistence following reference pattern - Replace global state management with individual item persistence - Use sessionStorage with 'nav-expansion-' prefix for each item - Follow the exact pattern from reference: usePersistedExpansionState hook - Maintain auto-expansion for active page sections - Simplify state management by removing complex global state - Each accordion item manages its own expansion state independently - Preserve user's manual toggle state across page refreshes - Use sessionStorage instead of cookies for better performance Benefits: - Cleaner architecture: Each item manages its own state - Better performance: No global state updates - Simpler logic: Direct item-to-storage mapping - Reference pattern compliance: Follows established patterns - Individual control: Each section can be toggled independently - Session persistence: Maintains state during browser session * refactor: implement URL-driven navigation state following Supabase docs pattern - Replace sessionStorage persistence with URL-driven expansion state - Follow the established Supabase docs pattern: URL as single source of truth - Remove individual item persistence hooks in favor of pathname-based logic - Implement useUrlDrivenExpansion hook that determines open sections from current URL - Use getSectionsContainingPath to find all sections that should be expanded - Remove manual toggle functionality - sections open/close based on URL navigation - Maintain smooth transitions and visual indicators for expandable sections - Ensure consistency and reliability by using URL as the definitive state source Benefits: - Reliability: URL is always the single source of truth - Consistency: Matches existing Supabase docs navigation behavior - Simplicity: No complex state management or storage concerns - Performance: No localStorage/sessionStorage operations - SSR Compatible: Works perfectly with server-side rendering - Predictable: Navigation state is always consistent with current page * persistant state. * file delete * cleanup.. * file cleanup * cleanup... * cleanup.. * formatting.. * aww shit that it. --------- Co-authored-by: Alan Daniel <stylesshjs@gmail.com>
105 lines
3.2 KiB
TypeScript
105 lines
3.2 KiB
TypeScript
'use client'
|
|
|
|
import * as Accordion from '@radix-ui/react-accordion'
|
|
|
|
import { type NavMenuSection } from '../Navigation.types'
|
|
import * as NavItems from './NavigationMenu.constants'
|
|
import NavigationMenuGuideListItems from './NavigationMenuGuideListItems'
|
|
import { usePathname } from 'next/navigation'
|
|
import { PropsWithChildren } from 'react'
|
|
import { MenuId } from './NavigationMenu'
|
|
|
|
const NavigationMenuGuideList = ({
|
|
id,
|
|
additionalNavItems,
|
|
}: {
|
|
id: string
|
|
additionalNavItems?: Record<string, Partial<NavMenuSection>[]>
|
|
}) => {
|
|
const pathname = usePathname()
|
|
const firstLevelRoute = pathname?.split('/')?.slice(0, 4)?.join('/')
|
|
|
|
// eslint-disable-next-line import/namespace -- dynamic access, can't lint properly
|
|
let menu = NavItems[id]
|
|
|
|
if (id === MenuId.Integrations && additionalNavItems?.integrations) {
|
|
const integrationsListIndex = menu.items.findIndex((item) => item.name === 'Integrations')
|
|
if (integrationsListIndex !== -1) {
|
|
menu = {
|
|
...menu,
|
|
items: [
|
|
...menu.items.slice(0, integrationsListIndex),
|
|
{
|
|
...menu.items[integrationsListIndex],
|
|
items: [...menu.items[integrationsListIndex].items, ...additionalNavItems.integrations],
|
|
},
|
|
...menu.items.slice(integrationsListIndex + 1),
|
|
],
|
|
}
|
|
}
|
|
}
|
|
|
|
// Inject federated prompts into the 'AI Tools > Prompts' section
|
|
if (id === MenuId.GettingStarted && additionalNavItems?.prompts) {
|
|
const aiToolsSectionIndex = menu.items.findIndex((item) => item.name === 'AI Tools')
|
|
if (aiToolsSectionIndex !== -1) {
|
|
const beforeAITools = menu.items.slice(0, aiToolsSectionIndex)
|
|
const afterAITools = menu.items.slice(aiToolsSectionIndex + 1)
|
|
|
|
const aiToolsSection = menu.items[aiToolsSectionIndex]
|
|
const promptsSectionIndex = aiToolsSection.items.findIndex((item) => item.name === 'Prompts')
|
|
|
|
if (promptsSectionIndex !== -1) {
|
|
const beforePrompts = aiToolsSection.items.slice(0, promptsSectionIndex)
|
|
const afterPrompts = aiToolsSection.items.slice(promptsSectionIndex + 1)
|
|
|
|
const promptsSection = aiToolsSection.items[promptsSectionIndex]
|
|
|
|
const modifiedPromptsSection = {
|
|
...promptsSection,
|
|
items: additionalNavItems.prompts,
|
|
}
|
|
|
|
const modifiedAIToolsSection = {
|
|
...aiToolsSection,
|
|
items: [...beforePrompts, modifiedPromptsSection, ...afterPrompts],
|
|
}
|
|
|
|
menu = {
|
|
...menu,
|
|
items: [...beforeAITools, modifiedAIToolsSection, ...afterAITools],
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (
|
|
<NavigationMenuGuideListWrapper id={id} firstLevelRoute={firstLevelRoute}>
|
|
<NavigationMenuGuideListItems menu={menu} id={id} />
|
|
</NavigationMenuGuideListWrapper>
|
|
)
|
|
}
|
|
|
|
export function NavigationMenuGuideListWrapper({
|
|
id,
|
|
firstLevelRoute,
|
|
children,
|
|
}: PropsWithChildren<{
|
|
id: string
|
|
firstLevelRoute?: string
|
|
}>) {
|
|
return (
|
|
<Accordion.Root
|
|
collapsible={true}
|
|
key={id}
|
|
type="single"
|
|
value={firstLevelRoute}
|
|
className="transition-all duration-150 ease-out opacity-100 ml-0 delay-150 w-full"
|
|
>
|
|
{children}
|
|
</Accordion.Root>
|
|
)
|
|
}
|
|
|
|
export default NavigationMenuGuideList
|