UI: Support themeSwitch option in layouts to customise theme switch

This commit is contained in:
Fuma Nama
2025-03-14 20:11:55 +08:00
parent 72f79cfe46
commit b7906994fa
5 changed files with 46 additions and 12 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-ui': patch
---
Support `themeSwitch` option in layouts to customise theme switch
+10 -5
View File
@@ -53,6 +53,7 @@ export function DocsLayout({
transparentMode,
...nav
} = {},
themeSwitch,
sidebar: {
enabled: sidebarEnabled = true,
collapsible = true,
@@ -178,7 +179,7 @@ export function DocsLayout({
<SidebarFooterItems
links={links}
i18n={i18n}
disableThemeSwitch={props.disableThemeSwitch ?? false}
themeSwitch={themeSwitch}
/>
{sidebarFooter}
</SidebarFooter>
@@ -197,17 +198,18 @@ export function DocsLayout({
function SidebarFooterItems({
i18n,
disableThemeSwitch,
themeSwitch,
links,
}: {
i18n: boolean;
links: LinkItemType[];
disableThemeSwitch: boolean;
themeSwitch: DocsLayoutProps['themeSwitch'];
}) {
const iconItems = links.filter((v) => v.type === 'icon');
// empty footer items
if (links.length === 0 && !i18n && disableThemeSwitch) return null;
if (links.length === 0 && !i18n && themeSwitch?.enabled === false)
return null;
return (
<div className="flex flex-row items-center">
@@ -231,7 +233,10 @@ function SidebarFooterItems({
<LanguageToggleText className="md:hidden" />
</LanguageToggle>
) : null}
{!disableThemeSwitch ? <ThemeToggle className="p-0" /> : null}
{replaceOrDefault(
themeSwitch,
<ThemeToggle className="p-0" mode={themeSwitch?.mode} />,
)}
</div>
);
}
+10 -3
View File
@@ -49,6 +49,7 @@ export function HomeLayout(props: HomeLayoutProps) {
links,
githubUrl,
i18n: _i18n,
themeSwitch: _themeSwitch,
disableThemeSwitch: _disableThemeSwitch,
...rest
} = props;
@@ -75,7 +76,7 @@ function Header({
nav: { enableSearch = true, ...nav } = {},
i18n = false,
finalLinks,
disableThemeSwitch,
themeSwitch,
}: HomeLayoutProps & {
finalLinks: LinkItemType[];
}) {
@@ -107,7 +108,10 @@ function Header({
/>
</>
) : null}
{!disableThemeSwitch ? <ThemeToggle className="max-lg:hidden" /> : null}
{replaceOrDefault(
themeSwitch,
<ThemeToggle className="max-lg:hidden" mode={themeSwitch?.mode} />,
)}
{i18n ? (
<LanguageToggle className="max-lg:hidden">
<Languages className="size-5" />
@@ -148,7 +152,10 @@ function Header({
<ChevronDown className="size-3 text-fd-muted-foreground" />
</LanguageToggle>
) : null}
{!disableThemeSwitch ? <ThemeToggle /> : null}
{replaceOrDefault(
themeSwitch,
<ThemeToggle mode={themeSwitch?.mode} />,
)}
</div>
</MenuContent>
</Menu>
+13 -4
View File
@@ -1,5 +1,9 @@
import { Fragment, type HTMLAttributes } from 'react';
import { type BaseLayoutProps, getLinks } from '@/layouts/shared';
import {
type BaseLayoutProps,
getLinks,
replaceOrDefault,
} from '@/layouts/shared';
import {
CollapsibleSidebar,
Sidebar,
@@ -70,6 +74,7 @@ export function DocsLayout({
...sidebar
} = {},
i18n = false,
themeSwitch,
...props
}: DocsLayoutProps) {
checkPageTree(props.tree);
@@ -177,9 +182,13 @@ export function DocsLayout({
<Languages className="size-5 text-fd-muted-foreground" />
</LanguageToggle>
) : null}
{!props.disableThemeSwitch ? (
<ThemeToggle className="md:hidden" mode="light-dark-system" />
) : null}
{replaceOrDefault(
themeSwitch,
<ThemeToggle
className="md:hidden"
mode={themeSwitch?.mode ?? 'light-dark-system'}
/>,
)}
{sidebarFooter}
</SidebarFooter>
</Aside>
+8
View File
@@ -19,8 +19,16 @@ export interface SharedNavProps extends TitleProps, NavProviderProps {
}
export interface BaseLayoutProps {
themeSwitch?: {
enabled?: boolean;
component?: ReactNode;
mode?: 'light-dark' | 'light-dark-system';
};
/**
* Remove theme switcher component
*
* @deprecated Use `themeSwitch.enabled` instead.
*/
disableThemeSwitch?: boolean;