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>
{ai.open && (
<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={{
show: {
y: 0,
@@ -89,7 +89,7 @@ function CustomNavigationPanel({ tool, ...props }: NavigationPanelProps) {
}}
>
<AISearchPanelHeader onClick={(e) => e.stopPropagation()} />
<AISearchPanelList className="flex-1" />
<AISearchPanelList className="px-3 flex-1" />
</motion.div>
)}
</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,
},
{
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',
files: [
+49 -39
View File
@@ -5,14 +5,20 @@ import type { RegistryClient } from '@/registry/client';
import { ComponentInstaller } from '@/registry/installer';
import { UIRegistries } from '@/commands/shared';
interface TargetInfo {
target: string[];
replace: [string, string][];
}
export async function customise(client: RegistryClient) {
intro(picocolors.bgBlack(picocolors.whiteBright('Customise Fumadocs UI')));
const config = client.config;
const installer = new ComponentInstaller(client);
const registry = UIRegistries[config.uiLibrary];
const result = await group(
{
target: () =>
layout: () =>
select({
message: 'What do you want to customise?',
options: [
@@ -28,25 +34,58 @@ export async function customise(client: RegistryClient) {
},
],
}),
mode: (v) => {
if (v.results.target !== 'docs') return;
target: (v): Promise<TargetInfo | symbol> => {
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?',
options: [
{
label: 'Start from minimal styles',
value: 'minimal',
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',
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.',
},
{
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.',
},
],
@@ -61,38 +100,9 @@ export async function customise(client: RegistryClient) {
},
);
const registry = UIRegistries[config.uiLibrary];
if (result.target === 'docs') {
const targets = [];
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`]);
}
const target = result.target as TargetInfo;
await install(target.target, installer);
printNext(...target.replace);
outro(picocolors.bold('Have fun!'));
}
+31
View File
@@ -101,6 +101,37 @@ export const registry: Registry = {
],
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',
files: [