fumadocs-ui 15.6.5 → 15.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/css/preset.css CHANGED
@@ -10,7 +10,12 @@
10
10
  --color-fd-success: oklch(72.3% 0.219 149.579);
11
11
  }
12
12
 
13
+ [dir='rtl'] {
14
+ --fd-sidebar-mobile-offset: -100%;
15
+ }
16
+
13
17
  @theme {
18
+ --fd-sidebar-mobile-offset: 100%;
14
19
  --spacing-fd-container: 1400px;
15
20
  --fd-page-width: 1200px;
16
21
  --fd-sidebar-width: 0px;
@@ -54,6 +59,18 @@
54
59
  --animate-fd-exitToLeft: fd-exitToLeft 250ms ease;
55
60
  --animate-fd-exitToRight: fd-exitToRight 250ms ease;
56
61
 
62
+ @keyframes fd-sidebar-in {
63
+ from {
64
+ transform: translateX(var(--fd-sidebar-mobile-offset));
65
+ }
66
+ }
67
+
68
+ @keyframes fd-sidebar-out {
69
+ to {
70
+ transform: translateX(var(--fd-sidebar-mobile-offset));
71
+ }
72
+ }
73
+
57
74
  @keyframes fd-collapsible-down {
58
75
  from {
59
76
  height: 0;
@@ -190,18 +207,6 @@
190
207
  }
191
208
  }
192
209
 
193
- @keyframes fd-sidebar-in {
194
- from {
195
- transform: translateX(-100%);
196
- }
197
- }
198
-
199
- @keyframes fd-sidebar-out {
200
- to {
201
- transform: translateX(-100%);
202
- }
203
- }
204
-
205
210
  @keyframes fd-nav-menu-in {
206
211
  from {
207
212
  opacity: 0;
package/css/shiki.css CHANGED
@@ -23,19 +23,22 @@
23
23
  }
24
24
 
25
25
  &[data-line-numbers] code .twoslash-meta-line {
26
- @apply ml-7;
26
+ padding-left: calc(var(--padding-left) + 7 * var(--spacing));
27
27
  }
28
28
 
29
29
  &[data-line-numbers] code .line {
30
- width: calc(100% - 7 * var(--spacing));
31
30
  counter-increment: line;
32
- padding-left: calc(var(--padding-left) - var(--spacing));
33
- @apply ml-7;
31
+ padding-left: calc(var(--padding-left) + 7 * var(--spacing));
34
32
 
35
33
  &::after {
36
34
  position: absolute;
37
35
  content: counter(line);
38
- @apply top-0 -left-5 text-fd-muted-foreground/60;
36
+ color: color-mix(
37
+ in oklab,
38
+ var(--fd-counter-color, var(--color-fd-muted-foreground)) 60%,
39
+ transparent
40
+ );
41
+ @apply top-0 left-4;
39
42
  }
40
43
  }
41
44
 
@@ -46,6 +49,7 @@
46
49
 
47
50
  code .diff.remove {
48
51
  opacity: 0.7;
52
+ --fd-counter-color: var(--color-fd-diff-remove-symbol);
49
53
  @apply bg-fd-diff-remove;
50
54
  }
51
55
 
@@ -55,6 +59,7 @@
55
59
  }
56
60
 
57
61
  code .diff.add {
62
+ --fd-counter-color: var(--color-fd-diff-add-symbol);
58
63
  @apply bg-fd-diff-add;
59
64
  }
60
65
 
@@ -63,11 +68,12 @@
63
68
  @apply text-fd-diff-add-symbol;
64
69
  }
65
70
 
