CLI: add Flux layout to customise option

This commit is contained in:
Fuma Nama
2026-02-08 17:24:11 +08:00
parent e7d49989a3
commit 4c570ce16c
7 changed files with 170 additions and 41 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@fumadocs/cli': patch
---
add Flux layout to customise option
+2 -2
View File
@@ -66,7 +66,7 @@ function CustomNavigationPanel({ tool, ...props }: NavigationPanelProps) {
<AnimatePresence> <AnimatePresence>
{ai.open && ( {ai.open && (
<motion.div <motion.div
className="flex flex-col size-full px-3 mx-auto sm:max-w-[380px]" className="flex flex-col size-full mx-auto sm:max-w-[380px]"
variants={{ variants={{
show: { show: {
y: 0, y: 0,
@@ -89,7 +89,7 @@ function CustomNavigationPanel({ tool, ...props }: NavigationPanelProps) {
}} }}
> >
<AISearchPanelHeader onClick={(e) => e.stopPropagation()} /> <AISearchPanelHeader onClick={(e) => e.stopPropagation()} />
<AISearchPanelList className="flex-1" /> <AISearchPanelList className="px-3 flex-1" />
</motion.div> </motion.div>
)} )}
</AnimatePresence> </AnimatePresence>
@@ -0,0 +1,52 @@
---
title: Flux Layout
description: An aggressively minimal layout for docs
---
A docs layout that impractically minimal & clean, originally made for experimental purpose.
![Flux](./flux.png)
<Customisation />
## Usage
Enable the Flux layout with `fumadocs-ui/layouts/flux`.
```tsx title="layout.tsx"
import { DocsLayout } from 'fumadocs-ui/layouts/flux'; // [!code highlight]
import { baseOptions } from '@/lib/layout.shared';
import { source } from '@/lib/source';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout {...baseOptions()} tree={source.getPageTree()}>
{children}
</DocsLayout>
);
}
```
Make sure to update your page import too:
```tsx title="page.tsx"
import { ... } from 'fumadocs-ui/layouts/docs/page'; // [!code --]
import { ... } from 'fumadocs-ui/layouts/flux/page'; // [!code ++]
```
<Callout title="Important to know">
- It is best to be paired with [static/local search](/docs/search/orama#static), the navigation is more efficient using document search.
- It prioritizes subjective aesthetics over user experience.
- It is opinionated, use Fumadocs CLI for customisation instead.
</Callout>
## Configurations
The options are inherited from [Docs Layout](/docs/ui/layouts/docs), with minor differences:
- Flux layout is a client component, you cannot pass unserializable props from a server component.
- A `renderNavigationPanel` prop to customise the bottom navigation panel.
- There is no `tocPopover` options.
Binary file not shown.

After

Width:  |  Height:  |  Size: 696 KiB

+31
View File
@@ -101,6 +101,37 @@ export const registry: Registry = {
], ],
unlisted: true, unlisted: true,
}, },
{
name: 'layouts/flux',
files: [
{
type: 'components',
path: 'layouts/flux/index.tsx',
target: '<dir>/layout/flux/index.tsx',
},
{
type: 'components',
path: 'layouts/flux/tab-dropdown.tsx',
target: '<dir>/layout/flux/tab-dropdown.tsx',
},
{
type: 'components',
path: 'layouts/flux/sidebar.tsx',
target: '<dir>/layout/flux/sidebar.tsx',
},
{
type: 'components',
path: 'layouts/flux/page/index.tsx',
target: '<dir>/layout/flux/page/index.tsx',
},
{
type: 'components',
path: 'layouts/flux/page/client.tsx',
target: '<dir>/layout/flux/page/client.tsx',
},
],
unlisted: true,
},
{ {
name: 'layouts/notebook', name: 'layouts/notebook',
files: [ files: [
+49 -39
View File
@@ -5,14 +5,20 @@ import type { RegistryClient } from '@/registry/client';
import { ComponentInstaller } from '@/registry/installer'; import { ComponentInstaller } from '@/registry/installer';
import { UIRegistries } from '@/commands/shared'; import { UIRegistries } from '@/commands/shared';
interface TargetInfo {
target: string[];
replace: [string, string][];
}
export async function customise(client: RegistryClient) { export async function customise(client: RegistryClient) {
intro(picocolors.bgBlack(picocolors.whiteBright('Customise Fumadocs UI'))); intro(picocolors.bgBlack(picocolors.whiteBright('Customise Fumadocs UI')));
const config = client.config; const config = client.config;
const installer = new ComponentInstaller(client); const installer = new ComponentInstaller(client);
const registry = UIRegistries[config.uiLibrary];
const result = await group( const result = await group(
{ {
target: () => layout: () =>
select({ select({
message: 'What do you want to customise?', message: 'What do you want to customise?',
options: [ options: [
@@ -28,25 +34,58 @@ export async function customise(client: RegistryClient) {
}, },
], ],
}), }),
mode: (v) => { target: (v): Promise<TargetInfo | symbol> => {
if (v.results.target !== 'docs') return; if (v.results.layout !== 'docs')
return Promise.resolve({
target: [`${registry}/layouts/home`],
replace: [['fumadocs-ui/layouts/home', `@/components/layout/home`]],
});
return select({ return select<TargetInfo>({
message: 'Which variant do you want to start from?', message: 'Which variant do you want to start from?',
options: [ options: [
{ {
label: 'Start from minimal styles', label: 'Start from minimal styles',
value: 'minimal',
hint: 'for those who want to build their own variant from ground up.', hint: 'for those who want to build their own variant from ground up.',
value: {
target: ['fumadocs/ui/layouts/docs-min'],
replace: [
['fumadocs-ui/layouts/docs', '@/components/layout/docs'],
['fumadocs-ui/layouts/docs/page', '@/components/layout/docs/page'],
],
},
}, },
{ {
label: 'Start from default layout', label: 'Start from default layout',
value: 'full-default', value: {
target: [`${registry}/layouts/docs`],
replace: [
['fumadocs-ui/layouts/docs', '@/components/layout/docs'],
['fumadocs-ui/layouts/docs/page', '@/components/layout/docs/page'],
],
},
hint: 'useful for adjusting small details.', hint: 'useful for adjusting small details.',
}, },
{ {
label: 'Start from Notebook layout', label: 'Start from Notebook layout',
value: 'full-notebook', value: {
target: [`${registry}/layouts/notebook`],
replace: [
['fumadocs-ui/layouts/notebook', '@/components/layout/notebook'],
['fumadocs-ui/layouts/notebook/page', '@/components/layout/notebook/page'],
],
},
hint: 'useful for adjusting small details.',
},
{
label: 'Start from Flux layout',
value: {
target: [`${registry}/layouts/flux`],
replace: [
['fumadocs-ui/layouts/flux', '@/components/layout/flux'],
['fumadocs-ui/layouts/flux/page', '@/components/layout/flux/page'],
],
},
hint: 'useful for adjusting small details.', hint: 'useful for adjusting small details.',
}, },
], ],
@@ -61,38 +100,9 @@ export async function customise(client: RegistryClient) {
}, },
); );
const registry = UIRegistries[config.uiLibrary]; const target = result.target as TargetInfo;
if (result.target === 'docs') { await install(target.target, installer);
const targets = []; printNext(...target.replace);
if (result.mode === 'minimal') {
targets.push('fumadocs/ui/layouts/docs-min');
} else {
targets.push(
result.mode === 'full-default'
? `${registry}/layouts/docs`
: `${registry}/layouts/notebook`,
);
}
await install(targets, installer);
const maps: [string, string][] =
result.mode === 'full-notebook'
? [
['fumadocs-ui/layouts/notebook', '@/components/layout/notebook'],
['fumadocs-ui/layouts/notebook/page', '@/components/layout/notebook/page'],
]
: [
['fumadocs-ui/layouts/docs', '@/components/layout/docs'],
['fumadocs-ui/layouts/docs/page', '@/components/layout/docs/page'],
];
printNext(...maps);
}
if (result.target === 'home') {
await install([`${registry}/layouts/home`], installer);
printNext(['fumadocs-ui/layouts/home', `@/components/layout/home`]);
}
outro(picocolors.bold('Have fun!')); outro(picocolors.bold('Have fun!'));
} }
+31
View File
@@ -101,6 +101,37 @@ export const registry: Registry = {
], ],
unlisted: true, unlisted: true,
}, },
{
name: 'layouts/flux',
files: [
{
type: 'components',
path: 'layouts/flux/index.tsx',
target: '<dir>/layout/flux/index.tsx',
},
{
type: 'components',
path: 'layouts/flux/tab-dropdown.tsx',
target: '<dir>/layout/flux/tab-dropdown.tsx',
},
{
type: 'components',
path: 'layouts/flux/sidebar.tsx',
target: '<dir>/layout/flux/sidebar.tsx',
},
{
type: 'components',
path: 'layouts/flux/page/index.tsx',
target: '<dir>/layout/flux/page/index.tsx',
},
{
type: 'components',
path: 'layouts/flux/page/client.tsx',
target: '<dir>/layout/flux/page/client.tsx',
},
],
unlisted: true,
},
{ {
name: 'layouts/notebook', name: 'layouts/notebook',
files: [ files: [