Skip to content

Commit d66fb51

Browse files
authored
Merge pull request #45 from hasparus/learn--restyled-left-sidebar
learn — restyled left sidebar
2 parents f56c655 + 629037c commit d66fb51

File tree

9 files changed

+910
-12
lines changed

9 files changed

+910
-12
lines changed

.vscode/settings.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,8 @@
1212
"tailwindCSS.classFunctions": ["clsx"],
1313
"editor.quickSuggestions": {
1414
"strings": "on"
15-
}
15+
},
16+
"typescript.preferences.autoImportFileExcludePatterns": [
17+
"**/node_modules/lucide-react"
18+
]
1619
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
"react-use-measure": "^2.1.7",
6868
"rehype-mermaid": "^3.0.0",
6969
"rss": "1.2.2",
70+
"scroll-into-view-if-needed": "^3.1.0",
7071
"server-only": "0.0.1",
7172
"string-similarity": "^4.0.4",
7273
"string-strip-html": "^13.4.8",

patches/nextra-theme-docs.patch

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
diff --git a/dist/index.d.mts b/dist/index.d.mts
2-
index 71f87bcd1dde49d7c19ad49fc098e715a76c5c10..6671e29326be99861058895916185910452ced17 100644
2+
index 71f87bcd1dde49d7c19ad49fc098e715a76c5c10..aadd6228910ee3ebafccfae8672cb9ae1b0bca3c 100644
33
--- a/dist/index.d.mts
44
+++ b/dist/index.d.mts
5-
@@ -1421,3 +1421,19 @@ declare function ThemeSwitch({ lite, className }: ThemeSwitchProps): ReactElemen
5+
@@ -1421,3 +1421,25 @@ declare function ThemeSwitch({ lite, className }: ThemeSwitchProps): ReactElemen
66
declare function Layout({ children, themeConfig, pageOpts }: NextraThemeLayoutProps): ReactElement;
77

