mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-26 06:31:49 +00:00
UI: No longer expose layout components
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
---
|
||||
'fumadocs-ui': minor
|
||||
---
|
||||
|
||||
**No longer expose layout components**
|
||||
|
||||
This includes Root Toggle, Language Toggle, Theme Toggle etc.
|
||||
|
||||
It allows Fumadocs UI to change these components without introducing breaking changes over existing customizations.
|
||||
|
||||
If you're using the removed components, consider overriding the layout components with yours, or use Fumadocs CLI add/customize command.
|
||||
@@ -3,7 +3,6 @@ import { Heading } from 'fumadocs-ui/components/heading';
|
||||
import { Card } from 'fumadocs-ui/components/card';
|
||||
import { Callout } from 'fumadocs-ui/components/callout';
|
||||
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
|
||||
import { RootToggle } from 'fumadocs-ui/components/layout/root-toggle';
|
||||
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
|
||||
import { Step, Steps } from 'fumadocs-ui/components/steps';
|
||||
import { TypeTable } from 'fumadocs-ui/components/type-table';
|
||||
@@ -200,30 +199,6 @@ export function steps(): ReactNode {
|
||||
);
|
||||
}
|
||||
|
||||
export function rootToggle(): ReactNode {
|
||||
return (
|
||||
<Wrapper>
|
||||
<div className="not-prose mx-auto grid max-w-[240px] rounded-lg bg-fd-background">
|
||||
<RootToggle
|
||||
className="p-3"
|
||||
options={[
|
||||
{
|
||||
title: 'Hello World',
|
||||
description: 'The example item of root toggle',
|
||||
url: '/docs/ui',
|
||||
},
|
||||
{
|
||||
title: 'Other page',
|
||||
description: 'The example item of root toggle',
|
||||
url: '/docs/headless',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export function dynamicCodeBlock() {
|
||||
return (
|
||||
<Wrapper>
|
||||
|
||||
@@ -57,7 +57,7 @@ export default function Layout({ children }: { children: ReactNode }) {
|
||||
|
||||
Sidebar Tabs are folders with tab-like behaviours, only the content of opened tab will be visible.
|
||||
|
||||
<div className='flex justify-center items-center *:max-w-[360px] bg-gradient-to-br from-fd-primary/10 rounded-xl border'>
|
||||
<div className='flex justify-center items-center *:max-w-[360px] bg-linear-to-br from-fd-primary/10 rounded-xl border'>
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -110,24 +110,44 @@ export const registry: Registry = {
|
||||
{
|
||||
type: 'components',
|
||||
path: 'layouts/shared/index.tsx',
|
||||
target: 'components/layout/shared/index.tsx',
|
||||
target: 'components/layout/shared.tsx',
|
||||
},
|
||||
{
|
||||
type: 'components',
|
||||
path: 'layouts/shared/client.tsx',
|
||||
target: 'components/layout/shared/client.tsx',
|
||||
path: 'layouts/shared/sidebar-tab.tsx',
|
||||
target: 'components/layout/sidebar-tab.tsx',
|
||||
},
|
||||
{
|
||||
type: 'components',
|
||||
path: 'components/layout/search-toggle.tsx',
|
||||
path: 'layouts/shared/language-toggle.tsx',
|
||||
target: 'components/layout/language-toggle.tsx',
|
||||
},
|
||||
{
|
||||
type: 'components',
|
||||
path: 'components/layout/theme-toggle.tsx',
|
||||
path: 'layouts/shared/link-item.tsx',
|
||||
target: 'components/layout/link-item.tsx',
|
||||
},
|
||||
{
|
||||
type: 'components',
|
||||
path: 'components/layout/sidebar.tsx',
|
||||
path: 'layouts/shared/search-toggle.tsx',
|
||||
target: 'components/layout/search-toggle.tsx',
|
||||
},
|
||||
{
|
||||
type: 'components',
|
||||
path: 'layouts/shared/theme-toggle.tsx',
|
||||
target: 'components/layout/theme-toggle.tsx',
|
||||
},
|
||||
{
|
||||
type: 'components',
|
||||
path: 'components/toc/clerk.tsx',
|
||||
},
|
||||
{
|
||||
type: 'components',
|
||||
path: 'components/toc/default.tsx',
|
||||
},
|
||||
{
|
||||
type: 'components',
|
||||
path: 'components/toc/index.tsx',
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -144,6 +164,21 @@ export const registry: Registry = {
|
||||
path: 'layouts/docs/client.tsx',
|
||||
target: 'components/layout/docs/client.tsx',
|
||||
},
|
||||
{
|
||||
type: 'block',
|
||||
path: 'layouts/docs/sidebar.tsx',
|
||||
target: 'components/layout/docs/sidebar.tsx',
|
||||
},
|
||||
{
|
||||
type: 'block',
|
||||
path: 'layouts/docs/page/index.tsx',
|
||||
target: 'components/layout/docs/page/index.tsx',
|
||||
},
|
||||
{
|
||||
type: 'block',
|
||||
path: 'layouts/docs/page/client.tsx',
|
||||
target: 'components/layout/docs/page/client.tsx',
|
||||
},
|
||||
],
|
||||
unlisted: true,
|
||||
},
|
||||
@@ -153,45 +188,27 @@ export const registry: Registry = {
|
||||
{
|
||||
type: 'block',
|
||||
path: 'layouts/notebook/index.tsx',
|
||||
target: 'components/layout/docs/index.tsx',
|
||||
target: 'components/layout/notebook/index.tsx',
|
||||
},
|
||||
{
|
||||
type: 'block',
|
||||
path: 'layouts/notebook/client.tsx',
|
||||
target: 'components/layout/docs/client.tsx',
|
||||
},
|
||||
],
|
||||
unlisted: true,
|
||||
},
|
||||
{
|
||||
name: 'layouts/page',
|
||||
files: [
|
||||
{
|
||||
type: 'components',
|
||||
path: 'layouts/docs/page.tsx',
|
||||
target: 'components/layout/docs/page.tsx',
|
||||
target: 'components/layout/notebook/client.tsx',
|
||||
},
|
||||
{
|
||||
type: 'block',
|
||||
path: 'layouts/docs/page-client.tsx',
|
||||
target: 'components/layout/docs/page-client.tsx',
|
||||
path: 'layouts/notebook/sidebar.tsx',
|
||||
target: 'components/layout/notebook/sidebar.tsx',
|
||||
},
|
||||
{
|
||||
type: 'components',
|
||||
path: 'page.tsx',
|
||||
target: 'components/layout/page.tsx',
|
||||
type: 'block',
|
||||
path: 'layouts/notebook/page/index.tsx',
|
||||
target: 'components/layout/notebook/page/index.tsx',
|
||||
},
|
||||
{
|
||||
type: 'ui',
|
||||
path: 'components/layout/toc.tsx',
|
||||
},
|
||||
{
|
||||
type: 'ui',
|
||||
path: 'components/layout/toc-clerk.tsx',
|
||||
},
|
||||
{
|
||||
type: 'ui',
|
||||
path: 'components/layout/toc-thumb.tsx',
|
||||
type: 'block',
|
||||
path: 'layouts/notebook/page/client.tsx',
|
||||
target: 'components/layout/notebook/page/client.tsx',
|
||||
},
|
||||
],
|
||||
unlisted: true,
|
||||
@@ -204,13 +221,6 @@ export const registry: Registry = {
|
||||
path: 'layouts/home/index.tsx',
|
||||
target: 'components/layout/home/index.tsx',
|
||||
},
|
||||
/* optional
|
||||
{
|
||||
type: 'components',
|
||||
path: 'layouts/home/navbar.tsx',
|
||||
target: 'components/layout/home/navbar.tsx',
|
||||
},
|
||||
*/
|
||||
{
|
||||
type: 'components',
|
||||
path: 'layouts/home/client.tsx',
|
||||
@@ -219,26 +229,6 @@ export const registry: Registry = {
|
||||
],
|
||||
unlisted: true,
|
||||
},
|
||||
{
|
||||
name: 'root-toggle',
|
||||
description: 'the UI of Sidebar Tabs',
|
||||
files: [
|
||||
{
|
||||
type: 'components',
|
||||
path: 'components/layout/root-toggle.tsx',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'language-toggle',
|
||||
description: 'Language Select',
|
||||
files: [
|
||||
{
|
||||
type: 'components',
|
||||
path: 'components/layout/language-toggle.tsx',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'accordion',
|
||||
files: [
|
||||
|
||||
@@ -8,10 +8,10 @@ import { useSidebar } from '@/contexts/sidebar';
|
||||
import { useNav } from '@/contexts/layout';
|
||||
import { SidebarCollapseTrigger } from './sidebar';
|
||||
import { SearchToggle } from '../shared/search-toggle';
|
||||
import type { Option } from '@/layouts/shared/root-toggle';
|
||||
import { usePathname } from 'fumadocs-core/framework';
|
||||
import { isTabActive } from '@/utils/is-active';
|
||||
import Link from 'fumadocs-core/link';
|
||||
import type { SidebarTab } from '@/utils/get-sidebar-tabs';
|
||||
|
||||
export function LayoutHeader(props: ComponentProps<'header'>) {
|
||||
const { isTransparent } = useNav();
|
||||
@@ -37,7 +37,10 @@ export function LayoutBody({
|
||||
return (
|
||||
<div
|
||||
id="nd-docs-layout"
|
||||
className={cn('grid transition-[grid-template-columns]', className)}
|
||||
className={cn(
|
||||
'grid transition-[grid-template-columns] overflow-x-clip',
|
||||
className,
|
||||
)}
|
||||
style={{
|
||||
gridTemplate: `"sidebar header header"
|
||||
"sidebar toc-popover toc-popover"
|
||||
@@ -81,7 +84,7 @@ export function LayoutTabs({
|
||||
options,
|
||||
...props
|
||||
}: ComponentProps<'div'> & {
|
||||
options: Option[];
|
||||
options: SidebarTab[];
|
||||
}) {
|
||||
const pathname = usePathname();
|
||||
const selected = useMemo(() => {
|
||||
|
||||
@@ -14,15 +14,16 @@ import {
|
||||
type SidebarComponents,
|
||||
SidebarContent,
|
||||
SidebarContentMobile,
|
||||
SidebarFooter,
|
||||
SidebarHeader,
|
||||
SidebarLinkItem,
|
||||
SidebarPageTree,
|
||||
type SidebarProps,
|
||||
SidebarTrigger,
|
||||
SidebarViewport,
|
||||
} from './sidebar';
|
||||
import { type Option, RootToggle } from '@/layouts/shared/root-toggle';
|
||||
import {
|
||||
type SidebarTabWithProps,
|
||||
SidebarTabTrigger,
|
||||
} from '@/layouts/shared/sidebar-tab';
|
||||
import { type BaseLayoutProps, resolveLinkItems } from '@/layouts/shared';
|
||||
import { LinkItem } from '@/layouts/shared/link-item';
|
||||
import {
|
||||
@@ -71,7 +72,7 @@ interface SidebarOptions
|
||||
/**
|
||||
* Root Toggle options
|
||||
*/
|
||||
tabs?: Option[] | GetSidebarTabsOptions | false;
|
||||
tabs?: SidebarTabWithProps[] | GetSidebarTabsOptions | false;
|
||||
|
||||
banner?: ReactNode;
|
||||
footer?: ReactNode;
|
||||
@@ -145,7 +146,7 @@ export function DocsLayout({
|
||||
|
||||
const mobile = (
|
||||
<SidebarContentMobile {...rest}>
|
||||
<SidebarHeader>
|
||||
<div className="flex flex-col gap-3 p-4 pb-2">
|
||||
<div className="flex text-fd-muted-foreground items-center gap-1.5">
|
||||
<div className="flex flex-1">
|
||||
{iconLinks.map((item, i) => (
|
||||
@@ -187,17 +188,19 @@ export function DocsLayout({
|
||||
<SidebarIcon />
|
||||
</SidebarTrigger>
|
||||
</div>
|
||||
{tabs.length > 0 && <RootToggle options={tabs} />}
|
||||
{tabs.length > 0 && <SidebarTabTrigger options={tabs} />}
|
||||
{banner}
|
||||
</SidebarHeader>
|
||||
</div>
|
||||
{viewport}
|
||||
<SidebarFooter className="empty:hidden">{footer}</SidebarFooter>
|
||||
<div className="flex flex-col border-t p-4 pt-2 empty:hidden">
|
||||
{footer}
|
||||
</div>
|
||||
</SidebarContentMobile>
|
||||
);
|
||||
|
||||
const content = (
|
||||
<SidebarContent {...rest}>
|
||||
<SidebarHeader>
|
||||
<div className="flex flex-col gap-3 p-4 pb-2">
|
||||
<div className="flex">
|
||||
<Link
|
||||
href={nav.url ?? '/'}
|
||||
@@ -225,16 +228,16 @@ export function DocsLayout({
|
||||
<LargeSearchToggle hideIfDisabled />
|
||||
))}
|
||||
{tabs.length > 0 && tabMode === 'auto' && (
|
||||
<RootToggle options={tabs} />
|
||||
<SidebarTabTrigger options={tabs} />
|
||||
)}
|
||||
{banner}
|
||||
</SidebarHeader>
|
||||
</div>
|
||||
{viewport}
|
||||
{(i18n ||
|
||||
iconLinks.length > 0 ||
|
||||
themeSwitch?.enabled !== false ||
|
||||
footer) && (
|
||||
<SidebarFooter>
|
||||
<div className="flex flex-col border-t p-4 pt-2 empty:hidden">
|
||||
<div className="flex text-fd-muted-foreground items-center empty:hidden">
|
||||
{i18n && (
|
||||
<LanguageToggle>
|
||||
@@ -262,7 +265,7 @@ export function DocsLayout({
|
||||
))}
|
||||
</div>
|
||||
{footer}
|
||||
</SidebarFooter>
|
||||
</div>
|
||||
)}
|
||||
</SidebarContent>
|
||||
);
|
||||
|
||||
@@ -116,12 +116,14 @@ export function SidebarContent(props: ComponentProps<'aside'>) {
|
||||
const ignoreHoverUntil = useRef(0);
|
||||
|
||||
useOnChange(collapsed, () => {
|
||||
setHover(true);
|
||||
ignoreHoverUntil.current = Date.now() + 200;
|
||||
if (collapsed) {
|
||||
setHover(true);
|
||||
ignoreHoverUntil.current = Date.now() + 200;
|
||||
|
||||
setTimeout(() => {
|
||||
setHover(false);
|
||||
}, 200);
|
||||
setTimeout(() => {
|
||||
setHover(false);
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -213,28 +215,6 @@ export function SidebarContentMobile({
|
||||
);
|
||||
}
|
||||
|
||||
export function SidebarHeader(props: ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
className={cn('flex flex-col gap-3 p-4 pb-2', props.className)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function SidebarFooter(props: ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
className={cn('flex flex-col border-t p-4 pt-2', props.className)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function SidebarViewport(props: ScrollAreaProps) {
|
||||
return (
|
||||
<ScrollArea {...props} className={cn('min-h-0 flex-1', props.className)}>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Sidebar as SidebarIcon } from 'lucide-react';
|
||||
import Link from 'fumadocs-core/link';
|
||||
import { usePathname } from 'fumadocs-core/framework';
|
||||
import { isTabActive } from '@/utils/is-active';
|
||||
import type { Option } from '@/layouts/shared/root-toggle';
|
||||
import type { SidebarTabWithProps } from '@/layouts/shared/sidebar-tab';
|
||||
|
||||
export function Navbar({
|
||||
mode,
|
||||
@@ -86,7 +86,7 @@ export function LayoutTabs({
|
||||
options,
|
||||
...props
|
||||
}: ComponentProps<'div'> & {
|
||||
options: Option[];
|
||||
options: SidebarTabWithProps[];
|
||||
}) {
|
||||
const pathname = usePathname();
|
||||
const selected = useMemo(() => {
|
||||
@@ -116,7 +116,7 @@ function LayoutTab({
|
||||
option: { title, url, unlisted, props },
|
||||
selected = false,
|
||||
}: {
|
||||
option: Option;
|
||||
option: SidebarTabWithProps;
|
||||
selected?: boolean;
|
||||
}) {
|
||||
return (
|
||||
|
||||
@@ -49,7 +49,10 @@ import {
|
||||
NavbarSidebarTrigger,
|
||||
} from '@/layouts/notebook/client';
|
||||
import { NavProvider } from '@/contexts/layout';
|
||||
import { type Option, RootToggle } from '@/layouts/shared/root-toggle';
|
||||
import {
|
||||
type SidebarTabWithProps,
|
||||
SidebarTabTrigger,
|
||||
} from '@/layouts/shared/sidebar-tab';
|
||||
import Link from 'fumadocs-core/link';
|
||||
import {
|
||||
LargeSearchToggle,
|
||||
@@ -82,7 +85,7 @@ interface SidebarOptions
|
||||
/**
|
||||
* Root Toggle options
|
||||
*/
|
||||
tabs?: Option[] | GetSidebarTabsOptions | false;
|
||||
tabs?: SidebarTabWithProps[] | GetSidebarTabsOptions | false;
|
||||
|
||||
banner?: ReactNode | FC<ComponentProps<typeof SidebarHeader>>;
|
||||
footer?: ReactNode | FC<ComponentProps<typeof SidebarFooter>>;
|
||||
@@ -155,10 +158,10 @@ export function DocsLayout(props: DocsLayoutProps) {
|
||||
const rootToggle = (
|
||||
<>
|
||||
{tabMode === 'sidebar' && tabs.length > 0 && (
|
||||
<RootToggle className="mb-2" options={tabs} />
|
||||
<SidebarTabTrigger className="mb-2" options={tabs} />
|
||||
)}
|
||||
{tabMode === 'navbar' && tabs.length > 0 && (
|
||||
<RootToggle options={tabs} className="lg:hidden" />
|
||||
<SidebarTabTrigger options={tabs} className="lg:hidden" />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
@@ -340,7 +343,7 @@ function DocsNavbar({
|
||||
i18n,
|
||||
}: DocsLayoutProps & {
|
||||
links: LinkItemType[];
|
||||
tabs: Option[];
|
||||
tabs: SidebarTabWithProps[];
|
||||
}) {
|
||||
const navMode = nav.mode ?? 'auto';
|
||||
|
||||
|
||||
+3
-3
@@ -13,17 +13,17 @@ import {
|
||||
} from '@/components/ui/popover';
|
||||
import type { SidebarTab } from '@/utils/get-sidebar-tabs';
|
||||
|
||||
export interface Option extends SidebarTab {
|
||||
export interface SidebarTabWithProps extends SidebarTab {
|
||||
props?: ComponentProps<'a'>;
|
||||
}
|
||||
|
||||
export function RootToggle({
|
||||
export function SidebarTabTrigger({
|
||||
options,
|
||||
placeholder,
|
||||
...props
|
||||
}: {
|
||||
placeholder?: ReactNode;
|
||||
options: Option[];
|
||||
options: SidebarTabWithProps[];
|
||||
} & ComponentProps<'button'>) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { closeOnRedirect } = useSidebar();
|
||||
Reference in New Issue
Block a user