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.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 (