Skip to content

Commit

Permalink
UI: Support disableThemeSwitch on layouts
Browse files Browse the repository at this point in the history
  • Loading branch information
fuma-nama committed Sep 15, 2024
1 parent 9c2f01a commit 34cf456
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 40 deletions.
5 changes: 5 additions & 0 deletions .changeset/chatty-ghosts-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'fumadocs-ui': minor
---

Support `disableThemeSwitch` on layouts
1 change: 1 addition & 0 deletions apps/docs/app/layout.config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export const docsOptions: DocsLayoutProps = {
transparentMode: 'none',
children: undefined,
},
links: baseOptions.links?.slice(1),
sidebar: {
banner: (
<RootToggle
Expand Down
11 changes: 7 additions & 4 deletions packages/ui/src/layouts/docs.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { SidebarTrigger } from 'fumadocs-core/sidebar';
import { Menu, SidebarIcon, X } from 'lucide-react';
import { useCallback } from 'react';
import { ButtonHTMLAttributes, useCallback } from 'react';
import { useSidebar } from '@/contexts/sidebar';
import { useSearchContext } from '@/contexts/search';
import { SearchToggle } from '@/components/layout/search-toggle';
Expand Down Expand Up @@ -45,18 +45,21 @@ export function SubNav({
);
}

export function SidebarCollapseTrigger(): React.ReactElement {
export function SidebarCollapseTrigger(
props: ButtonHTMLAttributes<HTMLButtonElement>,
): React.ReactElement {
const { setCollapsed } = useSidebar();

return (
<button
type="button"
aria-label="Collapse Sidebar"
{...props}
className={cn(
buttonVariants({
color: 'ghost',
size: 'icon',
className: 'ms-auto max-md:hidden',
className: props.className,
}),
)}
onClick={useCallback(() => {
Expand All @@ -68,7 +71,7 @@ export function SidebarCollapseTrigger(): React.ReactElement {
);
}

export { LinksMenu } from '@/components/layout/link-item';
export { LinksMenu, LinkItem } from '@/components/layout/link-item';
export { Sidebar } from '@/components/layout/sidebar';
export { TreeContextProvider } from '@/contexts/tree';
export { ThemeToggle } from '@/components/layout/theme-toggle';
Expand Down
43 changes: 28 additions & 15 deletions packages/ui/src/layouts/docs.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { PageTree } from 'fumadocs-core/server';
import type { ReactNode, HTMLAttributes } from 'react';
import { ReactNode, HTMLAttributes, Fragment } from 'react';
import Link from 'next/link';
import { MoreHorizontal } from 'lucide-react';
import { notFound } from 'next/navigation';
Expand All @@ -17,6 +17,7 @@ declare const {
SubNav,
LanguageToggle,
LinksMenu,
LinkItem,
DynamicSidebar,
Sidebar,
}: typeof import('./docs.client');
Expand Down Expand Up @@ -46,7 +47,6 @@ export function DocsLayout({
component: sidebarReplace,
...sidebar
} = {},
containerProps = {},
i18n = false,
...props
}: DocsLayoutProps): React.ReactNode {
Expand Down Expand Up @@ -87,29 +87,49 @@ export function DocsLayout({
</LinksMenu>,
);

footer.push(<ThemeToggle key="theme" />);
if (sidebar.footer) {
footer.push(<Fragment key="footer">{sidebar.footer}</Fragment>);
}

if (!props.disableThemeSwitch) {
footer.push(<ThemeToggle key="theme" className="me-auto" />);
}

if (i18n) {
footer.push(<LanguageToggle key="i18n" />);
}

if (links.some((v) => v.type === 'icon')) {
footer.push(
<Fragment key="links">
{links
.filter((v) => v.type === 'icon')
.map((v, i) => (
<LinkItem key={i} item={v} on="nav" className="md:hidden" />
))}
</Fragment>,
);
}

if (collapsible) {
footer.push(<SidebarCollapseTrigger key="sidebar" />);
footer.push(
<SidebarCollapseTrigger key="sidebar" className="max-md:hidden" />,
);
}

return (
<TreeContextProvider tree={props.tree}>
{replaceOrDefault(nav, <SubNav {...nav} />)}
<main
id="nd-docs-layout"
{...containerProps}
className={cn('flex flex-1 flex-row', containerProps.className)}
{...props.containerProps}
className={cn('flex flex-1 flex-row', props.containerProps?.className)}
>
{replaceOrDefault(
{ enabled: sidebarEnabled, component: sidebarReplace },
<Aside
{...sidebar}
items={links}
items={links.filter((v) => v.type !== 'icon')}
banner={
banner.length > 0 || sidebar.banner ? (
<>
Expand All @@ -129,14 +149,7 @@ export function DocsLayout({
sidebar.bannerProps?.className,
),
}}
footer={
footer.length > 0 || sidebar.footer ? (
<>
{sidebar.footer}
{footer}
</>
) : null
}
footer={footer.length > 0 ? footer : null}
/>,
)}
{props.children}
Expand Down
33 changes: 18 additions & 15 deletions packages/ui/src/layouts/home.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,26 @@ import { LanguageToggle } from '@/components/layout/language-toggle';
import type { SharedNavProps } from './shared';

export function Nav({
title,
url,
items,
transparentMode,
enableSearch = true,
i18n,
children,
...props
}: SharedNavProps & {
disableThemeSwitch?: boolean;
i18n?: boolean;
items: LinkItemType[];
}): React.ReactElement {
const search = useSearchContext();
const { text } = useI18n();

return (
<NavBox id="nd-nav" className="h-14" transparentMode={transparentMode}>
<NavBox
id="nd-nav"
className="h-14"
transparentMode={props.transparentMode}
>
<nav className="mx-auto flex size-full max-w-container flex-row items-center gap-6 px-4">
<Title title={title} url={url} />
{children}
<Title title={props.title} url={props.url} />
{props.children}
{items
.filter((item) => !isSecondary(item))
.map((item, i) => (
Expand Down Expand Up @@ -68,13 +69,15 @@ export function Nav({
)}
footer={
<>
<div className="flex flex-row items-center justify-between px-2 pt-2">
<p className="font-medium text-fd-muted-foreground">
{text.chooseTheme}
</p>
<ThemeToggle />
</div>
{i18n ? (
{!props.disableThemeSwitch ? (
<div className="flex flex-row items-center justify-between px-2 pt-2">
<p className="font-medium text-fd-muted-foreground">
{text.chooseTheme}
</p>
<ThemeToggle />
</div>
) : null}
{props.i18n ? (
<div className="flex flex-row items-center justify-between px-2 pt-2">
<p className="font-medium text-fd-muted-foreground">
{text.chooseLanguage}
Expand Down
15 changes: 9 additions & 6 deletions packages/ui/src/layouts/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,24 @@ export type HomeLayoutProps = BaseLayoutProps;
export function HomeLayout({
nav = {},
links = [],
githubUrl,
i18n,
children,
...props
}: BaseLayoutProps): React.ReactElement {
const finalLinks = getLinks(links, githubUrl);
const finalLinks = getLinks(links, props.githubUrl);

return (
<>
{replaceOrDefault(
nav,
<Nav items={finalLinks} i18n={i18n} {...nav}>
<Nav
items={finalLinks}
i18n={props.i18n}
disableThemeSwitch={props.disableThemeSwitch}
{...nav}
>
{nav.children}
</Nav>,
)}
{children}
{props.children}
</>
);
}
5 changes: 5 additions & 0 deletions packages/ui/src/layouts/shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ export interface SharedNavProps extends TitleProps, NavBoxProps {
}

export interface BaseLayoutProps {
/**
* Remove theme switcher component
*/
disableThemeSwitch?: boolean;

/**
* Enable Language Switch
*
Expand Down

0 comments on commit 34cf456

Please sign in to comment.