66
- .highlighted {
71
+ code .highlighted {
72
+ --fd-counter-color: var(--color-fd-primary);
67
73
  @apply bg-fd-primary/10;
68
74
  }
69
75
 
70
- .highlighted-word {
76
+ code .highlighted-word {
71
77
  padding: 1px;
72
78
  @apply border -my-px border-fd-primary/30 bg-fd-primary/10 rounded-md font-medium;
73
79
  }
@@ -65,7 +65,7 @@ export function SearchDialogList({ items = null, Empty = () => (_jsx("div", { cl
65
65
  onOpenChange(false);
66
66
  };
67
67
  const onKey = useEffectEvent((e) => {
68
- if (!items)
68
+ if (!items || e.isComposing)
69
69
  return;
70
70
  if (e.key === 'ArrowDown' || e.key == 'ArrowUp') {
71
71
  let idx = items.findIndex((item) => item.id === active);
@@ -3,7 +3,7 @@ import { type LinkProps } from 'fumadocs-core/link';
3
3
  import { type ScrollAreaProps } from '@radix-ui/react-scroll-area';
4
4
  import type { CollapsibleContentProps, CollapsibleTriggerProps } from '@radix-ui/react-collapsible';
5
5
  import type { PageTree } from 'fumadocs-core/server';
6
- export interface SidebarProps extends ComponentProps<'aside'> {
6
+ export interface SidebarProps {
7
7
  /**
8
8
  * Open folders by default if their level is lower or equal to a specific level
9
9
  * (Starting from 1)
@@ -18,13 +18,17 @@ export interface SidebarProps extends ComponentProps<'aside'> {
18
18
  */
19
19
  prefetch?: boolean;
20
20
  /**
21
- * Support collapsing the sidebar on desktop mode
22
- *
23
- * @defaultValue true
21
+ * Children to render
22
+ */
23
+ Content: ReactNode;
24
+ /**
25
+ * Alternative children for mobile
24
26
  */
25
- collapsible?: boolean;
27
+ Mobile?: ReactNode;
26
28
  }
27
- export declare function Sidebar({ defaultOpenLevel, prefetch, collapsible, ...props }: SidebarProps): import("react/jsx-runtime").JSX.Element;
29
+ export declare function Sidebar({ defaultOpenLevel, prefetch, Mobile, Content, }: SidebarProps): import("react/jsx-runtime").JSX.Element;
30
+ export declare function SidebarContent(props: ComponentProps<'aside'>): import("react/jsx-runtime").JSX.Element;
31
+ export declare function SidebarContentMobile({ className, children, ...props }: ComponentProps<'aside'>): import("react/jsx-runtime").JSX.Element;
28
32
  export declare function SidebarHeader(props: ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
29
33
  export declare function SidebarFooter(props: ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
30
34
  export declare function SidebarViewport(props: ScrollAreaProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/layout/sidebar.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,EAAE,EAEP,KAAK,SAAS,EAKf,MAAM,OAAO,CAAC;AACf,OAAa,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAU1D,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,KAAK,EACV,uBAAuB,EACvB,uBAAuB,EACxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAKrD,MAAM,WAAW,YAAa,SAAQ,cAAc,CAAC,OAAO,CAAC;IAC3D;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AA2BD,wBAAgB,OAAO,CAAC,EACtB,gBAAoB,EACpB,QAAe,EACf,WAAkB,EAClB,GAAG,KAAK,EACT,EAAE,YAAY,2CA+Gd;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,2CASzD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,2CASzD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,2CAcrD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,2CAkB1D;AAED,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,SAAS,GAAG;IACb,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,2CAsBA;AAED,wBAAgB,aAAa,CAAC,EAC5B,WAAmB,EACnB,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,2CAgBA;AAED,wBAAgB,oBAAoB,CAAC,EACnC,SAAS,EACT,GAAG,KAAK,EACT,EAAE,uBAAuB,2CAqBzB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,2CAsCjD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,uBAAuB,2CAqBlE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,CAAC,QAAQ,CAAC,2CAgBrE;AAgBD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAA;KAAE,CAAC,CAAC;IAClC,MAAM,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC1E,SAAS,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAA;KAAE,CAAC,CAAC;CAC7C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACzC,2CAuDA"}
1
+ {"version":3,"file":"sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/layout/sidebar.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,EAAE,EAEP,KAAK,SAAS,EAKf,MAAM,OAAO,CAAC;AACf,OAAa,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAU1D,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAGnE,OAAO,KAAK,EACV,uBAAuB,EACvB,uBAAuB,EACxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAKrD,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,OAAO,EAAE,SAAS,CAAC;IAEnB;;OAEG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AA2BD,wBAAgB,OAAO,CAAC,EACtB,gBAAoB,EACpB,QAAe,EACf,MAAM,EACN,OAAO,GACR,EAAE,YAAY,2CAed;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,2CAoE5D;AAED,wBAAgB,oBAAoB,CAAC,EACnC,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,OAAO,CAAC,2CA+BzB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,2CASzD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,2CASzD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,2CAiBrD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,CAAC,GAAG,CAAC,2CAY1D;AAED,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,SAAS,GAAG;IACb,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,2CAiBA;AAED,wBAAgB,aAAa,CAAC,EAC5B,WAAmB,EACnB,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,2CAgBA;AAED,wBAAgB,oBAAoB,CAAC,EACnC,SAAS,EACT,GAAG,KAAK,EACT,EAAE,uBAAuB,2CAezB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,2CAiCjD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,uBAAuB,2CAoClE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,CAAC,QAAQ,CAAC,2CAgBrE;AAgBD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAA;KAAE,CAAC,CAAC;IAClC,MAAM,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC1E,SAAS,EAAE,EAAE,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC,SAAS,CAAA;KAAE,CAAC,CAAC;CAC7C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACzC,2CAuDA"}
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { ChevronDown, ExternalLink } from '../../icons.js';
4
4
  import { usePathname } from 'fumadocs-core/framework';
5
5
  import { createContext, Fragment, useContext, useMemo, useRef, useState, } from 'react';
@@ -14,7 +14,7 @@ import { cva } from 'class-variance-authority';
14
14
  import { useTreeContext, useTreePath } from '../../contexts/tree.js';
15
15
  import { useMediaQuery } from 'fumadocs-core/utils/use-media-query';
16
16
  import { Presence } from '@radix-ui/react-presence';
17
- const itemVariants = cva('relative flex flex-row items-center gap-2 rounded-xl p-2 text-start text-fd-muted-foreground [overflow-wrap:anywhere] [&_svg]:size-4 [&_svg]:shrink-0', {
17
+ const itemVariants = cva('relative flex flex-row items-center gap-2 rounded-xl p-2 ps-(--sidebar-item-offset) text-start text-fd-muted-foreground [overflow-wrap:anywhere] [&_svg]:size-4 [&_svg]:shrink-0', {
18
18
  variants: {
19
19
  active: {
20
20
  true: 'bg-fd-primary/10 text-fd-primary',
@@ -24,8 +24,8 @@ const itemVariants = cva('relative flex flex-row items-center gap-2 rounded-xl p
24
24
  });
25
25
  const Context = createContext(null);
26
26
  const FolderContext = createContext(null);
27
- export function Sidebar({ defaultOpenLevel = 0, prefetch = true, collapsible = true, ...props }) {
28
- const { open, setOpen, collapsed } = useSidebar();
27
+ export function Sidebar({ defaultOpenLevel = 0, prefetch = true, Mobile, Content, }) {
28
+ const isMobile = useMediaQuery('(width < 768px)') ?? false;
29
29
  const context = useMemo(() => {
30
30
  return {
31
31
  defaultOpenLevel,
@@ -33,45 +33,42 @@ export function Sidebar({ defaultOpenLevel = 0, prefetch = true, collapsible = t
33
33
  level: 1,
34
34
  };
35
35
  }, [defaultOpenLevel, prefetch]);
36
+ return (_jsx(Context.Provider, { value: context, children: isMobile && Mobile != null ? Mobile : Content }));
37
+ }
38
+ export function SidebarContent(props) {
39
+ const { collapsed } = useSidebar();
36
40
  const [hover, setHover] = useState(false);
37
41
  const timerRef = useRef(0);
38
42
  const closeTimeRef = useRef(0);
39
- // md
40
- const isMobile = useMediaQuery('(width < 768px)') ?? false;
41
43
  useOnChange(collapsed, () => {
42
44
  setHover(false);
43
45
  closeTimeRef.current = Date.now() + 150;
44
46
  });
45
- if (isMobile) {
46
- const state = open ? 'open' : 'closed';
47
- return (_jsxs(Context.Provider, { value: context, children: [_jsx(Presence, { present: open, children: _jsx("div", { "data-state": state, className: "fixed z-40 inset-0 backdrop-blur-xs data-[state=open]:animate-fd-fade-in data-[state=closed]:animate-fd-fade-out", onClick: () => setOpen(false) }) }), _jsx(Presence, { present: open, children: ({ present }) => (_jsx("aside", { id: "nd-sidebar-mobile", ...props, "data-state": state, className: cn('fixed text-[15px] flex flex-col shadow-lg rounded-2xl border start-2 inset-y-2 w-[85%] max-w-[380px] z-40 bg-fd-background data-[state=open]:animate-fd-sidebar-in data-[state=closed]:animate-fd-sidebar-out', !present && 'invisible', props.className), children: props.children })) })] }));
48
- }
49
47
  return (_jsx("aside", { id: "nd-sidebar", ...props, "data-collapsed": collapsed, className: cn('fixed start-0 flex flex-col items-end top-(--fd-sidebar-top) bottom-(--fd-sidebar-margin) z-20 bg-fd-card text-sm border-e max-md:hidden *:w-(--fd-sidebar-width)', collapsed && [
50
- 'rounded-xl border',
51
- hover
52
- ? 'z-50 translate-x-2 shadow-lg'
53
- : 'opacity-0 -translate-x-(--fd-sidebar-offset) rtl:translate-x-(--fd-sidebar-offset)',
48
+ 'rounded-xl border translate-x-(--fd-sidebar-offset) rtl:-translate-x-(--fd-sidebar-offset)',
49
+ hover ? 'z-50 shadow-lg' : 'opacity-0',
54
50
  ], props.className), style: {
55
51
  transition: ['top', 'opacity', 'translate', 'width']
56
52
  .map((v) => `${v} ease 250ms`)
57
53
  .join(', '),
58
54
  ...props.style,
59
- '--fd-sidebar-offset': 'calc(100% - 16px)',
55
+ '--fd-sidebar-offset': hover
56
+ ? 'calc(var(--spacing) * 2)'
57
+ : 'calc(16px - 100%)',
60
58
  '--fd-sidebar-margin': collapsed ? '0.5rem' : '0px',
59
+ '--fd-sidebar-top': `calc(var(--fd-banner-height) + var(--fd-nav-height) + var(--fd-sidebar-margin))`,
61
60
  width: collapsed
62
61
  ? 'var(--fd-sidebar-width)'
63
62
  : 'calc(var(--fd-sidebar-width) + var(--fd-layout-offset))',
64
- '--fd-sidebar-top': `calc(var(--fd-banner-height) + var(--fd-nav-height) + var(--fd-sidebar-margin))`,
65
63
  }, onPointerEnter: (e) => {
66
- if (!collapsible ||
67
- !collapsed ||
64
+ if (!collapsed ||
68
65
  e.pointerType === 'touch' ||
69
66
  closeTimeRef.current > Date.now())
70
67
  return;
71
68
  window.clearTimeout(timerRef.current);
72
69
  setHover(true);
73
70
  }, onPointerLeave: (e) => {
74
- if (!collapsible || !collapsed || e.pointerType === 'touch')
71
+ if (!collapsed || e.pointerType === 'touch')
75
72
  return;
76
73
  window.clearTimeout(timerRef.current);
77
74
  timerRef.current = window.setTimeout(() => {
@@ -80,7 +77,12 @@ export function Sidebar({ defaultOpenLevel = 0, prefetch = true, collapsible = t
80
77
  }, Math.min(e.clientX, document.body.clientWidth - e.clientX) > 100
81
78
  ? 0
82
79
  : 500);
83
- }, children: _jsx(Context.Provider, { value: context, children: props.children }) }));
80
+ }, children: props.children }));
81
+ }
82
+ export function SidebarContentMobile({ className, children, ...props }) {
83
+ const { open, setOpen } = useSidebar();
84
+ const state = open ? 'open' : 'closed';
85
+ return (_jsxs(_Fragment, { children: [_jsx(Presence, { present: open, children: _jsx("div", { "data-state": state, className: "fixed z-40 inset-0 backdrop-blur-xs data-[state=open]:animate-fd-fade-in data-[state=closed]:animate-fd-fade-out", onClick: () => setOpen(false) }) }), _jsx(Presence, { present: open, children: ({ present }) => (_jsx("aside", { id: "nd-sidebar-mobile", ...props, "data-state": state, className: cn('fixed text-[15px] flex flex-col shadow-lg border-s end-0 inset-y-0 w-[85%] max-w-[380px] z-40 bg-fd-background data-[state=open]:animate-fd-sidebar-in data-[state=closed]:animate-fd-sidebar-out', !present && 'invisible', className), children: children })) })] }));
84
86
  }
85
87
  export function SidebarHeader(props) {
86
88
  return (_jsx("div", { ...props, className: cn('flex flex-col gap-3 p-4 pb-2', props.className), children: props.children }));
@@ -90,24 +92,18 @@ export function SidebarFooter(props) {
90
92
  }
91
93
  export function SidebarViewport(props) {
92
94
  return (_jsx(ScrollArea, { ...props, className: cn('h-full', props.className), children: _jsx(ScrollViewport, { className: "p-4", style: {
95
+ '--sidebar-item-offset': 'calc(var(--spacing) * 2)',
93
96
  maskImage: 'linear-gradient(to bottom, transparent, white 12px, white calc(100% - 12px), transparent)',
94
97
  }, children: props.children }) }));
95
98
  }
96
99
  export function SidebarSeparator(props) {
97
- const { level } = useInternalContext();
98
- return (_jsx("p", { ...props, className: cn('inline-flex items-center gap-2 mb-1.5 px-2 empty:mb-0 [&_svg]:size-4 [&_svg]:shrink-0', props.className), style: {
99
- paddingInlineStart: getOffset(level),
100
- ...props.style,
101
- }, children: props.children }));
100
+ return (_jsx("p", { ...props, className: cn('inline-flex items-center gap-2 mb-1.5 px-2 ps-(--sidebar-item-offset) empty:mb-0 [&_svg]:size-4 [&_svg]:shrink-0', props.className), children: props.children }));
102
101
  }
103
102
  export function SidebarItem({ icon, ...props }) {
104
103
  const pathname = usePathname();
105
104
  const active = props.href !== undefined && isActive(props.href, pathname, false);
106
- const { prefetch, level } = useInternalContext();
107
- return (_jsxs(Link, { ...props, "data-active": active, className: cn(itemVariants({ active }), props.className), prefetch: prefetch, style: {
108
- paddingInlineStart: getOffset(level),
109
- ...props.style,
110
- }, children: [_jsx(Border, { level: level, active: active }), icon ?? (props.external ? _jsx(ExternalLink, {}) : null), props.children] }));
105
+ const { prefetch } = useInternalContext();
106
+ return (_jsxs(Link, { ...props, "data-active": active, className: cn(itemVariants({ active }), props.className), prefetch: prefetch, children: [icon ?? (props.external ? _jsx(ExternalLink, {}) : null), props.children] }));
111
107
  }
112
108
  export function SidebarFolder({ defaultOpen = false, ...props }) {
113
109
  const [open, setOpen] = useState(defaultOpen);
@@ -118,16 +114,12 @@ export function SidebarFolder({ defaultOpen = false, ...props }) {
118
114
  return (_jsx(Collapsible, { open: open, onOpenChange: setOpen, ...props, children: _jsx(FolderContext.Provider, { value: useMemo(() => ({ open, setOpen }), [open]), children: props.children }) }));
119
115
  }
120
116
  export function SidebarFolderTrigger({ className, ...props }) {
121
- const { level } = useInternalContext();
122
117
  const { open } = useFolderContext();
123
- return (_jsxs(CollapsibleTrigger, { className: cn(itemVariants({ active: false }), 'w-full', className), ...props, style: {
124
- paddingInlineStart: getOffset(level),
125
- ...props.style,
126
- }, children: [_jsx(Border, { level: level }), props.children, _jsx(ChevronDown, { "data-icon": true, className: cn('ms-auto transition-transform', !open && '-rotate-90') })] }));
118
+ return (_jsxs(CollapsibleTrigger, { className: cn(itemVariants({ active: false }), 'w-full', className), ...props, children: [props.children, _jsx(ChevronDown, { "data-icon": true, className: cn('ms-auto transition-transform', !open && '-rotate-90') })] }));
127
119
  }
128
120
  export function SidebarFolderLink(props) {
129
121
  const { open, setOpen } = useFolderContext();
130
- const { prefetch, level } = useInternalContext();
122
+ const { prefetch } = useInternalContext();
131
123
  const pathname = usePathname();
132
124
  const active = props.href !== undefined && isActive(props.href, pathname, false);
133
125
  return (_jsxs(Link, { ...props, "data-active": active, className: cn(itemVariants({ active }), 'w-full', props.className), onClick: (e) => {
@@ -139,17 +131,19 @@ export function SidebarFolderLink(props) {
139
131
  else {
140
132
  setOpen(active ? !open : true);
141
133
  }
142
- }, prefetch: prefetch, style: {
143
- paddingInlineStart: getOffset(level),
144
- ...props.style,
145
- }, children: [_jsx(Border, { level: level, active: active }), props.children, _jsx(ChevronDown, { "data-icon": true, className: cn('ms-auto transition-transform', !open && '-rotate-90') })] }));
134
+ }, prefetch: prefetch, children: [props.children, _jsx(ChevronDown, { "data-icon": true, className: cn('ms-auto transition-transform', !open && '-rotate-90') })] }));
146
135
  }
147
136
  export function SidebarFolderContent(props) {
148
137
  const ctx = useInternalContext();
149
- return (_jsx(CollapsibleContent, { ...props, className: cn('relative', props.className), children: _jsxs(Context.Provider, { value: useMemo(() => ({
150
- ...ctx,
151
- level: ctx.level + 1,
152
- }), [ctx]), children: [ctx.level === 1 && (_jsx("div", { className: "absolute w-px inset-y-1 bg-fd-border start-2.5" })), props.children] }) }));
138
+ const level = ctx.level + 1;
139
+ return (_jsxs(CollapsibleContent, { ...props, className: cn('relative', level === 2 &&
140
+ "**:data-[active=true]:before:content-[''] **:data-[active=true]:before:bg-fd-primary **:data-[active=true]:before:absolute **:data-[active=true]:before:w-px **:data-[active=true]:before:inset-y-2.5 **:data-[active=true]:before:start-2.5", props.className), style: {
141
+ '--sidebar-item-offset': `calc(var(--spacing) * ${level > 1 ? level * 3 : 2})`,
142
+ ...props.style,
143
+ }, children: [level === 2 && (_jsx("div", { className: "absolute w-px inset-y-1 bg-fd-border start-2.5" })), _jsx(Context.Provider, { value: useMemo(() => ({
144
+ ...ctx,
145
+ level,
146
+ }), [ctx, level]), children: props.children })] }));
153
147
  }
154
148
  export function SidebarCollapseTrigger(props) {
155
149
  const { collapsed, setCollapsed } = useSidebar();
@@ -202,11 +196,3 @@ function PageTreeFolder({ item, ...props }) {
202
196
  const path = useTreePath();
203
197
  return (_jsxs(SidebarFolder, { defaultOpen: (item.defaultOpen ?? defaultOpenLevel >= level) || path.includes(item), children: [item.index ? (_jsxs(SidebarFolderLink, { href: item.index.url, external: item.index.external, ...props, children: [item.icon, item.name] })) : (_jsxs(SidebarFolderTrigger, { ...props, children: [item.icon, item.name] })), _jsx(SidebarFolderContent, { children: props.children })] }));
204
198
  }
205
- function getOffset(level) {
206
- return `calc(var(--spacing) * ${level > 1 ? level * 3 : 2})`;
207
- }
208
- function Border({ level, active }) {
209
- if (level <= 1)
210
- return null;
211
- return (_jsx("div", { className: cn('absolute w-px inset-y-3 z-2 start-2.5 md:inset-y-2', active && 'bg-fd-primary') }));
212
- }
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { Info as InfoIcon } from '../icons.js';
3
+ import { Info as InfoIcon, Link as LinkIcon } from '../icons.js';
4
4
  import Link from 'fumadocs-core/link';
5
5
  import { cva } from 'class-variance-authority';
6
6
  import { cn } from '../utils/cn.js';
@@ -20,5 +20,5 @@ const code = cva('rounded-md bg-fd-secondary p-1 text-fd-secondary-foreground',
20
20
  export function TypeTable({ type }) {
21
21
  return (_jsx("div", { className: "prose my-6 overflow-auto prose-no-margin", children: _jsxs("table", { className: "whitespace-nowrap text-sm text-fd-muted-foreground", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { className: "w-[45%]", children: "Prop" }), _jsx("th", { className: "w-[30%]", children: "Type" }), _jsx("th", { className: "w-1/4", children: "Default" })] }) }), _jsx("tbody", { children: Object.entries(type).map(([key, value]) => (_jsxs("tr", { children: [_jsx("td", { children: _jsxs("div", { className: field(), children: [_jsxs("code", { className: cn(code({
22
22
  color: value.deprecated ? 'deprecated' : 'primary',
23
- })), children: [key, !value.required && '?'] }), value.description ? _jsx(Info, { children: value.description }) : null] }) }), _jsx("td", { children: _jsxs("div", { className: field(), children: [_jsx("code", { className: code(), children: value.type }), value.typeDescription ? (_jsx(Info, { children: value.typeDescription })) : null, value.typeDescriptionLink ? (_jsx(Link, { href: value.typeDescriptionLink, children: _jsx(InfoIcon, { className: "size-4" }) })) : null] }) }), _jsx("td", { children: value.default ? (_jsx("code", { className: code(), children: value.default })) : ('-') })] }, key))) })] }) }));
23
+ })), children: [key, !value.required && '?'] }), value.description ? _jsx(Info, { children: value.description }) : null] }) }), _jsx("td", { children: _jsxs("div", { className: field(), children: [_jsx("code", { className: code(), children: value.type }), value.typeDescription ? (_jsx(Info, { children: value.typeDescription })) : null, value.typeDescriptionLink ? (_jsx(Link, { href: value.typeDescriptionLink, children: _jsx(LinkIcon, { className: "size-4 text-fd-muted-foreground" }) })) : null] }) }), _jsx("td", { children: value.default ? (_jsx("code", { className: code(), children: value.default })) : ('-') })] }, key))) })] }) }));
24
24
  }
