diff --git a/apps/ui-library/app/(app)/docs/[[...slug]]/page.tsx b/apps/ui-library/app/(app)/docs/[[...slug]]/page.tsx index ea7d13022fe..4c67b9f26ef 100644 --- a/apps/ui-library/app/(app)/docs/[[...slug]]/page.tsx +++ b/apps/ui-library/app/(app)/docs/[[...slug]]/page.tsx @@ -1,3 +1,4 @@ +import { FrameworkSelector } from '@/components/framework-selector' import { Mdx } from '@/components/mdx-components' import { SourcePanel } from '@/components/source-panel' import { DashboardTableOfContents } from '@/components/toc' @@ -87,13 +88,16 @@ export default async function DocPage({ params }: DocPageProps) {
{doc.title}
-
-

{doc.title}

- {doc.description && ( -

- {doc.description} -

- )} +
+
+

{doc.title}

+ {doc.description && ( +

+ {doc.description} +

+ )} +
+
diff --git a/apps/ui-library/app/Providers.tsx b/apps/ui-library/app/Providers.tsx index 87bac1f1e2f..ef236a75fcc 100644 --- a/apps/ui-library/app/Providers.tsx +++ b/apps/ui-library/app/Providers.tsx @@ -5,12 +5,15 @@ import { ThemeProvider as NextThemesProvider } from 'next-themes' import { ThemeProviderProps } from 'next-themes/dist/types' import { TooltipProvider } from 'ui' +import { FrameworkProvider } from '@/context/framework-context' export function ThemeProvider({ children, ...props }: ThemeProviderProps) { return ( - {children} + + {children} + ) diff --git a/apps/ui-library/components/framework-selector.tsx b/apps/ui-library/components/framework-selector.tsx new file mode 100644 index 00000000000..17686b9958a --- /dev/null +++ b/apps/ui-library/components/framework-selector.tsx @@ -0,0 +1,78 @@ +'use client' + +import { usePathname, useRouter } from 'next/navigation' + +import { componentPages, frameworkTitles } from '@/config/docs' +import { useFramework } from '@/context/framework-context' +import { SelectValue } from '@ui/components/shadcn/ui/select' +import { + Select_Shadcn_, + SelectContent_Shadcn_, + SelectGroup_Shadcn_, + SelectItem_Shadcn_, + SelectTrigger_Shadcn_, +} from 'ui' + +const frameworks = Object.keys(frameworkTitles) + +export function FrameworkSelector() { + const pathname = usePathname() + + // Extract framework and docTitle from pathname + // Example: /ui/docs/nextjs/password-based-auth + const pathParts = pathname.split('/') + const docTitle = pathParts[pathParts.length - 1] + const framework = pathParts[pathParts.length - 2] + + const router = useRouter() + const { setFramework: setPreferredFramework } = useFramework() + const selectedFramework = frameworks.includes(framework) ? framework : 'nextjs' + + if (!framework) { + return null + } + + // Get the supported frameworks for this component + const supportedFrameworks = componentPages[docTitle]?.supportedFrameworks || [] + + // Don't show selector if component only supports one framework + if (supportedFrameworks.length <= 1) { + return null + } + + const onSelect = (value: string) => { + // Get current path parts + const currentPathParts = [...pathParts] + // Replace the framework part (second to last) with the new framework + currentPathParts[currentPathParts.length - 2] = value + // Build the new path + const newPath = currentPathParts.join('/') + + router.push(newPath) + + // Also update the context/localStorage for future use + setPreferredFramework(value as keyof typeof frameworkTitles) + } + + const options = supportedFrameworks.map((f) => ({ + label: frameworkTitles[f], + value: f, + })) + + return ( + + + + + + + {options.map((f) => ( + + {f.label} + + ))} + + + + ) +} diff --git a/apps/ui-library/components/side-navigation-item.tsx b/apps/ui-library/components/side-navigation-item.tsx index 00673321624..691de3058c4 100644 --- a/apps/ui-library/components/side-navigation-item.tsx +++ b/apps/ui-library/components/side-navigation-item.tsx @@ -8,12 +8,27 @@ import React from 'react' const NavigationItem: React.FC<{ item: SidebarNavItem }> = React.memo(({ item }) => { const pathname = usePathname() + const pathParts = pathname.split('/') + const slug = pathParts[pathParts.length - 1] + const framework = pathParts[pathParts.length - 2] - const isActive = pathname === item.href + // Build URL with framework param if provided + let href = item.href + + // Handle component items with slug and framework + if (!href && slug) { + if (framework) { + href = `/docs/${framework}/${slug}` + } else { + href = `/docs/${slug}` + } + } + + const isActive = pathname === href return ( = React.memo(({ item }) className={cn( 'transition', 'absolute left-0 w-1 h-full bg-foreground', - isActive ? 'opacity-100' : 'opacity-0' )} >
diff --git a/apps/ui-library/components/side-navigation.tsx b/apps/ui-library/components/side-navigation.tsx index 395638afe62..5753d7a4a63 100644 --- a/apps/ui-library/components/side-navigation.tsx +++ b/apps/ui-library/components/side-navigation.tsx @@ -1,38 +1,36 @@ 'use client' import NavigationItem from '@/components/side-navigation-item' -import { aiEditorsRules, frameworkPages, gettingStarted } from '@/config/docs' -import { SelectValue } from '@ui/components/shadcn/ui/select' -import { usePathname, useRouter } from 'next/navigation' -import { - Select_Shadcn_, - SelectContent_Shadcn_, - SelectGroup_Shadcn_, - SelectItem_Shadcn_, - SelectTrigger_Shadcn_, -} from 'ui' - -const frameworks = Object.keys(frameworkPages) +import { aiEditorsRules, componentPages, gettingStarted } from '@/config/docs' +import { useFramework } from '@/context/framework-context' function SideNavigation() { - const router = useRouter() - const pathname = usePathname() + const { framework: preferredFramework } = useFramework() - const pathRegex = /\/docs\/([^/]+)/ - const match = pathname?.match(pathRegex) - const selectedFramework = frameworks.includes(match?.[1] ?? '') ? match?.[1]! : 'nextjs' - - const onSelect = (value: string) => { - const firstUrl = frameworkPages[value].items[0].href - router.push(firstUrl as string) + // Create a function to build URLs + const buildUrl = (slug: string, framework?: string) => { + if (!framework) return `/docs/${slug}` + return `/docs/${framework}/${slug}` } - const options = frameworks.map((f) => ({ - label: frameworkPages[f].title, - value: f, - })) + // Get all component pages + const componentItems = Object.entries(componentPages).map(([slug, component]) => { + let frameworkToUse = undefined - const selectedFrameworkConfig = frameworkPages[selectedFramework] + // Add framework param only if needed + if (preferredFramework && component.supportedFrameworks.includes(preferredFramework)) { + frameworkToUse = preferredFramework + } else if (component.supportedFrameworks.length > 0) { + frameworkToUse = component.supportedFrameworks[0] + } + + return { + title: component.title, + href: buildUrl(slug, frameworkToUse), + items: [], + commandItemLabel: component.commandItemLabel, + } + }) return (