-
Notifications
You must be signed in to change notification settings - Fork 0
feat: default theme layout with tab bar + page nav types #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b995510
2fe9b61
70e9404
fcbe6c0
ff911ef
bd031a8
6cd486f
29fa42d
b634599
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,35 @@ | ||
| 'use client' | ||
|
|
||
| import { ThemeSwitcher } from '@raystack/apsara' | ||
| import { useState, useEffect } from 'react' | ||
| import { MoonIcon, SunIcon } from '@heroicons/react/24/outline' | ||
| import { IconButton, useTheme } from '@raystack/apsara' | ||
| import { useEffect, useState } from 'react' | ||
|
|
||
| interface ClientThemeSwitcherProps { | ||
| size?: number | ||
| } | ||
|
|
||
| export function ClientThemeSwitcher({ size }: ClientThemeSwitcherProps) { | ||
| export function ClientThemeSwitcher({ size = 16 }: ClientThemeSwitcherProps) { | ||
| const [isClient, setIsClient] = useState(false) | ||
| const { resolvedTheme, setTheme } = useTheme() | ||
|
|
||
| useEffect(() => { | ||
| setIsClient(true) | ||
| }, []) | ||
|
|
||
| return isClient ? <ThemeSwitcher size={size} /> : null | ||
| if (!isClient) return null | ||
|
|
||
| const isDark = resolvedTheme === 'dark' | ||
| return ( | ||
| <IconButton | ||
| size={3} | ||
| aria-label={isDark ? 'Switch to light theme' : 'Switch to dark theme'} | ||
| onClick={() => setTheme(isDark ? 'light' : 'dark')} | ||
| > | ||
| {isDark ? ( | ||
| <SunIcon width={size} height={size} /> | ||
| ) : ( | ||
| <MoonIcon width={size} height={size} /> | ||
| )} | ||
| </IconButton> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,8 +1,9 @@ | ||||||||||||||||||
| import { loader } from 'fumadocs-core/source'; | ||||||||||||||||||
| import { flattenTree } from 'fumadocs-core/page-tree'; | ||||||||||||||||||
| import type { Root, Node, Folder } from 'fumadocs-core/page-tree'; | ||||||||||||||||||
| import type { MDXContent } from 'mdx/types'; | ||||||||||||||||||
| import type { TableOfContents } from 'fumadocs-core/toc'; | ||||||||||||||||||
| import type { Frontmatter } from '@/types'; | ||||||||||||||||||
| import type { Frontmatter, PageNav, PageNavLink } from '@/types'; | ||||||||||||||||||
|
|
||||||||||||||||||
| const CONTENT_PREFIX = '../../.content/'; | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
@@ -105,6 +106,22 @@ export async function getPage(slugs?: string[]) { | |||||||||||||||||
| return s.getPage(slugs); | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| export async function getPageNav(slug: string[]): Promise<PageNav> { | ||||||||||||||||||
| const tree = await getPageTree(); | ||||||||||||||||||
| const pages = flattenTree(tree.children); | ||||||||||||||||||
| const url = slug.length === 0 ? '/' : `/${slug.join('/')}`; | ||||||||||||||||||
| const i = pages.findIndex(p => p.url === url); | ||||||||||||||||||
| if (i < 0) return { prev: null, next: null }; | ||||||||||||||||||
| const toLink = (p: (typeof pages)[number]): PageNavLink => ({ | ||||||||||||||||||
| url: p.url, | ||||||||||||||||||
| title: typeof p.name === 'string' ? p.name : '' | ||||||||||||||||||
| }); | ||||||||||||||||||
|
Comment on lines
+115
to
+118
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Confirm the shape of items returned by fumadocs-core/page-tree flattenTree in v16.6.15.
fd -t f 'package.json' node_modules/fumadocs-core 2>/dev/null | head -n 2
rg -nP --type=ts -C2 'export\s+(declare\s+)?(function|const)\s+flattenTree' node_modules/fumadocs-core 2>/dev/null
rg -nP --type=ts -C3 'name\s*:' node_modules/fumadocs-core/dist/page-tree 2>/dev/null | head -n 40Repository: raystack/chronicle Length of output: 44 🏁 Script executed: # First, let's look at the actual source.ts file around lines 115-118
cat -n packages/chronicle/src/lib/source.ts | sed -n '100,130p'Repository: raystack/chronicle Length of output: 1318 🏁 Script executed: # Check the package.json for fumadocs-core dependency
cat packages/chronicle/package.json | jq '.dependencies, .devDependencies' 2>/dev/null || cat packages/chronicle/package.json | grep -A 20 '"dependencies"'Repository: raystack/chronicle Length of output: 1633 🏁 Script executed: # Look for type definitions and imports related to PageNavLink, PageTree
rg -n 'PageNavLink|PageTree' packages/chronicle/src/lib/source.ts -B 3 -A 3Repository: raystack/chronicle Length of output: 1076 🏁 Script executed: # Check for fumadocs-core imports and usage
rg -n 'from.*fumadocs-core' packages/chronicle/src/lib/source.tsRepository: raystack/chronicle Length of output: 296 🏁 Script executed: # Find and read the types file
find packages/chronicle/src -name 'types.ts' -o -name 'types.d.ts' -o -name 'index.d.ts' | head -5Repository: raystack/chronicle Length of output: 44 🏁 Script executed: # Check the types directory or types file
cat packages/chronicle/src/types.ts 2>/dev/null || cat packages/chronicle/src/types/index.ts 2>/dev/null || find packages/chronicle/src -type f -name '*.ts' | xargs grep -l 'PageNavLink\|PageNav' | head -3Repository: raystack/chronicle Length of output: 136 🏁 Script executed: # Search for PageNavLink definition
rg -n 'PageNavLink' packages/chronicle/src -B 2 -A 2Repository: raystack/chronicle Length of output: 2457 🏁 Script executed: # Search for PageNav definition as well
rg -n 'interface PageNav|type PageNav' packages/chronicle/src -B 2 -A 5Repository: raystack/chronicle Length of output: 811 🏁 Script executed: # List the types directory structure
ls -la packages/chronicle/src/types/Repository: raystack/chronicle Length of output: 470 🏁 Script executed: # Check what Node type looks like when imported from fumadocs-core
rg -n 'Root|Node|Folder' packages/chronicle/src/lib/source.ts -A 3 | head -30Repository: raystack/chronicle Length of output: 1293 🏁 Script executed: # Search for any usage of page.name or how Node type items are accessed
rg -n '\.name' packages/chronicle/src/lib/source.ts -B 2 -A 2Repository: raystack/chronicle Length of output: 210 🏁 Script executed: # Let's check the fumadocs-core documentation or type stubs in the project
find packages/chronicle -name '*.d.ts' -o -name '*.ts' | xargs grep -l 'fumadocs' | xargs grep -l 'name.*ReactNode\|ReactNode.*name' 2>/dev/null | head -5Repository: raystack/chronicle Length of output: 44 🏁 Script executed: # Look for any comments or usage patterns around page names
rg -n 'p\.name|pages\[.*\]\.name' packages/chronicle/src -B 3 -A 3Repository: raystack/chronicle Length of output: 1804 🌐 Web query:
💡 Result: In fumadocs-core version 16.6.15, the PageTree.Item interface defines the "name" property as type ReactNode (import { ReactNode } from 'react'). This represents the display name of the page/navigation item, which can be a string, JSX element, or other React renderable content for flexible rendering in UI components like sidebars. The full Item interface is: interface Item { $id?: string; $ref?: { file: string }; type: 'page'; name: ReactNode; url: string; external?: boolean; description?: ReactNode; icon?: ReactNode; } This structure is consistent across fumadocs-core v16.x releases, including 16.6.15, as shown in official documentation and API references. PageTree nodes (Root, Folder, Separator) also use ReactNode for name and similar properties to support rich content. Citations:
🌐 Web query:
💡 Result: The flattenTree function from fumadocs-core/page-tree flattens a page tree into an array of page nodes. Its signature is function flattenTree(nodes: Node[]): Item[]. The return type is Item[], where Item is the interface for page nodes with fields like $id?: string, $ref?: { file: string }, type: 'page', name: ReactNode, url: string, external?: boolean, description?: ReactNode, and icon?: ReactNode. The name field in Item is of type ReactNode and represents the display name of the page. Citations:
In fumadocs-core 16.6.15, The Prefer deriving the title from the page's frontmatter title (matching what 🛠 Proposed fix- const toLink = (p: (typeof pages)[number]): PageNavLink => ({
- url: p.url,
- title: String(p.name ?? '')
- });
+ const toLink = (p: (typeof pages)[number]): PageNavLink => ({
+ url: p.url,
+ title: typeof p.name === 'string' ? p.name : (p.name == null ? '' : String(p.name))
+ });Or, for full fidelity, resolve the title from 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| return { | ||||||||||||||||||
| prev: i > 0 ? toLink(pages[i - 1]) : null, | ||||||||||||||||||
| next: i < pages.length - 1 ? toLink(pages[i + 1]) : null | ||||||||||||||||||
| }; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| export function extractFrontmatter(page: { data: unknown }, fallbackTitle?: string): Frontmatter { | ||||||||||||||||||
| const d = page.data as Record<string, unknown>; | ||||||||||||||||||
| return { | ||||||||||||||||||
|
|
||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.