@@ -4,7 +4,7 @@ import type { PageTree } from 'fumadocs-core/server';
4
4
  import type { ReactNode } from 'react';
5
5
  import type { Option } from '../../components/layout/root-toggle.js';
6
6
  import { type GetSidebarTabsOptions } from '../../utils/get-sidebar-tabs.js';
7
- export interface SidebarOptions extends SidebarProps {
7
+ export interface SidebarOptions extends Pick<SidebarProps, 'defaultOpenLevel' | 'prefetch'> {
8
8
  components?: Partial<SidebarComponents>;
9
9
  /**
10
10
  * Root Toggle options
@@ -12,6 +12,12 @@ export interface SidebarOptions extends SidebarProps {
12
12
  tabs?: Option[] | GetSidebarTabsOptions | false;
13
13
  banner?: ReactNode;
14
14
  footer?: ReactNode;
15
+ /**
16
+ * Support collapsing the sidebar on desktop mode
17
+ *
18
+ * @defaultValue true
19
+ */
20
+ collapsible?: boolean;
15
21
  }
16
22
  export declare function SidebarLinkItem({ item, ...props }: {
17
23
  item: LinkItemType;
@@ -1 +1 @@
1
- {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/layouts/docs/shared.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EACL,KAAK,iBAAiB,EAMtB,KAAK,YAAY,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,cAAe,SAAQ,YAAY;IAClD,UAAU,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAExC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,qBAAqB,GAAG,KAAK,CAAC;IAEhD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,GAAG,KAAK,EACT,EAAE;IACD,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,2CAmCA;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,EAC/B,IAAI,EAAE,QAAQ,CAAC,IAAI,wBASpB"}
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/layouts/docs/shared.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EACL,KAAK,iBAAiB,EAMtB,KAAK,YAAY,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,cACf,SAAQ,IAAI,CAAC,YAAY,EAAE,kBAAkB,GAAG,UAAU,CAAC;IAC3D,UAAU,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAExC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,qBAAqB,GAAG,KAAK,CAAC;IAEhD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,GAAG,KAAK,EACT,EAAE;IACD,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,2CAmCA;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,EAC/B,IAAI,EAAE,QAAQ,CAAC,IAAI,wBASpB"}
@@ -1,6 +1,6 @@
1
1
  import { type ComponentProps } from 'react';
2
2
  export declare function Navbar(props: ComponentProps<'header'>): import("react/jsx-runtime").JSX.Element;
3
3
  export declare function LayoutBody(props: ComponentProps<'main'>): import("react/jsx-runtime").JSX.Element;
4
- export declare function NavbarSidebarTrigger({ className, ...props }: ComponentProps<'button'>): import("react/jsx-runtime").JSX.Element;
5
- export declare function CollapsibleControl(): import("react/jsx-runtime").JSX.Element | undefined;
4
+ export declare function SidebarTrigger({ children, ...props }: ComponentProps<'button'>): import("react/jsx-runtime").JSX.Element;
5
+ export declare function CollapsibleControl(): import("react/jsx-runtime").JSX.Element;
6
6
  //# sourceMappingURL=docs-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"docs-client.d.ts","sourceRoot":"","sources":["../../src/layouts/docs-client.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAQ5C,wBAAgB,MAAM,CAAC,KAAK,EAAE,cAAc,CAAC,QAAQ,CAAC,2CAgBrD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,2CAqBvD;AAED,wBAAgB,oBAAoB,CAAC,EACnC,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,QAAQ,CAAC,2CAmB1B;AAED,wBAAgB,kBAAkB,wDAyBjC"}
1
+ {"version":3,"file":"docs-client.d.ts","sourceRoot":"","sources":["../../src/layouts/docs-client.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAQ5C,wBAAgB,MAAM,CAAC,KAAK,EAAE,cAAc,CAAC,QAAQ,CAAC,2CAgBrD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,2CAqBvD;AAED,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,QAAQ,CAAC,2CAY1B;AAED,wBAAgB,kBAAkB,4CA2BjC"}
@@ -9,7 +9,7 @@ import { SidebarCollapseTrigger } from '../components/layout/sidebar.js';
9
9
  import { SearchToggle } from '../components/layout/search-toggle.js';
10
10
  export function Navbar(props) {
11
11
  const { isTransparent } = useNav();
12
- return (_jsx("header", { id: "nd-subnav", ...props, className: cn('fixed top-(--fd-banner-height) inset-x-0 z-30 flex items-center px-4 border-b transition-colors backdrop-blur-sm', !isTransparent && 'bg-fd-background/80', props.className), children: props.children }));
12
+ return (_jsx("header", { id: "nd-subnav", ...props, className: cn('fixed top-(--fd-banner-height) inset-x-0 z-30 flex items-center ps-4 pe-2.5 border-b transition-colors backdrop-blur-sm', !isTransparent && 'bg-fd-background/80', props.className), children: props.children }));
13
13
  }
14
14
  export function LayoutBody(props) {
15
15
  const { collapsed } = useSidebar();
@@ -20,19 +20,13 @@ export function LayoutBody(props) {
20
20
  : 'var(--fd-sidebar-width)',
21
21
  }, children: props.children }));
22
22
  }
23
- export function NavbarSidebarTrigger({ className, ...props }) {
23
+ export function SidebarTrigger({ children, ...props }) {
24
24
  const { setOpen } = useSidebar();
25
- return (_jsx("button", { ...props, "aria-label": "Open Sidebar", className: cn(buttonVariants({
26
- color: 'ghost',
27
- size: 'icon-sm',
28
- className,
29
- })), onClick: () => setOpen((prev) => !prev), children: _jsx(SidebarIcon, {}) }));
25
+ return (_jsx("button", { ...props, "aria-label": "Open Sidebar", onClick: () => setOpen((prev) => !prev), children: children }));
30
26
  }
31
27
  export function CollapsibleControl() {
32
28
  const { collapsed } = useSidebar();
33
- if (!collapsed)
34
- return;
35
- return (_jsxs("div", { className: "fixed flex shadow-lg animate-fd-fade-in rounded-xl p-0.5 border bg-fd-muted text-fd-muted-foreground z-10 xl:start-4 max-xl:end-4", style: {
29
+ return (_jsxs("div", { className: cn('fixed flex shadow-lg transition-opacity rounded-xl p-0.5 border bg-fd-muted text-fd-muted-foreground z-10 max-md:hidden xl:start-4 max-xl:end-4', !collapsed && 'pointer-events-none opacity-0'), style: {
36
30
  top: 'calc(var(--fd-banner-height) + var(--fd-tocnav-height) + var(--spacing) * 4)',
37
31
  }, children: [_jsx(SidebarCollapseTrigger, { className: cn(buttonVariants({
38
32
  color: 'ghost',
@@ -1,12 +1,12 @@
1
1
  import type { PageTree } from 'fumadocs-core/server';
2
- import { type HTMLAttributes, type ReactNode } from 'react';
2
+ import { type ComponentProps, type HTMLAttributes, type ReactNode } from 'react';
3
3
  import { type LinkItemType } from '../layouts/links.js';
4
4
  import { type BaseLayoutProps } from './shared.js';
5
- import { CollapsibleControl, Navbar, NavbarSidebarTrigger } from '../layouts/docs-client.js';
5
+ import { CollapsibleControl, Navbar, SidebarTrigger } from '../layouts/docs-client.js';
6
6
  import { type SidebarOptions } from '../layouts/docs/shared.js';
7
7
  export interface DocsLayoutProps extends BaseLayoutProps {
8
8
  tree: PageTree.Root;
9
- sidebar?: Partial<SidebarOptions> & {
9
+ sidebar?: SidebarOptions & ComponentProps<'aside'> & {
10
10
  enabled?: boolean;
11
11
  component?: ReactNode;
12
12
  };
@@ -15,6 +15,6 @@ export interface DocsLayoutProps extends BaseLayoutProps {
15
15
  */
16
16
  containerProps?: HTMLAttributes<HTMLDivElement>;
17
17
  }
18
- export declare function DocsLayout({ nav: { transparentMode, ...nav }, sidebar: { tabs: sidebarTabs, footer: sidebarFooter, banner: sidebarBanner, enabled: sidebarEnabled, collapsible: sidebarCollapsible, component: sidebarComponent, components: sidebarComponents, ...sidebarProps }, searchToggle, disableThemeSwitch, themeSwitch, i18n, children, ...props }: DocsLayoutProps): import("react/jsx-runtime").JSX.Element;
19
- export { CollapsibleControl, Navbar, NavbarSidebarTrigger, type LinkItemType };
18
+ export declare function DocsLayout({ nav: { transparentMode, ...nav }, sidebar: { tabs: sidebarTabs, enabled: sidebarEnabled, ...sidebarProps }, searchToggle, disableThemeSwitch, themeSwitch, i18n, children, ...props }: DocsLayoutProps): import("react/jsx-runtime").JSX.Element;
19
+ export { CollapsibleControl, Navbar, SidebarTrigger, type LinkItemType };
20
20
  //# sourceMappingURL=docs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/layouts/docs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAW,MAAM,OAAO,CAAC;AAYrE,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAElE,OAAO,EAAE,KAAK,eAAe,EAAY,MAAM,UAAU,CAAC;AAK1D,OAAO,EACL,kBAAkB,EAElB,MAAM,EACN,oBAAoB,EACrB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAS/B,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IAEpB,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG;QAClC,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,SAAS,CAAC,EAAE,SAAS,CAAC;KACvB,CAAC;IAEF;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;CACjD;AAED,wBAAgB,UAAU,CAAC,EACzB,GAAG,EAAE,EAAE,eAAe,EAAE,GAAG,GAAG,EAAO,EACrC,OAAO,EAAE,EACP,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,cAAqB,EAC9B,WAAW,EAAE,kBAAyB,EACtC,SAAS,EAAE,gBAAgB,EAC3B,UAAU,EAAE,iBAAiB,EAC7B,GAAG,YAAY,EACX,EACN,YAAiB,EACjB,kBAA0B,EAC1B,WAA8C,EAC9C,IAAY,EACZ,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,eAAe,2CAuIjB;AAED,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,oBAAoB,EAAE,KAAK,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/layouts/docs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAcf,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,KAAK,eAAe,EAAY,MAAM,UAAU,CAAC;AAK1D,OAAO,EACL,kBAAkB,EAElB,MAAM,EACN,cAAc,EACf,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAS/B,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IAEpB,OAAO,CAAC,EAAE,cAAc,GACtB,cAAc,CAAC,OAAO,CAAC,GAAG;QACxB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,SAAS,CAAC,EAAE,SAAS,CAAC;KACvB,CAAC;IAEJ;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;CACjD;AAED,wBAAgB,UAAU,CAAC,EACzB,GAAG,EAAE,EAAE,eAAe,EAAE,GAAG,GAAG,EAAO,EACrC,OAAO,EAAE,EACP,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,cAAqB,EAC9B,GAAG,YAAY,EACX,EACN,YAAiB,EACjB,kBAA0B,EAC1B,WAA8C,EAC9C,IAAY,EACZ,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,eAAe,2CA4NjB;AAED,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,CAAC"}
@@ -1,14 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useMemo } from 'react';
2
+ import { useMemo, } from 'react';
3
3
  import { Languages, Sidebar as SidebarIcon } from '../icons.js';
4
4
  import { cn } from '../utils/cn.js';
5
5
  import { buttonVariants } from '../components/ui/button.js';
6
- import { Sidebar, SidebarCollapseTrigger, SidebarFooter, SidebarHeader, SidebarPageTree, SidebarViewport, } from '../components/layout/sidebar.js';
7
- import { BaseLinkItem } from '../layouts/links.js';
6
+ import { Sidebar, SidebarCollapseTrigger, SidebarContent, SidebarContentMobile, SidebarFooter, SidebarHeader, SidebarPageTree, SidebarViewport, } from '../components/layout/sidebar.js';
7
+ import { BaseLinkItem, } from '../layouts/links.js';
8
8
  import { RootToggle } from '../components/layout/root-toggle.js';
9
9
  import { getLinks } from './shared.js';
10
10
  import { LanguageToggle, LanguageToggleText, } from '../components/layout/language-toggle.js';
11
- import { CollapsibleControl, LayoutBody, Navbar, NavbarSidebarTrigger, } from '../layouts/docs-client.js';
11
+ import { CollapsibleControl, LayoutBody, Navbar, SidebarTrigger, } from '../layouts/docs-client.js';
12
12
  import { TreeContextProvider } from '../contexts/tree.js';
13
13
  import { ThemeToggle } from '../components/layout/theme-toggle.js';
14
14
  import { getSidebarTabsFromOptions, SidebarLinkItem, } from '../layouts/docs/shared.js';
@@ -16,26 +16,46 @@ import { NavProvider } from '../contexts/layout.js';
16
16
  import Link from 'fumadocs-core/link';
17
17
  import { LargeSearchToggle, SearchToggle, } from '../components/layout/search-toggle.js';
18
18
  import { HideIfEmpty } from 'fumadocs-core/hide-if-empty';
19
- export function DocsLayout({ nav: { transparentMode, ...nav } = {}, sidebar: { tabs: sidebarTabs, footer: sidebarFooter, banner: sidebarBanner, enabled: sidebarEnabled = true, collapsible: sidebarCollapsible = true, component: sidebarComponent, components: sidebarComponents, ...sidebarProps } = {}, searchToggle = {}, disableThemeSwitch = false, themeSwitch = { enabled: !disableThemeSwitch }, i18n = false, children, ...props }) {
19
+ export function DocsLayout({ nav: { transparentMode, ...nav } = {}, sidebar: { tabs: sidebarTabs, enabled: sidebarEnabled = true, ...sidebarProps } = {}, searchToggle = {}, disableThemeSwitch = false, themeSwitch = { enabled: !disableThemeSwitch }, i18n = false, children, ...props }) {
20
20
  const tabs = useMemo(() => getSidebarTabsFromOptions(sidebarTabs, props.tree) ?? [], [sidebarTabs, props.tree]);
21
21
  const links = getLinks(props.links ?? [], props.githubUrl);
22
22
  const variables = cn(sidebarEnabled &&
23
23
  'md:[--fd-sidebar-width:268px] lg:[--fd-sidebar-width:286px]', 'xl:[--fd-toc-width:286px]', !nav.component && nav.enabled !== false
24
24
  ? '[--fd-nav-height:56px] md:[--fd-nav-height:0px]'
25
25
  : undefined);
26
- const sidebar = sidebarComponent ?? (_jsxs(_Fragment, { children: [sidebarCollapsible ? _jsx(CollapsibleControl, {}) : null, _jsxs(Sidebar, { ...sidebarProps, collapsible: sidebarCollapsible, children: [_jsx(HideIfEmpty, { children: _jsxs(SidebarHeader, { className: "data-[empty=true]:hidden", children: [_jsxs("div", { className: "flex max-md:hidden", children: [_jsx(Link, { href: nav.url ?? '/', className: "inline-flex text-[15px] items-center gap-2.5 font-medium me-auto", children: nav.title }), nav.children, sidebarCollapsible && (_jsx(SidebarCollapseTrigger, { className: cn(buttonVariants({
27
- color: 'ghost',
28
- size: 'icon-sm',
29
- className: 'mb-auto text-fd-muted-foreground max-md:hidden',
30
- })), children: _jsx(SidebarIcon, {}) }))] }), searchToggle.enabled !== false &&
31
- (searchToggle.components?.lg ?? (_jsx(LargeSearchToggle, { hideIfDisabled: true, className: "max-md:hidden" }))), tabs.length > 0 && _jsx(RootToggle, { options: tabs }), sidebarBanner] }) }), _jsxs(SidebarViewport, { children: [links
32
- .filter((v) => v.type !== 'icon')
33
- .map((item, i, list) => (_jsx(SidebarLinkItem, { item: item, className: cn(i === list.length - 1 && 'mb-4') }, i))), _jsx(SidebarPageTree, { components: sidebarComponents })] }), _jsx(HideIfEmpty, { children: _jsxs(SidebarFooter, { className: "data-[empty=true]:hidden", children: [_jsxs("div", { className: "flex items-center justify-end empty:hidden", children: [links
34
- .filter((item) => item.type === 'icon')
35
- .map((item, i, arr) => (_jsx(BaseLinkItem, { item: item, className: cn(buttonVariants({ size: 'icon', color: 'ghost' }), 'text-fd-muted-foreground md:[&_svg]:size-4.5', i === arr.length - 1 && 'me-auto'), "aria-label": item.label, children: item.icon }, i))), i18n ? (_jsxs(LanguageToggle, { className: "me-1.5", children: [_jsx(Languages, { className: "size-4.5" }), _jsx(LanguageToggleText, { className: "md:hidden" })] })) : null, themeSwitch.enabled !== false &&
36
- (themeSwitch.component ?? (_jsx(ThemeToggle, { className: "p-0", mode: themeSwitch.mode })))] }), sidebarFooter] }) })] })] }));
26
+ function sidebar() {
27
+ const { footer, banner, collapsible = true, component, components, defaultOpenLevel, prefetch, ...rest } = sidebarProps;
28
+ if (component)
29
+ return component;
30
+ const iconLinks = links.filter((item) => item.type === 'icon');
31
+ const viewport = (_jsxs(SidebarViewport, { children: [links
32
+ .filter((v) => v.type !== 'icon')
33
+ .map((item, i, list) => (_jsx(SidebarLinkItem, { item: item, className: cn(i === list.length - 1 && 'mb-4') }, i))), _jsx(SidebarPageTree, { components: components })] }));
34
+ const mobile = (_jsxs(SidebarContentMobile, { ...rest, children: [_jsxs(HideIfEmpty, { as: SidebarHeader, children: [_jsxs("div", { className: "flex text-fd-muted-foreground items-center justify-end empty:hidden", children: [iconLinks.map((item, i) => (_jsx(BaseLinkItem, { item: item, className: cn(buttonVariants({
35
+ size: 'icon-sm',
36
+ color: 'ghost',
37
+ className: 'p-2',
38
+ }), i === iconLinks.length - 1 && 'me-auto'), "aria-label": item.label, children: item.icon }, i))), i18n ? (_jsxs(LanguageToggle, { children: [_jsx(Languages, { className: "size-4.5" }), _jsx(LanguageToggleText, {})] })) : null, themeSwitch.enabled !== false &&
39
+ (themeSwitch.component ?? (_jsx(ThemeToggle, { className: "p-0 ms-1.5", mode: themeSwitch.mode }))), _jsx(SidebarTrigger, { className: cn(buttonVariants({
40
+ color: 'ghost',
41
+ size: 'icon-sm',
42
+ className: 'p-2 ms-1.5',
43
+ })), children: _jsx(SidebarIcon, {}) })] }), tabs.length > 0 && _jsx(RootToggle, { options: tabs }), banner] }), viewport, _jsx(SidebarFooter, { className: "empty:hidden", children: footer })] }));
44
+ const content = (_jsxs(SidebarContent, { ...rest, children: [_jsxs(SidebarHeader, { children: [_jsxs("div", { className: "flex", children: [_jsx(Link, { href: nav.url ?? '/', className: "inline-flex text-[15px] items-center gap-2.5 font-medium me-auto", children: nav.title }), nav.children, collapsible && (_jsx(SidebarCollapseTrigger, { className: cn(buttonVariants({
45
+ color: 'ghost',
46
+ size: 'icon-sm',
47
+ className: 'mb-auto text-fd-muted-foreground',
48
+ })), children: _jsx(SidebarIcon, {}) }))] }), searchToggle.enabled !== false &&
49
+ (searchToggle.components?.lg ?? (_jsx(LargeSearchToggle, { hideIfDisabled: true }))), tabs.length > 0 && _jsx(RootToggle, { options: tabs }), banner] }), viewport, _jsxs(HideIfEmpty, { as: SidebarFooter, children: [_jsxs("div", { className: "flex text-fd-muted-foreground items-center justify-end empty:hidden", children: [iconLinks.map((item, i) => (_jsx(BaseLinkItem, { item: item, className: cn(buttonVariants({ size: 'icon-sm', color: 'ghost' }), i === iconLinks.length - 1 && 'me-auto'), "aria-label": item.label, children: item.icon }, i))), i18n ? (_jsx(LanguageToggle, { children: _jsx(Languages, { className: "size-4.5" }) })) : null, themeSwitch.enabled !== false &&
50
+ (themeSwitch.component ?? (_jsx(ThemeToggle, { className: "p-0 ms-1.5", mode: themeSwitch.mode })))] }), footer] })] }));
51
+ return (_jsx(Sidebar, { defaultOpenLevel: defaultOpenLevel, prefetch: prefetch, Mobile: mobile, Content: _jsxs(_Fragment, { children: [collapsible && _jsx(CollapsibleControl, {}), content] }) }));
52
+ }
37
53
  return (_jsx(TreeContextProvider, { tree: props.tree, children: _jsxs(NavProvider, { transparentMode: transparentMode, children: [nav.enabled !== false &&
38
- (nav.component ?? (_jsxs(Navbar, { className: "h-14 md:hidden", children: [_jsx(Link, { href: nav.url ?? '/', className: "inline-flex items-center gap-2.5 font-semibold", children: nav.title }), _jsx("div", { className: "flex-1", children: nav.children }), searchToggle?.enabled !== false &&
39
- (searchToggle.components?.sm ?? (_jsx(SearchToggle, { className: "p-2", hideIfDisabled: true }))), sidebarEnabled && (_jsx(NavbarSidebarTrigger, { className: "p-2 -me-1.5 md:hidden" }))] }))), _jsxs(LayoutBody, { ...props.containerProps, className: cn(variables, props.containerProps?.className), children: [sidebarEnabled && sidebar, children] })] }) }));
54
+ (nav.component ?? (_jsxs(Navbar, { className: "h-14 md:hidden", children: [_jsx(Link, { href: nav.url ?? '/', className: "inline-flex items-center gap-2.5 font-semibold", children: nav.title }), _jsx("div", { className: "flex-1", children: nav.children }), searchToggle.enabled !== false &&
55
+ (searchToggle.components?.sm ?? (_jsx(SearchToggle, { className: "p-2", hideIfDisabled: true }))), sidebarEnabled && (_jsx(SidebarTrigger, { className: cn(buttonVariants({
56
+ color: 'ghost',
57
+ size: 'icon-sm',
58
+ className: 'p-2',
59
+ })), children: _jsx(SidebarIcon, {}) }))] }))), _jsxs(LayoutBody, { ...props.containerProps, className: cn(variables, props.containerProps?.className), children: [sidebarEnabled && sidebar(), children] })] }) }));
40
60
  }
41
- export { CollapsibleControl, Navbar, NavbarSidebarTrigger };
61
+ export { CollapsibleControl, Navbar, SidebarTrigger };
@@ -1,4 +1,4 @@
1
- import { type HTMLAttributes } from 'react';
1
+ import { type ComponentProps, type HTMLAttributes } from 'react';
2
2
  import { type BaseLayoutProps } from '../layouts/shared.js';
3
3
  import { type SidebarOptions } from '../layouts/docs/shared.js';
4
4
  import type { PageTree } from 'fumadocs-core/server';
@@ -9,7 +9,7 @@ export interface DocsLayoutProps extends BaseLayoutProps {
9
9
  nav?: BaseLayoutProps['nav'] & {
10
10
  mode?: 'top' | 'auto';
11
11
  };
12
- sidebar?: Partial<SidebarOptions>;
12
+ sidebar?: SidebarOptions & ComponentProps<'aside'>;
13
13
  containerProps?: HTMLAttributes<HTMLDivElement>;
14
14
  }
15
15
  export declare function DocsLayout(props: DocsLayoutProps): import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"notebook.d.ts","sourceRoot":"","sources":["../../src/layouts/notebook.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,cAAc,EAAW,MAAM,OAAO,CAAC;AAC/D,OAAO,EAAE,KAAK,eAAe,EAAY,MAAM,kBAAkB,CAAC;AAqBlE,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAGL,MAAM,EACN,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAU3B,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAE/B,GAAG,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG;QAC7B,IAAI,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;KACvB,CAAC;IAEF,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAElC,cAAc,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;CACjD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,2CAiJhD;AAiMD,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"notebook.d.ts","sourceRoot":"","sources":["../../src/layouts/notebook.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,cAAc,EAEpB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,KAAK,eAAe,EAAY,MAAM,kBAAkB,CAAC;AAuBlE,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAGL,MAAM,EACN,oBAAoB,EACrB,MAAM,mBAAmB,CAAC;AAU3B,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAE/B,GAAG,CAAC,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG;QAC7B,IAAI,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;KACvB,CAAC;IAEF,OAAO,CAAC,EAAE,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAEnD,cAAc,CAAC,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC;CACjD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,2CAqMhD;AAiMD,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC"}
@@ -1,7 +1,7 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Fragment, useMemo } from 'react';
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Fragment, useMemo, } from 'react';
3
3
  import { getLinks } from '../layouts/shared.js';
4
- import { Sidebar, SidebarCollapseTrigger, SidebarFooter, SidebarHeader, SidebarPageTree, SidebarViewport, } from '../components/layout/sidebar.js';
4
+ import { Sidebar, SidebarCollapseTrigger, SidebarContent, SidebarContentMobile, SidebarFooter, SidebarHeader, SidebarPageTree, SidebarViewport, } from '../components/layout/sidebar.js';
5
5
  import { TreeContextProvider } from '../contexts/tree.js';
6
6
  import { cn } from '../utils/cn.js';
7
7
  import { buttonVariants } from '../components/ui/button.js';
@@ -18,28 +18,38 @@ import Link from 'fumadocs-core/link';
18
18
  import { LargeSearchToggle, SearchToggle, } from '../components/layout/search-toggle.js';
19
19
  import { HideIfEmpty } from 'fumadocs-core/hide-if-empty';
20
20
  export function DocsLayout(props) {
21
- const { tabMode = 'sidebar', nav: { transparentMode, ...nav } = {}, sidebar: { tabs: tabOptions, banner: sidebarBanner, footer: sidebarFooter, components: sidebarComponents, ...sidebar } = {}, i18n = false, disableThemeSwitch = false, themeSwitch = { enabled: !disableThemeSwitch }, } = props;
21
+ const { tabMode = 'sidebar', nav: { transparentMode, ...nav } = {}, sidebar: { tabs: tabOptions, ...sidebarProps } = {}, i18n = false, disableThemeSwitch = false, themeSwitch = { enabled: !disableThemeSwitch }, } = props;
22
22
  const navMode = nav.mode ?? 'auto';
23
23
  const links = getLinks(props.links ?? [], props.githubUrl);
24
24
  const tabs = useMemo(() => getSidebarTabsFromOptions(tabOptions, props.tree) ?? [], [tabOptions, props.tree]);
25
25
  const variables = cn('[--fd-nav-height:56px] md:[--fd-sidebar-width:286px] md:[--fd-nav-height:64px] xl:[--fd-toc-width:286px]', tabs.length > 0 && tabMode === 'navbar' && 'lg:[--fd-nav-height:104px]');
26
- const sidebarHeader = (_jsxs("div", { className: "flex justify-between max-md:hidden", children: [_jsx(Link, { href: nav.url ?? '/', className: "inline-flex items-center gap-2.5 font-medium", children: nav.title }), (sidebar.collapsible ?? true) && (_jsx(SidebarCollapseTrigger, { className: cn(buttonVariants({
27
- color: 'ghost',
28
- size: 'icon-sm',
29
- className: 'mt-px mb-auto text-fd-muted-foreground',
30
- })), children: _jsx(SidebarIcon, {}) }))] }));
31
- return (_jsx(TreeContextProvider, { tree: props.tree, children: _jsx(NavProvider, { transparentMode: transparentMode, children: _jsxs(LayoutBody, { ...props.containerProps, className: cn(variables, props.containerProps?.className), children: [_jsxs(Sidebar, { ...sidebar, className: cn(navMode === 'top'
32
- ? 'border-e-0 md:bg-transparent'
33
- : 'md:[--fd-nav-height:0px]', sidebar.className), children: [_jsx(HideIfEmpty, { children: _jsxs(SidebarHeader, { className: "data-[empty=true]:hidden", children: [navMode === 'auto' && sidebarHeader, nav.children, sidebarBanner, tabMode === 'sidebar' && tabs.length > 0 ? (_jsx(RootToggle, { className: "mb-2", options: tabs })) : null, tabMode === 'navbar' && tabs.length > 0 && (_jsx(RootToggle, { options: tabs, className: "lg:hidden" }))] }) }), _jsxs(SidebarViewport, { children: [links
34
- .filter((item) => item.type !== 'icon')
35
- .map((item, i) => (_jsx(SidebarLinkItem, { item: item, className: cn('lg:hidden', i === links.length - 1 && 'mb-4') }, i))), _jsx(SidebarPageTree, { components: sidebarComponents })] }), _jsx(HideIfEmpty, { children: _jsxs(SidebarFooter, { className: "flex flex-row items-center justify-end data-[empty=true]:hidden", children: [_jsx("div", { className: "flex items-center flex-1 empty:hidden lg:hidden", children: links
36
- .filter((item) => item.type === 'icon')
37
- .map((item, i) => (_jsx(BaseLinkItem, { item: item, className: cn(buttonVariants({
38
- size: 'icon-sm',
39
- color: 'ghost',
40
- className: 'text-fd-muted-foreground',
41
- })), "aria-label": item.label, children: item.icon }, i))) }), i18n ? (_jsx(LanguageToggle, { className: "me-auto md:hidden", children: _jsx(Languages, { className: "size-4.5 text-fd-muted-foreground" }) })) : null, themeSwitch.enabled !== false &&
42
- (themeSwitch.component ?? (_jsx(ThemeToggle, { className: "md:hidden", mode: themeSwitch?.mode ?? 'light-dark-system' }))), sidebarFooter] }) })] }), _jsx(DocsNavbar, { ...props, links: links, tabs: tabMode == 'navbar' ? tabs : [] }), props.children] }) }) }));
26
+ function sidebar() {
27
+ const { banner, footer, components, collapsible = true, prefetch, defaultOpenLevel, ...rest } = sidebarProps;
28
+ const iconLinks = links.filter((item) => item.type === 'icon');
29
+ const rootToggle = (_jsxs(_Fragment, { children: [tabMode === 'sidebar' && tabs.length > 0 && (_jsx(RootToggle, { className: "mb-2", options: tabs })), tabMode === 'navbar' && tabs.length > 0 && (_jsx(RootToggle, { options: tabs, className: "lg:hidden" }))] }));
30
+ const sidebarNav = (_jsxs("div", { className: "flex justify-between", children: [_jsx(Link, { href: nav.url ?? '/', className: "inline-flex items-center gap-2.5 font-medium", children: nav.title }), collapsible && (_jsx(SidebarCollapseTrigger, { className: cn(buttonVariants({
31
+ color: 'ghost',
32
+ size: 'icon-sm',
33
+ className: 'mt-px mb-auto text-fd-muted-foreground',
34
+ })), children: _jsx(SidebarIcon, {}) }))] }));
35
+ const viewport = (_jsxs(SidebarViewport, { children: [links
36
+ .filter((item) => item.type !== 'icon')
37
+ .map((item, i, arr) => (_jsx(SidebarLinkItem, { item: item, className: cn('lg:hidden', i === arr.length - 1 && 'mb-4') }, i))), _jsx(SidebarPageTree, { components: components })] }));
38
+ const content = (_jsxs(SidebarContent, { ...rest, className: cn(navMode === 'top'
39
+ ? 'border-e-0 bg-transparent'
40
+ : '[--fd-nav-height:0px]', rest.className), children: [_jsxs(HideIfEmpty, { as: SidebarHeader, children: [navMode === 'auto' && sidebarNav, nav.children, banner, rootToggle] }), viewport, _jsxs(HideIfEmpty, { as: SidebarFooter, className: "flex flex-row text-fd-muted-foreground items-center", children: [iconLinks.map((item, i) => (_jsx(BaseLinkItem, { item: item, className: cn(buttonVariants({
41
+ size: 'icon-sm',
42
+ color: 'ghost',
43
+ className: 'lg:hidden',
44
+ })), "aria-label": item.label, children: item.icon }, i))), footer] })] }));
45
+ const mobile = (_jsxs(SidebarContentMobile, { ...rest, children: [_jsxs(HideIfEmpty, { as: SidebarHeader, children: [banner, rootToggle] }), viewport, _jsxs(HideIfEmpty, { as: SidebarFooter, className: "flex flex-row items-center justify-end", children: [iconLinks.map((item, i) => (_jsx(BaseLinkItem, { item: item, className: cn(buttonVariants({
46
+ size: 'icon-sm',
47
+ color: 'ghost',
48
+ }), 'text-fd-muted-foreground lg:hidden', i === iconLinks.length - 1 && 'me-auto'), "aria-label": item.label, children: item.icon }, i))), i18n ? (_jsx(LanguageToggle, { children: _jsx(Languages, { className: "size-4.5 text-fd-muted-foreground" }) })) : null, themeSwitch.enabled !== false &&
49
+ (themeSwitch.component ?? (_jsx(ThemeToggle, { mode: themeSwitch.mode ?? 'light-dark-system' }))), footer] })] }));
50
+ return (_jsx(Sidebar, { defaultOpenLevel: defaultOpenLevel, prefetch: prefetch, Content: content, Mobile: mobile }));
51
+ }
52
+ return (_jsx(TreeContextProvider, { tree: props.tree, children: _jsx(NavProvider, { transparentMode: transparentMode, children: _jsxs(LayoutBody, { ...props.containerProps, className: cn(variables, props.containerProps?.className), children: [sidebar(), _jsx(DocsNavbar, { ...props, links: links, tabs: tabMode == 'navbar' ? tabs : [] }), props.children] }) }) }));
43
53
  }
44
54
  function DocsNavbar({ links, tabs, searchToggle = {}, themeSwitch = {}, ...props }) {
45
55
  const navMode = props.nav?.mode ?? 'auto';
package/dist/style.css CHANGED
@@ -55,6 +55,7 @@
55
55
  --color-fd-warning: oklch(76.9% 0.188 70.08);
56
56
  --color-fd-error: oklch(63.7% 0.237 25.331);
57
57
  --color-fd-success: oklch(72.3% 0.219 149.579);
58
+ --fd-sidebar-mobile-offset: 100%;
58
59
  --spacing-fd-container: 1400px;
59
60
  --fd-page-width: 1200px;
60
61
  --fd-sidebar-width: 0px;
@@ -312,24 +313,18 @@
312
313
  .inset-y-1 {
313
314
  inset-block: calc(var(--spacing) * 1);
314
315
  }
315
- .inset-y-2 {
316
- inset-block: calc(var(--spacing) * 2);
317
- }
318
- .inset-y-3 {
319
- inset-block: calc(var(--spacing) * 3);
320
- }
321
316
  .start-0 {
322
317
  inset-inline-start: calc(var(--spacing) * 0);
323
318
  }
324
- .start-2 {
325
- inset-inline-start: calc(var(--spacing) * 2);
326
- }
327
319
  .start-2\.5 {
328
320
  inset-inline-start: calc(var(--spacing) * 2.5);
329
321
  }
330
322
  .start-4\.5 {
331
323
  inset-inline-start: calc(var(--spacing) * 4.5);
332
324
  }
325
+ .end-0 {
326
+ inset-inline-end: calc(var(--spacing) * 0);
327
+ }
333
328
  .end-2 {
334
329
  inset-inline-end: calc(var(--spacing) * 2);
335
330
  }
@@ -460,6 +455,9 @@
460
455
  .-ms-1\.5 {
461
456
  margin-inline-start: calc(var(--spacing) * -1.5);
462
457
  }
458
+ .ms-1\.5 {
459
+ margin-inline-start: calc(var(--spacing) * 1.5);
460
+ }
463
461
  .ms-2 {
464
462
  margin-inline-start: calc(var(--spacing) * 2);
465
463
  }
@@ -475,9 +473,6 @@
475
473
  .-me-1\.5 {
476
474
  margin-inline-end: calc(var(--spacing) * -1.5);
477
475
  }
478
- .me-1\.5 {
479
- margin-inline-end: calc(var(--spacing) * 1.5);
480
- }
481
476
  .me-2 {
482
477
  margin-inline-end: calc(var(--spacing) * 2);
483
478
  }
@@ -1116,16 +1111,12 @@
1116
1111
  .origin-\[top_center\] {
1117
1112
  transform-origin: top center;
1118
1113
  }
1119
- .-translate-x-\(--fd-sidebar-offset\) {
1120
- --tw-translate-x: calc(var(--fd-sidebar-offset) * -1);
1121
- translate: var(--tw-translate-x) var(--tw-translate-y);
1122
- }
1123
1114
  .-translate-x-1\/2 {
1124
1115
  --tw-translate-x: calc(calc(1/2 * 100%) * -1);
1125
1116
  translate: var(--tw-translate-x) var(--tw-translate-y);
1126
1117
  }
1127
- .translate-x-2 {
1128
- --tw-translate-x: calc(var(--spacing) * 2);
1118
+ .translate-x-\(--fd-sidebar-offset\) {
1119
+ --tw-translate-x: var(--fd-sidebar-offset);
1129
1120
  translate: var(--tw-translate-x) var(--tw-translate-y);
1130
1121
  }
1131
1122
  .-translate-y-1\/2 {
@@ -1149,9 +1140,6 @@
1149
1140
  .transform {
1150
1141
  transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
1151
1142
  }
1152
- .animate-fd-fade-in {
1153
- animation: var(--animate-fd-fade-in);
1154
- }
1155
1143
  .animate-pulse {
1156
1144
  animation: var(--animate-pulse);
1157
1145
  }
@@ -1466,6 +1454,9 @@
1466
1454
  .py-12 {
1467
1455
  padding-block: calc(var(--spacing) * 12);
1468
1456
  }
1457
+ .ps-\(--sidebar-item-offset\) {
1458
+ padding-inline-start: var(--sidebar-item-offset);
1459
+ }
1469
1460
  .ps-1 {
1470
1461
  padding-inline-start: calc(var(--spacing) * 1);
1471
1462
  }
@@ -1478,6 +1469,9 @@
1478
1469
  .ps-3 {
1479
1470
  padding-inline-start: calc(var(--spacing) * 3);
1480
1471
  }
1472
+ .ps-4 {
1473
+ padding-inline-start: calc(var(--spacing) * 4);
1474
+ }
1481
1475
  .ps-6 {
1482
1476
  padding-inline-start: calc(var(--spacing) * 6);
1483
1477
  }
@@ -1487,6 +1481,9 @@
1487
1481
  .ps-\[calc\(var\(--fd-layout-offset\)\+var\(--fd-sidebar-width\)\)\] {
1488
1482
  padding-inline-start: calc(var(--fd-layout-offset) + var(--fd-sidebar-width));
1489
1483
  }
1484
+ .pe-2\.5 {
1485
+ padding-inline-end: calc(var(--spacing) * 2.5);
1486
+ }
1490
1487
  .pe-4 {
1491
1488
  padding-inline-end: calc(var(--spacing) * 4);
1492
1489
  }
@@ -1744,6 +1741,9 @@
1744
1741
  -webkit-user-select: none;
1745
1742
  user-select: none;
1746
1743
  }
1744
+ .\[--fd-nav-height\:0px\] {
1745
+ --fd-nav-height: 0px;
1746
+ }
1747
1747
  .\[--fd-nav-height\:56px\] {
1748
1748
  --fd-nav-height: 56px;
1749
1749
  }
@@ -1979,13 +1979,69 @@
1979
1979
  color: var(--color-fd-primary);
1980
1980
  }
1981
1981
  }
1982
- .data-\[collapsed\=false\]\:hidden {
1983
- &[data-collapsed="false"] {
1984
- display: none;
1982
+ .\*\*\:data-\[active\=true\]\:before\:absolute {
1983
+ :is(& *) {
1984
+ &[data-active="true"] {
1985
+ &::before {
1986
+ content: var(--tw-content);
1987
+ position: absolute;
1988
+ }
1989
+ }
1985
1990
  }
1986
1991
  }
1987
- .data-\[empty\=true\]\:hidden {
1988
- &[data-empty="true"] {
1992
+ .\*\*\:data-\[active\=true\]\:before\:inset-y-2\.5 {
1993
+ :is(& *) {
1994
+ &[data-active="true"] {
1995
+ &::before {
1996
+ content: var(--tw-content);
1997
+ inset-block: calc(var(--spacing) * 2.5);
1998
+ }
1999
+ }
2000
+ }
2001
+ }
2002
+ .\*\*\:data-\[active\=true\]\:before\:start-2\.5 {
2003
+ :is(& *) {
2004
+ &[data-active="true"] {
2005
+ &::before {
2006
+ content: var(--tw-content);
2007
+ inset-inline-start: calc(var(--spacing) * 2.5);
2008
+ }
2009
+ }
2010
+ }
2011
+ }
2012
+ .\*\*\:data-\[active\=true\]\:before\:w-px {
2013
+ :is(& *) {
2014
+ &[data-active="true"] {
2015
+ &::before {
2016
+ content: var(--tw-content);
2017
+ width: 1px;
2018
+ }
2019
+ }
2020
+ }
2021
+ }
2022
+ .\*\*\:data-\[active\=true\]\:before\:bg-fd-primary {
2023
+ :is(& *) {
2024
+ &[data-active="true"] {
2025
+ &::before {
2026
+ content: var(--tw-content);
2027
+ background-color: var(--color-fd-primary);
2028
+ }
2029
+ }
2030
+ }
2031
+ }
2032
+ .\*\*\:data-\[active\=true\]\:before\:content-\[\'\'\] {
2033
+ :is(& *) {
2034
+ &[data-active="true"] {
2035
+ &::before {
2036
+ content: var(--tw-content);
2037
+ --tw-content: '';
2038
+ content: var(--tw-content);
2039
+ }
2040
+ }
2041
+ }
2042
+ }
2043
+ .data-\[collapsed\=false\]\:hidden {
2044
+ &[data-collapsed="false"] {
1989
2045
  display: none;
1990
2046
  }
1991
2047
  }
@@ -2240,11 +2296,6 @@
2240
2296
  position: sticky;
2241
2297
  }
2242
2298
  }
2243
- .md\:inset-y-2 {
2244
- @media (width >= 48rem) {
2245
- inset-block: calc(var(--spacing) * 2);
2246
- }
2247
- }
2248
2299
  .md\:top-\[calc\(50\%-250px\)\] {
2249
2300
  @media (width >= 48rem) {
2250
2301
  top: calc(50% - 250px);
@@ -2291,11 +2342,6 @@
2291
2342
  grid-template-columns: repeat(2, minmax(0, 1fr));
2292
2343
  }
2293
2344
  }
2294
- .md\:bg-transparent {
2295
- @media (width >= 48rem) {
2296
- background-color: transparent;
2297
- }
2298
- }
2299
2345
  .md\:px-6 {
2300
2346
  @media (width >= 48rem) {
2301
2347
  padding-inline: calc(var(--spacing) * 6);
@@ -2381,9 +2427,9 @@
2381
2427
  grid-column: 1 / -1;
2382
2428
  }
2383
2429
  }
2384
- .rtl\:translate-x-\(--fd-sidebar-offset\) {
2430
+ .rtl\:-translate-x-\(--fd-sidebar-offset\) {
2385
2431
  &:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) {
2386
- --tw-translate-x: var(--fd-sidebar-offset);
2432
+ --tw-translate-x: calc(var(--fd-sidebar-offset) * -1);
2387
2433
  translate: var(--tw-translate-x) var(--tw-translate-y);
2388
2434
  }
2389
2435
  }
@@ -2438,14 +2484,6 @@
2438
2484
  flex-shrink: 0;
2439
2485
  }
2440
2486
  }
2441
- .md\:\[\&_svg\]\:size-4\.5 {
2442
- @media (width >= 48rem) {
2443
- & svg {
2444
- width: calc(var(--spacing) * 4.5);
2445
- height: calc(var(--spacing) * 4.5);
2446
- }
2447
- }
2448
- }
2449
2487
  .\[\&\>figure\:only-child\]\:-m-4 {
2450
2488
  &>figure:only-child {
2451
2489
  margin: calc(var(--spacing) * -4);
@@ -2501,22 +2539,20 @@
2501
2539
  filter: blur(0);
2502
2540
  }
2503
2541
  &[data-line-numbers] code .twoslash-meta-line {
2504
- margin-left: calc(var(--spacing) * 7);
2542
+ padding-left: calc(var(--padding-left) + 7 * var(--spacing));
2505
2543
  }
2506
2544
  &[data-line-numbers] code .line {
2507
- width: calc(100% - 7 * var(--spacing));
2508
2545
  counter-increment: line;
2509
- padding-left: calc(var(--padding-left) - var(--spacing));
2510
- margin-left: calc(var(--spacing) * 7);
2546
+ padding-left: calc(var(--padding-left) + 7 * var(--spacing));
2511
2547
  &::after {
2512
2548
  position: absolute;
2513
2549
  content: counter(line);
2514
- top: calc(var(--spacing) * 0);
2515
- left: calc(var(--spacing) * -5);
2516
- color: color-mix(in srgb, hsl(0, 0%, 45.1%) 60%, transparent);
2550
+ color: var(--fd-counter-color, hsl(0, 0%, 45.1%));
2517
2551
  @supports (color: color-mix(in lab, red, red)) {
2518
- color: color-mix(in oklab, var(--color-fd-muted-foreground) 60%, transparent);
2552
+ color: color-mix( in oklab, var(--fd-counter-color, var(--color-fd-muted-foreground)) 60%, transparent );
2519
2553
  }
2554
+ top: calc(var(--spacing) * 0);
2555
+ left: calc(var(--spacing) * 4);
2520
2556
  }
2521
2557
  }
2522
2558
  code .diff::before {
@@ -2525,6 +2561,7 @@
2525
2561
  }
2526
2562
  code .diff.remove {
2527
2563
  opacity: 0.7;
2564
+ --fd-counter-color: var(--color-fd-diff-remove-symbol);
2528
2565
  background-color: var(--color-fd-diff-remove);
2529
2566
  }
2530
2567
  code .diff.remove::before {
@@ -2532,19 +2569,21 @@
2532
2569
  color: var(--color-fd-diff-remove-symbol);
2533
2570
  }
2534
2571
  code .diff.add {
2572
+ --fd-counter-color: var(--color-fd-diff-add-symbol);
2535
2573
  background-color: var(--color-fd-diff-add);
2536
2574
  }
2537
2575
  code .diff.add::before {
2538
2576
  content: '+';
2539
2577
  color: var(--color-fd-diff-add-symbol);
2540
2578
  }
2541
- .highlighted {
2579
+ code .highlighted {
2580
+ --fd-counter-color: var(--color-fd-primary);
2542
2581
  background-color: color-mix(in srgb, hsl(0, 0%, 9%) 10%, transparent);
2543
2582
  @supports (color: color-mix(in lab, red, red)) {
2544
2583
  background-color: color-mix(in oklab, var(--color-fd-primary) 10%, transparent);
2545
2584
  }
2546
2585
  }
2547
- .highlighted-word {
2586
+ code .highlighted-word {
2548
2587
  padding: 1px;
2549
2588
  margin-block: -1px;
2550
2589
  border-radius: var(--radius-md);
@@ -2567,6 +2606,9 @@
2567
2606
  color: var(--shiki-dark);
2568
2607
  }
2569
2608
  }
2609
+ [dir='rtl'] {
2610
+ --fd-sidebar-mobile-offset: -100%;
2611
+ }
2570
2612
  @layer base {
2571
2613
  *, ::after, ::before, ::backdrop, ::file-selector-button {
2572
2614
  border-color: var(--color-fd-border, currentColor);
@@ -2811,6 +2853,11 @@
2811
2853
  syntax: "*";
2812
2854
  inherits: false;
2813
2855
  }
2856
+ @property --tw-content {
2857
+ syntax: "*";
2858
+ initial-value: "";
2859
+ inherits: false;
2860
+ }
2814
2861
  @property --tw-scale-x {
2815
2862
  syntax: "*";
2816
2863
  inherits: false;
@@ -2831,6 +2878,16 @@
2831
2878
  opacity: 0.5;
2832
2879
  }
2833
2880
  }
2881
+ @keyframes fd-sidebar-in {
2882
+ from {
2883
+ transform: translateX(var(--fd-sidebar-mobile-offset));
2884
+ }
2885
+ }
2886
+ @keyframes fd-sidebar-out {
2887
+ to {
2888
+ transform: translateX(var(--fd-sidebar-mobile-offset));
2889
+ }
2890
+ }
2834
2891
  @keyframes fd-collapsible-down {
2835
2892
  from {
2836
2893
  height: 0;
@@ -2953,16 +3010,6 @@
2953
3010
  transform: translateX(-200px);
2954
3011
  }
2955
3012
  }
2956
- @keyframes fd-sidebar-in {
2957
- from {
2958
- transform: translateX(-100%);
2959
- }
2960
- }
2961
- @keyframes fd-sidebar-out {
2962
- to {
2963
- transform: translateX(-100%);
2964
- }
2965
- }
2966
3013
  @keyframes fd-nav-menu-in {
2967
3014
  from {
2968
3015
  opacity: 0;
@@ -3035,6 +3082,7 @@
3035
3082
  --tw-backdrop-saturate: initial;
3036
3083
  --tw-backdrop-sepia: initial;
3037
3084
  --tw-duration: initial;
3085
+ --tw-content: "";
3038
3086
  --tw-scale-x: 1;
3039
3087
  --tw-scale-y: 1;
3040
3088
  --tw-scale-z: 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-ui",
3
- "version": "15.6.5",
3
+ "version": "15.6.7",
4
4
  "description": "The framework for building a documentation website in Next.js",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -89,20 +89,20 @@
89
89
  "react-medium-image-zoom": "^5.3.0",
90
90
  "scroll-into-view-if-needed": "^3.1.0",
91
91
  "tailwind-merge": "^3.3.1",
92
- "fumadocs-core": "15.6.5"
92
+ "fumadocs-core": "15.6.7"
93
93
  },
94
94
  "devDependencies": {
95
- "@next/eslint-plugin-next": "^15.4.2",
95
+ "@next/eslint-plugin-next": "^15.4.4",
96
96
  "@tailwindcss/cli": "^4.1.11",
97
97
  "@types/lodash.merge": "^4.6.9",
98
98
  "@types/react": "^19.1.8",
99
99
  "@types/react-dom": "^19.1.6",
100
- "next": "15.4.2",
100
+ "next": "15.4.4",
101
101
  "tailwindcss": "^4.1.11",
102
102
  "tsc-alias": "^1.8.16",
103
103
  "@fumadocs/cli": "0.2.1",
104
104
  "eslint-config-custom": "0.0.0",
105
- "fumadocs-core": "15.6.5",
105
+ "fumadocs-core": "15.6.7",
106
106
  "tsconfig": "0.0.0"
107
107
  },
108
108
  "peerDependencies": {