88
export { Bleed, Collapse, type PartialDocsThemeConfig as DocsThemeConfig, Link, LocaleSwitch, Navbar, NotFoundPage, SkipNavContent, SkipNavLink, ThemeSwitch, Layout as default, getComponents, useConfig, useMenu, useThemeConfig };
@@ -22,8 +22,14 @@ index 71f87bcd1dde49d7c19ad49fc098e715a76c5c10..6671e29326be99861058895916185910
2222
+export declare const useIntersectionObserver: () => IntersectionObserver | null
2323
+export declare const useSlugs: () => WeakMap<any, any>
2424
+
25+
+export declare const Breadcrumb: (props: { activePath: Item[] }) => ReactElement | null
26+
+export declare const NavLinks: (props: NavLinkProps) => ReactElement | null
27+
+export interface NavLinkProps {
28+
+ currentIndex: number
29+
+ flatDocsDirectories: Item[]
30+
+}
2531
diff --git a/dist/index.js b/dist/index.js
26-
index 56201641fd965dcc5ab7c5df53e444c41293c00e..860b8cfd297e82da041c4d8287ed266691d75a0e 100644
32+
index 56201641fd965dcc5ab7c5df53e444c41293c00e..07147c688ae75c4c7daf082833acc71de16b36ee 100644
2733
--- a/dist/index.js
2834
+++ b/dist/index.js
2935
@@ -100,10 +100,10 @@ IntersectionObserverContext.displayName = "IntersectionObserver";
@@ -41,3 +47,21 @@ index 56201641fd965dcc5ab7c5df53e444c41293c00e..860b8cfd297e82da041c4d8287ed2666
4147
var ActiveAnchorProvider = ({
4248
children
4349
}) => {
50+
@@ -526,7 +526,7 @@ import NextLink2 from "next/link";
51+
import { ArrowRightIcon } from "nextra/icons";
52+
import { Fragment as Fragment3 } from "react";
53+
import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
54+
-function Breadcrumb({
55+
+export function Breadcrumb({
56+
activePath
57+
}) {
58+
return /* @__PURE__ */ jsx9("div", { className: "nextra-breadcrumb _mt-1.5 _flex _items-center _gap-1 _overflow-hidden _text-sm _text-gray-500 dark:_text-gray-400 contrast-more:_text-current", children: activePath.map((item, index, arr) => {
59+
@@ -1255,7 +1255,7 @@ var classes = {
60+
),
61+
icon: cn10("_inline _h-5 _shrink-0")
62+
};
63+
-function NavLinks({
64+
+export function NavLinks({
65+
flatDocsDirectories,
66+
currentIndex
67+
}) {

pnpm-lock.yaml

Lines changed: 6 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/back-to-top.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* @file BackToTop component extracted from Nextra
3+
*/
4+
5+
import { clsx } from "clsx"
6+
import { Button } from "nextra/components"
7+
import { ArrowRightIcon } from "nextra/icons"
8+
import type { ComponentProps, ReactElement, ReactNode } from "react"
9+
10+
const SCROLL_TO_OPTIONS = { top: 0, behavior: "smooth" } as const
11+
12+
const scrollToTop: ComponentProps<"button">["onClick"] = event => {
13+
const buttonElement = event.currentTarget
14+
const tocElement = buttonElement.parentElement!.parentElement!
15+
16+
window.scrollTo(SCROLL_TO_OPTIONS)
17+
tocElement.scrollTo(SCROLL_TO_OPTIONS)
18+
19+
// Fixes https://github.com/facebook/react/issues/20770
20+
// Fixes https://github.com/shuding/nextra/issues/2917
21+
buttonElement.disabled = true
22+
}
23+
24+
export function BackToTop({
25+
children,
26+
className,
27+
hidden,
28+
}: {
29+
children: ReactNode
30+
className?: string
31+
hidden: boolean
32+
}): ReactElement {
33+
return (
34+
<Button
35+
// elements with `aria-hidden: true` must not be focusable or contain focusable elements
36+
aria-hidden={hidden ? "true" : undefined}
37+
onClick={scrollToTop}
38+
disabled={hidden}
39+
className={({ disabled }) =>
40+
clsx(
41+
"flex items-center gap-1.5",
42+
disabled ? "opacity-0" : "opacity-100",
43+
className,
44+
)
45+
}
46+
>
47+
{children}
48+
<ArrowRightIcon
49+
height="16"
50+
className="-rotate-90 rounded-full border border-current"
51+
/>
52+
</Button>
53+
)
54+
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import type { ReactElement, ReactNode } from "react"
2+
import { useMounted } from "nextra/hooks"
3+
import { Heading } from "nextra"
4+
import {
5+
useConfig,
6+
useThemeConfig,
7+
SkipNavContent,
8+
Breadcrumb,
9+
NavLinks,
10+
} from "nextra-theme-docs"
11+
import { clsx } from "clsx"
12+
13+
import { Sidebar } from "./sidebar"
14+
import { renderComponent } from "./utils"
15+
import { TableOfContents } from "./table-of-contents"
16+
17+
const classes = {
18+
toc: clsx("nextra-toc order-last max-xl:hidden w-64 shrink-0 print:hidden"),
19+
main: clsx("w-full break-words"),
20+
}
21+
22+
export interface NextraMdxWrapperProps {
23+
toc?: Heading[]
24+
children?: React.ReactNode
25+
}
26+
27+
export function NextraMdxWrapper({
28+
toc = [],
29+
children,
30+
}: NextraMdxWrapperProps) {
31+
const config = useConfig()
32+
const {
33+
activeType,
34+
activeThemeContext: themeContext,
35+
docsDirectories,
36+
directories,
37+
} = config.normalizePagesResult
38+
39+
const tocEl =
40+
activeType === "page" ||
41+
!themeContext.toc ||
42+
themeContext.layout !== "default" ? (
43+
themeContext.layout !== "full" &&
44+
themeContext.layout !== "raw" && (
45+
<nav className={classes.toc} aria-label="table of contents" />
46+
)
47+
) : (
48+
<nav className={classes.toc} aria-label="table of contents">
49+
<TableOfContents toc={toc} filePath={config.filePath} />
50+
</nav>
51+
)
52+
return (
53+
<div
54+
className={clsx(
55+
"mx-auto flex",
56+
themeContext.layout !== "raw" && "max-w-[90rem]",
57+
)}
58+
>
59+
<Sidebar
60+
docsDirectories={docsDirectories}
61+
fullDirectories={directories}
62+
toc={toc}
63+
asPopover={config.hideSidebar}
64+
includePlaceholder={themeContext.layout === "default"}
65+
/>
66+
{tocEl}
67+
<SkipNavContent />
68+
<Body>{children}</Body>
69+
</div>
70+
)
71+
}
72+
73+
function Body({ children }: { children: ReactNode }): ReactElement {
74+
const config = useConfig()
75+
const themeConfig = useThemeConfig()
76+
const mounted = useMounted()
77+
const {
78+
activeThemeContext: themeContext,
79+
activeType,
80+
activeIndex,
81+
flatDocsDirectories,
82+
activePath,
83+
} = config.normalizePagesResult
84+
85+
if (themeContext.layout === "raw") {
86+
return <div className={classes.main}>{children}</div>
87+
}
88+
89+
const date =
90+
themeContext.timestamp && themeConfig.gitTimestamp && config.timestamp
91+
? new Date(config.timestamp)
92+
: null
93+
94+
const gitTimestampEl =
95+
// Because a user's time zone may be different from the server page
96+
mounted && date ? (
97+
<div className="mb-8 mt-12 block text-xs text-neu-500 ltr:text-right rtl:text-left">
98+
{renderComponent(themeConfig.gitTimestamp, { timestamp: date })}
99+
</div>
100+
) : (
101+
<div className="mt-16" />
102+
)
103+
104+
const content = (
105+
<>
106+
{renderComponent(themeContext.topContent)}
107+
{children}
108+
{gitTimestampEl}
109+
{renderComponent(themeContext.bottomContent)}
110+
{activeType !== "page" && themeContext.pagination && (
111+
<NavLinks
112+
flatDocsDirectories={flatDocsDirectories}
113+
currentIndex={activeIndex}
114+
/>
115+
)}
116+
</>
117+
)
118+
119+
const body = themeConfig.main ? (
120+
<themeConfig.main>{content}</themeConfig.main>
121+
) : (
122+
content
123+
)
124+
125+
if (themeContext.layout === "full") {
126+
return (
127+
<article
128+
className={clsx(
129+
classes.main,
130+
"nextra-content min-h-[calc(100vh-var(--nextra-navbar-height))] pl-[max(env(safe-area-inset-left),1.5rem)] pr-[max(env(safe-area-inset-right),1.5rem)]",
131+
)}
132+
>
133+
{body}
134+
</article>
135+
)
136+
}
137+
138+
return (
139+
<article
140+
className={clsx(
141+
classes.main,
142+
"nextra-content flex min-h-[calc(100vh-var(--nextra-navbar-height))] min-w-0 justify-center pb-8 pr-[calc(env(safe-area-inset-right)-1.5rem)]",
143+
themeContext.typesetting === "article" &&
144+
"nextra-body-typesetting-article",
145+
)}
146+
>
147+
<main className="w-full min-w-0 max-w-6xl px-6 pt-4 md:px-12">
148+
{activeType !== "page" && themeContext.breadcrumb && (
149+
<Breadcrumb activePath={activePath} />
150+
)}
151+
{body}
152+
</main>
153+
</article>
154+
)
155+
}

0 commit comments

Comments
 (0)