UI: Hide TOC Popover on full mode

This commit is contained in:
fuma-nama
2024-08-11 23:09:22 +08:00
parent ec983a323f
commit 96c9ddac06
12 changed files with 58 additions and 37 deletions
+7
View File
@@ -0,0 +1,7 @@
---
'fumadocs-openapi': patch
'fumadocs-core': patch
'fumadocs-ui': patch
---
Change Heading scroll margins
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-ui': patch
---
Hide TOC Popover on full mode
@@ -76,7 +76,7 @@ Use the official Tailwind CSS plugin.
### Layout
Create a new catch-all route `/app/docs/[[..slugs]]` for our docs, and give it a proper layout.
Create a folder `/app/docs` for our docs, and give it a proper layout.
```tsx title="app/docs/layout.tsx"
import { DocsLayout } from 'fumadocs-ui/layout';
@@ -96,9 +96,10 @@ export default function RootDocsLayout({ children }: { children: ReactNode }) {
### Page
For the `page.tsx`, it may vary depending on your source. You should configure static rendering with `generateStaticParams` and metadata with `generateMetadata`.
Create a catch-all route `/app/docs/[[...slug]]` for docs pages.
Wrap your content in the [Page](/docs/ui/blocks/page) component.
In the page, wrap your content in the [Page](/docs/ui/blocks/page) component.
It may vary depending on your content source. You should configure static rendering with `generateStaticParams` and metadata with `generateMetadata`.
<Tabs groupId='content-source' items={['Fumadocs MDX', 'Content Collections']}>
@@ -25,7 +25,7 @@ export function useAnchorObserver(watch: string[]): string | undefined {
return f ?? watch[0];
});
},
{ rootMargin: `-60px 0% -75% 0%`, threshold: 1 },
{ rootMargin: `-100px 0% -75% 0%`, threshold: 1 },
);
const scroll = (): void => {
+1 -1
View File
@@ -9,7 +9,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
<input
type={type}
className={cn(
'flex h-9 w-full rounded-md border bg-transparent px-3 py-1 text-sm text-fd-foreground transition-colors placeholder:text-fd-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-fd-ring disabled:cursor-not-allowed disabled:opacity-50',
'flex h-9 w-full rounded-md border bg-transparent px-2 py-1.5 text-sm text-fd-foreground transition-colors placeholder:text-fd-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-fd-ring disabled:cursor-not-allowed disabled:opacity-50',
className,
)}
ref={ref}
+5 -2
View File
@@ -51,11 +51,14 @@ export function ApiProvider({
useEffect(() => {
setBaseUrl((prev) => localStorage.getItem('apiBaseUrl') ?? prev);
if (highlighterInstance) setHighlighter(highlighterInstance);
else
if (highlighterInstance) {
setHighlighter(highlighterInstance);
} else {
void initHighlighter().then((res) => {
highlighterInstance = res;
setHighlighter(res);
});
}
}, []);
useEffect(() => {
+6 -3
View File
@@ -41,7 +41,7 @@ export function APIInfo({
<div className={cn('min-w-0 flex-1', className)} {...props}>
<div
className={cn(
'sticky top-24 z-[2] mb-4 flex flex-row items-center gap-2 rounded-lg border bg-fd-card p-3 md:top-10',
'sticky top-24 z-20 mb-4 flex flex-row items-center gap-2 rounded-lg border bg-fd-card px-3 py-2 md:top-12 lg:top-1',
)}
>
<span
@@ -70,7 +70,7 @@ export function API({
return (
<div
className={cn(
'flex flex-col gap-x-6 gap-y-2 xl:flex-row xl:items-start',
'flex flex-col gap-x-6 gap-y-4 xl:flex-row xl:items-start',
className,
)}
{...props}
@@ -115,7 +115,10 @@ export function APIExample({
}: HTMLAttributes<HTMLDivElement>): React.ReactElement {
return (
<div
className={cn('sticky top-10 prose-no-margin xl:w-[400px]', className)}
className={cn(
'prose-no-margin md:sticky md:top-12 lg:top-1 xl:w-[400px]',
className,
)}
{...props}
>
{children}
+3 -3
View File
@@ -179,7 +179,7 @@ export function APIPlayground({
)}
>
<form
className="not-prose flex flex-col gap-5 rounded-lg border bg-fd-card p-4"
className="not-prose flex flex-col gap-5 rounded-lg border bg-fd-card p-3"
onSubmit={onSubmit as React.FormEventHandler}
>
<div className="flex flex-row gap-2">
@@ -199,7 +199,7 @@ export function APIPlayground({
<Accordions
type="multiple"
className={cn(
'-m-4 border-0 text-sm',
'-m-3 border-0 text-sm',
path.length === 0 &&
query.length === 0 &&
header.length === 0 &&
@@ -294,7 +294,7 @@ function RouteDisplay({ route }: { route: string }): ReactElement {
);
return (
<code className="flex-1 overflow-auto text-nowrap rounded-lg border bg-fd-muted px-3 py-1.5 text-sm text-fd-muted-foreground">
<code className="flex-1 overflow-auto text-nowrap rounded-lg border bg-fd-muted px-2 py-1.5 text-sm text-fd-muted-foreground">
{pathname}
</code>
);
+1 -1
View File
@@ -18,7 +18,7 @@ export function Heading<T extends Types = 'h1'>({
return (
<As
className={cn('flex scroll-m-20 flex-row items-center gap-2', className)}
className={cn('flex scroll-m-28 flex-row items-center gap-2', className)}
{...props}
>
<a href={`#${props.id}`} className="peer">
@@ -73,7 +73,7 @@ export function DynamicSidebar(props: SidebarProps): React.ReactElement {
onPointerLeave: onLeave,
'aria-hidden': Boolean(collapsed && !hover),
className: cn(
'md:transition-all',
'md:transition-[transform,padding,width,margin]',
collapsed && [
'md:top-1 md:me-fd-sidebar-offset md:h-[calc(100dvh-4px)] md:w-[var(--fd-sidebar-width)] md:animate-fd-sidebar-collapse md:rounded-xl md:border md:ps-0 md:shadow-md',
hover
+1 -1
View File
@@ -64,7 +64,7 @@ export function TocPopover({ items, header, footer }: TOCProps): ReactElement {
return (
<Popover>
<PopoverTrigger className="inline-flex items-center gap-2 text-nowrap px-4 py-2 text-left max-md:size-full md:px-3 md:text-fd-muted-foreground">
<PopoverTrigger className="inline-flex size-full items-center gap-2 text-nowrap px-4 py-2 text-left md:px-3">
<Text className="size-4 shrink-0" />
{text.toc}
{current ? (
+23 -21
View File
@@ -61,7 +61,7 @@ export function DocsPage({
toc = [],
tableOfContent = {},
breadcrumb = {},
tableOfContentPopover = {},
tableOfContentPopover: tocPopoverOptions = {},
lastUpdate,
full = false,
footer = {},
@@ -75,28 +75,30 @@ export function DocsPage({
return (
<TocProvider toc={toc}>
<div className="flex min-w-0 flex-1 flex-col">
<div
className={cn(
'sticky top-14 z-10 border-b bg-fd-background/60 text-sm font-medium backdrop-blur-md md:top-0 md:bg-fd-card',
!full && 'lg:hidden',
)}
>
{replaceOrDefault(
tableOfContentPopover,
<div
className={cn(
'mx-auto flex min-w-0 max-w-[860px] flex-1 flex-col',
!tocOptions.enabled &&
// ensure it's still centered when toc is hidden
'max-w-[1200px] md:ms-[max(0px,calc(50vw-min(50%,600px)-var(--fd-c-sidebar)))]',
)}
>
{replaceOrDefault(
tocPopoverOptions,
<div
className={cn(
'sticky top-14 z-10 border-b bg-fd-background/60 text-sm backdrop-blur-md md:top-1 md:mx-3 md:rounded-full md:border md:shadow-md',
tocPopoverOptions.enabled !== true && 'lg:hidden',
)}
>
<TocPopover
items={toc}
header={tableOfContentPopover.header}
footer={tableOfContentPopover.footer}
/>,
)}
</div>
<article
className={cn(
'mx-auto flex w-full max-w-[860px] flex-1 flex-col gap-6 px-4 pt-10 md:px-6 md:pt-12',
!tocOptions.enabled && 'max-w-[1200px]',
)}
>
header={tocPopoverOptions.header}
footer={tocPopoverOptions.footer}
/>
</div>,
)}
<article className="flex flex-1 flex-col gap-6 px-4 pt-10 md:px-6 md:pt-12">
{replaceOrDefault(breadcrumb, <Breadcrumb {...breadcrumb} />)}
{props.children}
<div className="mt-auto" />