@barodoc/theme-docs 2.0.0 → 5.0.0

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.
Files changed (52) hide show
  1. package/package.json +2 -2
  2. package/src/components/Breadcrumb.astro +8 -8
  3. package/src/components/CodeCopy.astro +14 -13
  4. package/src/components/DocHeader.tsx +24 -24
  5. package/src/components/DocsSidebar.tsx +11 -15
  6. package/src/components/LanguageSwitcher.astro +3 -3
  7. package/src/components/MobileNavSheet.tsx +1 -1
  8. package/src/components/Search.tsx +10 -10
  9. package/src/components/SearchDialog.tsx +8 -8
  10. package/src/components/TableOfContents.astro +5 -5
  11. package/src/components/ThemeToggle.tsx +4 -4
  12. package/src/components/api/ApiEndpoint.astro +5 -5
  13. package/src/components/api/ApiParam.astro +4 -4
  14. package/src/components/api/ApiParams.astro +3 -3
  15. package/src/components/api/ApiResponse.astro +2 -2
  16. package/src/components/mdx/Accordion.tsx +6 -6
  17. package/src/components/mdx/Badge.tsx +1 -1
  18. package/src/components/mdx/Callout.astro +20 -20
  19. package/src/components/mdx/Card.astro +5 -5
  20. package/src/components/mdx/CodeGroup.astro +23 -20
  21. package/src/components/mdx/CodeGroup.tsx +6 -6
  22. package/src/components/mdx/DocAccordion.tsx +5 -5
  23. package/src/components/mdx/DocCard.tsx +2 -2
  24. package/src/components/mdx/DocTabs.tsx +3 -3
  25. package/src/components/mdx/Expandable.tsx +11 -11
  26. package/src/components/mdx/FileTree.tsx +6 -6
  27. package/src/components/mdx/Frame.tsx +2 -2
  28. package/src/components/mdx/Mermaid.tsx +3 -3
  29. package/src/components/mdx/ParamField.tsx +7 -7
  30. package/src/components/mdx/ResponseField.tsx +6 -6
  31. package/src/components/mdx/Step.astro +2 -2
  32. package/src/components/mdx/Steps.astro +3 -3
  33. package/src/components/mdx/Steps.tsx +10 -19
  34. package/src/components/mdx/Tabs.tsx +5 -8
  35. package/src/components/mdx/Tooltip.tsx +20 -19
  36. package/src/components/ui/accordion.tsx +2 -2
  37. package/src/components/ui/alert.tsx +1 -1
  38. package/src/components/ui/button.tsx +3 -3
  39. package/src/components/ui/card.tsx +2 -2
  40. package/src/components/ui/dialog.tsx +2 -2
  41. package/src/components/ui/scroll-area.tsx +1 -1
  42. package/src/components/ui/separator.tsx +1 -1
  43. package/src/components/ui/sheet.tsx +3 -3
  44. package/src/components/ui/tabs.tsx +2 -2
  45. package/src/components/ui/tooltip.tsx +1 -1
  46. package/src/index.ts +6 -0
  47. package/src/layouts/BaseLayout.astro +7 -1
  48. package/src/layouts/DocsLayout.astro +39 -22
  49. package/src/pages/404.astro +5 -5
  50. package/src/pages/docs/[...slug].astro +2 -2
  51. package/src/pages/index.astro +21 -21
  52. package/src/styles/global.css +473 -166
@@ -2,7 +2,7 @@
2
2
  // Steps component for step-by-step guides
3
3
  ---
4
4
 
5
- <div class="not-prose my-6 space-y-4 border-l-2 border-[var(--color-border)] pl-6 ml-2">
5
+ <div class="not-prose my-6 space-y-4 border-l-2 border-[var(--bd-border)] pl-6 ml-2">
6
6
  <slot />
7
7
  </div>
8
8
 
@@ -23,8 +23,8 @@
23
23
  height: 1.5rem;
24
24
  font-size: 0.75rem;
25
25
  font-weight: 600;
26
- background-color: var(--color-bg);
27
- border: 2px solid var(--color-border);
26
+ background-color: var(--bd-bg);
27
+ border: 2px solid var(--bd-border);
28
28
  border-radius: 9999px;
29
29
  }
30
30
  </style>
@@ -8,15 +8,8 @@ interface StepsProps {
8
8
 
9
9
  export function Steps({ children, className }: StepsProps) {
10
10
  return (
11
- <div className={cn("not-prose my-6 ml-4 border-l-2 border-[var(--color-border)] pl-6 space-y-6", className)}>
12
- {React.Children.map(children, (child, index) => {
13
- if (React.isValidElement(child)) {
14
- return React.cloneElement(child as React.ReactElement<StepProps>, {
15
- stepNumber: index + 1,
16
- });
17
- }
18
- return child;
19
- })}
11
+ <div className={cn("bd-steps", className)}>
12
+ {children}
20
13
  </div>
21
14
  );
22
15
  }
@@ -24,22 +17,20 @@ export function Steps({ children, className }: StepsProps) {
24
17
  interface StepProps {
25
18
  title: string;
26
19
  children?: React.ReactNode;
27
- stepNumber?: number;
28
20
  className?: string;
29
21
  }
30
22
 
31
- export function Step({ title, children, stepNumber = 1, className }: StepProps) {
23
+ export function Step({ title, children, className }: StepProps) {
32
24
  return (
33
- <div className={cn("relative", className)}>
34
- {/* Step number circle */}
35
- <div className="absolute -left-[2.125rem] flex h-6 w-6 items-center justify-center rounded-full border-2 border-[var(--color-border)] bg-[var(--color-bg)] text-xs font-semibold text-[var(--color-text-muted)]">
36
- {stepNumber}
25
+ <div className={cn("bd-step", className)}>
26
+ <div className="bd-step-indicator">
27
+ <span className="bd-step-number" />
28
+ <div className="bd-step-connector" />
37
29
  </div>
38
- {/* Content */}
39
- <div>
40
- <h3 className="font-semibold text-[var(--color-text)] mb-2">{title}</h3>
30
+ <div className="bd-step-content">
31
+ <h3 className="bd-step-title">{title}</h3>
41
32
  {children && (
42
- <div className="text-sm text-[var(--color-text-secondary)] prose prose-sm dark:prose-invert max-w-none">
33
+ <div className="bd-step-body prose prose-sm dark:prose-invert max-w-none">
43
34
  {children}
44
35
  </div>
45
36
  )}
@@ -16,22 +16,19 @@ export function Tabs({ items, defaultValue }: TabsProps) {
16
16
 
17
17
  return (
18
18
  <div className="not-prose my-4">
19
- <div className="flex border-b border-[var(--color-border)]">
19
+ <div className="flex border-b border-[var(--bd-border)]">
20
20
  {items.map((item) => {
21
21
  const isActive = activeTab === item.value;
22
22
  return (
23
23
  <button
24
24
  key={item.value}
25
25
  type="button"
26
- onClick={() => {
27
- console.log('Tab clicked:', item.value);
28
- setActiveTab(item.value);
29
- }}
26
+ onClick={() => setActiveTab(item.value)}
30
27
  style={{ cursor: 'pointer' }}
31
28
  className={`px-4 py-2 text-sm font-medium transition-colors ${
32
29
  isActive
33
- ? "border-b-2 border-blue-600 text-blue-600 -mb-px"
34
- : "text-gray-500 hover:text-gray-900"
30
+ ? "border-b-2 border-primary-500 text-primary-600 dark:text-primary-400 -mb-px"
31
+ : "text-[var(--bd-text-muted)] hover:text-[var(--bd-text)]"
35
32
  }`}
36
33
  >
37
34
  {item.label}
@@ -45,7 +42,7 @@ export function Tabs({ items, defaultValue }: TabsProps) {
45
42
  if (!isActive) return null;
46
43
  return (
47
44
  <div key={item.value}>
48
- <pre className="bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-md p-3 text-sm overflow-x-auto">
45
+ <pre className="bg-[var(--bd-bg-code)] border border-[var(--bd-border)] rounded-md p-3 text-sm overflow-x-auto">
49
46
  <code>{item.children}</code>
50
47
  </pre>
51
48
  </div>
@@ -1,6 +1,5 @@
1
1
  import * as React from "react";
2
2
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
3
- import { cn } from "../../lib/utils.js";
4
3
 
5
4
  interface TooltipProps {
6
5
  children: React.ReactNode;
@@ -8,28 +7,30 @@ interface TooltipProps {
8
7
  }
9
8
 
10
9
  export function Tooltip({ children, tip }: TooltipProps) {
10
+ const [container, setContainer] = React.useState<HTMLElement | null>(null);
11
+
12
+ React.useEffect(() => {
13
+ setContainer(document.body);
14
+ }, []);
15
+
11
16
  return (
12
- <TooltipPrimitive.Provider delayDuration={200}>
17
+ <TooltipPrimitive.Provider delayDuration={150}>
13
18
  <TooltipPrimitive.Root>
14
19
  <TooltipPrimitive.Trigger asChild>
15
- <span className="cursor-help border-b border-dashed border-[var(--color-text-muted)] text-[var(--color-text)]">
16
- {children}
17
- </span>
20
+ <span className="bd-tooltip-trigger">{children}</span>
18
21
  </TooltipPrimitive.Trigger>
19
- <TooltipPrimitive.Portal>
20
- <TooltipPrimitive.Content
21
- className={cn(
22
- "z-50 overflow-hidden rounded-md bg-[var(--color-bg-tertiary)] px-3 py-1.5 text-sm text-[var(--color-text)] shadow-md",
23
- "animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
24
- "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
25
- "max-w-xs"
26
- )}
27
- sideOffset={4}
28
- >
29
- {tip}
30
- <TooltipPrimitive.Arrow className="fill-[var(--color-bg-tertiary)]" />
31
- </TooltipPrimitive.Content>
32
- </TooltipPrimitive.Portal>
22
+ {container && (
23
+ <TooltipPrimitive.Portal container={container}>
24
+ <TooltipPrimitive.Content
25
+ className="bd-tooltip-content"
26
+ sideOffset={6}
27
+ style={{ zIndex: 99999 }}
28
+ >
29
+ {tip}
30
+ <TooltipPrimitive.Arrow className="bd-tooltip-arrow" />
31
+ </TooltipPrimitive.Content>
32
+ </TooltipPrimitive.Portal>
33
+ )}
33
34
  </TooltipPrimitive.Root>
34
35
  </TooltipPrimitive.Provider>
35
36
  );
@@ -11,7 +11,7 @@ const AccordionItem = React.forwardRef<
11
11
  >(({ className, ...props }, ref) => (
12
12
  <AccordionPrimitive.Item
13
13
  ref={ref}
14
- className={cn("border-b border-[var(--color-border)]", className)}
14
+ className={cn("border-b border-[var(--bd-border)]", className)}
15
15
  {...props}
16
16
  />
17
17
  ));
@@ -31,7 +31,7 @@ const AccordionTrigger = React.forwardRef<
31
31
  {...props}
32
32
  >
33
33
  {children}
34
- <ChevronDown className="h-4 w-4 shrink-0 text-[var(--color-text-secondary)] transition-transform duration-200" />
34
+ <ChevronDown className="h-4 w-4 shrink-0 text-[var(--bd-text-secondary)] transition-transform duration-200" />
35
35
  </AccordionPrimitive.Trigger>
36
36
  </AccordionPrimitive.Header>
37
37
  ));
@@ -7,7 +7,7 @@ const alertVariants = cva(
7
7
  {
8
8
  variants: {
9
9
  variant: {
10
- default: "bg-[var(--color-bg-secondary)] border-l-[var(--color-border)] text-[var(--color-text)]",
10
+ default: "bg-[var(--bd-bg-subtle)] border-l-[var(--bd-border)] text-[var(--bd-text)]",
11
11
  info: "bg-blue-50/70 dark:bg-blue-950/30 border-l-blue-500 text-blue-900 dark:text-blue-100 [&>svg]:text-blue-600",
12
12
  warning: "bg-orange-50/70 dark:bg-orange-950/30 border-l-orange-500 text-orange-900 dark:text-orange-100 [&>svg]:text-orange-600",
13
13
  success: "bg-green-50/70 dark:bg-green-950/30 border-l-green-500 text-green-900 dark:text-green-100 [&>svg]:text-green-600",
@@ -13,11 +13,11 @@ const buttonVariants = cva(
13
13
  destructive:
14
14
  "bg-red-600 text-white shadow-sm hover:bg-red-700",
15
15
  outline:
16
- "border border-[var(--color-border)] bg-transparent shadow-sm hover:bg-[var(--color-bg-secondary)] hover:text-[var(--color-text)]",
16
+ "border border-[var(--bd-border)] bg-transparent shadow-sm hover:bg-[var(--bd-bg-subtle)] hover:text-[var(--bd-text)]",
17
17
  secondary:
18
- "bg-[var(--color-bg-secondary)] text-[var(--color-text)] shadow-sm hover:bg-[var(--color-bg-tertiary)]",
18
+ "bg-[var(--bd-bg-subtle)] text-[var(--bd-text)] shadow-sm hover:bg-[var(--bd-bg-muted)]",
19
19
  ghost:
20
- "hover:bg-[var(--color-bg-secondary)] hover:text-[var(--color-text)]",
20
+ "hover:bg-[var(--bd-bg-subtle)] hover:text-[var(--bd-text)]",
21
21
  link: "text-primary-600 underline-offset-4 hover:underline",
22
22
  },
23
23
  size: {
@@ -8,7 +8,7 @@ const Card = React.forwardRef<
8
8
  <div
9
9
  ref={ref}
10
10
  className={cn(
11
- "rounded-xl border border-[var(--color-border)] bg-[var(--color-bg)] text-[var(--color-text)] shadow-sm",
11
+ "rounded-xl border border-[var(--bd-border)] bg-[var(--bd-bg)] text-[var(--bd-text)] shadow-sm",
12
12
  className
13
13
  )}
14
14
  {...props}
@@ -46,7 +46,7 @@ const CardDescription = React.forwardRef<
46
46
  >(({ className, ...props }, ref) => (
47
47
  <div
48
48
  ref={ref}
49
- className={cn("text-sm text-[var(--color-text-secondary)]", className)}
49
+ className={cn("text-sm text-[var(--bd-text-secondary)]", className)}
50
50
  {...props}
51
51
  />
52
52
  ));
@@ -35,7 +35,7 @@ const DialogContent = React.forwardRef<
35
35
  <DialogPrimitive.Content
36
36
  ref={ref}
37
37
  className={cn(
38
- "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-[var(--color-border)] bg-[var(--color-bg)] p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
38
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-[var(--bd-border)] bg-[var(--bd-bg)] p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
39
39
  className
40
40
  )}
41
41
  {...props}
@@ -99,7 +99,7 @@ const DialogDescription = React.forwardRef<
99
99
  >(({ className, ...props }, ref) => (
100
100
  <DialogPrimitive.Description
101
101
  ref={ref}
102
- className={cn("text-sm text-[var(--color-text-secondary)]", className)}
102
+ className={cn("text-sm text-[var(--bd-text-secondary)]", className)}
103
103
  {...props}
104
104
  />
105
105
  ));
@@ -37,7 +37,7 @@ const ScrollBar = React.forwardRef<
37
37
  )}
38
38
  {...props}
39
39
  >
40
- <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-[var(--color-border)]" />
40
+ <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-[var(--bd-border)]" />
41
41
  </ScrollAreaPrimitive.ScrollAreaScrollbar>
42
42
  ));
43
43
  ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
@@ -15,7 +15,7 @@ const Separator = React.forwardRef<
15
15
  decorative={decorative}
16
16
  orientation={orientation}
17
17
  className={cn(
18
- "shrink-0 bg-[var(--color-border)]",
18
+ "shrink-0 bg-[var(--bd-border)]",
19
19
  orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
20
20
  className
21
21
  )}
@@ -28,7 +28,7 @@ const SheetOverlay = React.forwardRef<
28
28
  SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
29
29
 
30
30
  const sheetVariants = cva(
31
- "fixed z-50 gap-4 bg-[var(--color-bg)] p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out",
31
+ "fixed z-50 gap-4 bg-[var(--bd-bg)] p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out",
32
32
  {
33
33
  variants: {
34
34
  side: {
@@ -105,7 +105,7 @@ const SheetTitle = React.forwardRef<
105
105
  >(({ className, ...props }, ref) => (
106
106
  <SheetPrimitive.Title
107
107
  ref={ref}
108
- className={cn("text-lg font-semibold text-[var(--color-text)]", className)}
108
+ className={cn("text-lg font-semibold text-[var(--bd-text)]", className)}
109
109
  {...props}
110
110
  />
111
111
  ));
@@ -117,7 +117,7 @@ const SheetDescription = React.forwardRef<
117
117
  >(({ className, ...props }, ref) => (
118
118
  <SheetPrimitive.Description
119
119
  ref={ref}
120
- className={cn("text-sm text-[var(--color-text-secondary)]", className)}
120
+ className={cn("text-sm text-[var(--bd-text-secondary)]", className)}
121
121
  {...props}
122
122
  />
123
123
  ));
@@ -11,7 +11,7 @@ const TabsList = React.forwardRef<
11
11
  <TabsPrimitive.List
12
12
  ref={ref}
13
13
  className={cn(
14
- "inline-flex h-10 items-center justify-center rounded-lg bg-[var(--color-bg-secondary)] p-1 text-[var(--color-text-secondary)]",
14
+ "inline-flex h-10 items-center justify-center rounded-lg bg-[var(--bd-bg-subtle)] p-1 text-[var(--bd-text-secondary)]",
15
15
  className
16
16
  )}
17
17
  {...props}
@@ -26,7 +26,7 @@ const TabsTrigger = React.forwardRef<
26
26
  <TabsPrimitive.Trigger
27
27
  ref={ref}
28
28
  className={cn(
29
- "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-[var(--color-bg)] data-[state=active]:text-[var(--color-text)] data-[state=active]:shadow",
29
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-[var(--bd-bg)] data-[state=active]:text-[var(--bd-text)] data-[state=active]:shadow",
30
30
  className
31
31
  )}
32
32
  {...props}
@@ -17,7 +17,7 @@ const TooltipContent = React.forwardRef<
17
17
  ref={ref}
18
18
  sideOffset={sideOffset}
19
19
  className={cn(
20
- "z-50 overflow-hidden rounded-md bg-[var(--color-text)] px-3 py-1.5 text-xs text-[var(--color-bg)] animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
20
+ "z-50 overflow-hidden rounded-md bg-[var(--bd-text)] px-3 py-1.5 text-xs text-[var(--bd-bg)] animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
21
21
  className
22
22
  )}
23
23
  {...props}
package/src/index.ts CHANGED
@@ -84,6 +84,12 @@ function createThemeIntegration(
84
84
  integrations: [mdx(), react()],
85
85
  vite: {
86
86
  plugins: [tailwindcss()],
87
+ optimizeDeps: {
88
+ include: ["mermaid"],
89
+ },
90
+ ssr: {
91
+ noExternal: [],
92
+ },
87
93
  resolve: {
88
94
  dedupe: ["react", "react-dom"],
89
95
  },
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  import ThemeScript from "../components/ThemeScript.astro";
3
3
  import { SearchDialog } from "../components/SearchDialog";
4
+ import { ClientRouter } from "astro:transitions";
4
5
  import config from "virtual:barodoc/config";
6
+ import { generateThemeCSS } from "@barodoc/core";
5
7
  import "@barodoc/theme-docs/styles/global.css";
6
8
 
7
9
  interface Props {
@@ -16,6 +18,8 @@ const canonicalUrl = config.site ? new URL(Astro.url.pathname, config.site).href
16
18
  const ogImageUrl = ogImage
17
19
  ? (config.site ? new URL(ogImage, config.site).href : ogImage)
18
20
  : undefined;
21
+
22
+ const themeCSS = config.theme?.colors ? generateThemeCSS(config.theme.colors) : "";
19
23
  ---
20
24
 
21
25
  <!doctype html>
@@ -43,8 +47,10 @@ const ogImageUrl = ogImage
43
47
 
44
48
  <title>{title}</title>
45
49
  <ThemeScript />
50
+ <ClientRouter />
51
+ {themeCSS && <style set:html={themeCSS} />}
46
52
  </head>
47
- <body class="min-h-screen bg-[var(--color-bg)] text-[var(--color-text)] antialiased">
53
+ <body class="min-h-screen bg-[var(--bd-bg)] text-[var(--bd-text)] antialiased">
48
54
  <slot />
49
55
  <SearchDialog client:load />
50
56
  </body>
@@ -48,18 +48,18 @@ const feedbackEndpoint = config.feedback?.endpoint;
48
48
  <Header currentLocale={currentLocale} currentPath={currentPath} />
49
49
 
50
50
  <!-- Centered container for docs layout -->
51
- <div class="w-full min-w-0 min-h-[calc(100vh-3.5rem)] flex justify-center overflow-x-hidden">
52
- <div class="flex w-full max-w-[1120px] min-w-0">
51
+ <div class="w-full min-w-0 min-h-[calc(100vh-3.5rem)] flex justify-center overflow-x-clip">
52
+ <div class="flex w-full max-w-[1280px] min-w-0">
53
53
  <!-- Desktop Sidebar -->
54
- <aside class="hidden lg:block w-[220px] shrink-0">
55
- <div class="sticky top-14 h-[calc(100vh-3.5rem)] overflow-y-auto py-6 pr-4">
54
+ <aside class="hidden lg:block w-[240px] shrink-0 border-r border-[var(--bd-border)]">
55
+ <div class="sticky top-14 h-[calc(100vh-3.5rem)] overflow-y-auto overscroll-contain pt-2 pb-8 px-4 sidebar-scroll">
56
56
  <Sidebar currentPath={currentPath} currentLocale={currentLocale} />
57
57
  </div>
58
58
  </aside>
59
59
 
60
- <!-- Main Content: no min-width on mobile to avoid horizontal scroll -->
61
- <main class="flex-1 min-w-0 lg:min-w-[650px] max-w-[720px]">
62
- <div class="px-4 py-6 sm:px-6 sm:py-8 lg:px-8 lg:py-8">
60
+ <!-- Main Content -->
61
+ <main class="flex-1 min-w-0 max-w-[768px]">
62
+ <div class="px-4 py-8 sm:px-6 sm:py-10 lg:px-10 lg:py-10">
63
63
  {breadcrumbs.length > 0 && <Breadcrumb items={breadcrumbs} />}
64
64
  <article class="prose prose-gray dark:prose-invert max-w-none min-w-0 overflow-x-auto">
65
65
  <slot />
@@ -67,21 +67,21 @@ const feedbackEndpoint = config.feedback?.endpoint;
67
67
 
68
68
  <!-- Page Navigation -->
69
69
  {(prevPage || nextPage) && (
70
- <nav class="mt-8 pt-6 border-t border-[var(--color-border)]" aria-label="Page navigation">
70
+ <nav class="mt-12 pt-8 border-t border-[var(--bd-border)]" aria-label="Page navigation">
71
71
  <div class="grid grid-cols-2 gap-4">
72
72
  <div class="col-span-1">
73
73
  {prevPage && (
74
74
  <a
75
75
  href={prevPage.href}
76
- class="group flex flex-col gap-1 p-3 rounded-lg border border-[var(--color-border)] hover:border-primary-300 dark:hover:border-primary-700 hover:bg-[var(--color-bg-secondary)] transition-all"
76
+ class="group flex flex-col gap-1.5 p-4 rounded-lg border border-[var(--bd-border)] hover:border-primary-400/50 dark:hover:border-primary-500/40 hover:shadow-[var(--bd-shadow-sm)] transition-all"
77
77
  >
78
- <span class="text-xs text-[var(--color-text-muted)] flex items-center gap-1">
78
+ <span class="text-xs font-medium text-[var(--bd-text-muted)] flex items-center gap-1">
79
79
  <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
80
80
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
81
81
  </svg>
82
82
  Previous
83
83
  </span>
84
- <span class="text-sm font-medium text-[var(--color-text)] group-hover:text-primary-600 dark:group-hover:text-primary-400 transition-colors">
84
+ <span class="text-sm font-medium text-[var(--bd-text)] group-hover:text-primary-600 dark:group-hover:text-primary-400 transition-colors">
85
85
  {prevPage.title}
86
86
  </span>
87
87
  </a>
@@ -91,15 +91,15 @@ const feedbackEndpoint = config.feedback?.endpoint;
91
91
  {nextPage && (
92
92
  <a
93
93
  href={nextPage.href}
94
- class="group flex flex-col gap-1 p-3 rounded-lg border border-[var(--color-border)] hover:border-primary-300 dark:hover:border-primary-700 hover:bg-[var(--color-bg-secondary)] transition-all text-right"
94
+ class="group flex flex-col gap-1.5 p-4 rounded-lg border border-[var(--bd-border)] hover:border-primary-400/50 dark:hover:border-primary-500/40 hover:shadow-[var(--bd-shadow-sm)] transition-all text-right"
95
95
  >
96
- <span class="text-xs text-[var(--color-text-muted)] flex items-center gap-1 justify-end">
96
+ <span class="text-xs font-medium text-[var(--bd-text-muted)] flex items-center gap-1 justify-end">
97
97
  Next
98
98
  <svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
99
99
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
100
100
  </svg>
101
101
  </span>
102
- <span class="text-sm font-medium text-[var(--color-text)] group-hover:text-primary-600 dark:group-hover:text-primary-400 transition-colors">
102
+ <span class="text-sm font-medium text-[var(--bd-text)] group-hover:text-primary-600 dark:group-hover:text-primary-400 transition-colors">
103
103
  {nextPage.title}
104
104
  </span>
105
105
  </a>
@@ -110,8 +110,8 @@ const feedbackEndpoint = config.feedback?.endpoint;
110
110
  )}
111
111
 
112
112
  <!-- Page footer -->
113
- <footer class="mt-6 pt-4 border-t border-[var(--color-border-light)] flex flex-col gap-3">
114
- <div class="flex flex-wrap items-center justify-between gap-2 text-sm text-[var(--color-text-muted)]">
113
+ <footer class="mt-8 pt-6 border-t border-[var(--bd-border-subtle)] flex flex-col gap-3">
114
+ <div class="flex flex-wrap items-center justify-between gap-2 text-[13px] text-[var(--bd-text-muted)]">
115
115
  {lastUpdated && (
116
116
  <span>
117
117
  Last updated: <time datetime={lastUpdated.toISOString()}>
@@ -124,7 +124,7 @@ const feedbackEndpoint = config.feedback?.endpoint;
124
124
  href={editUrl}
125
125
  target="_blank"
126
126
  rel="noopener noreferrer"
127
- class="inline-flex items-center gap-1 text-primary-600 dark:text-primary-400 hover:underline"
127
+ class="inline-flex items-center gap-1.5 text-[var(--bd-text-secondary)] hover:text-primary-600 dark:hover:text-primary-400 transition-colors"
128
128
  >
129
129
  <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
130
130
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
@@ -134,12 +134,12 @@ const feedbackEndpoint = config.feedback?.endpoint;
134
134
  )}
135
135
  </div>
136
136
  {hasFeedback && (
137
- <div class="doc-feedback flex items-center gap-3 text-sm text-[var(--color-text-muted)]" data-endpoint={feedbackEndpoint}>
137
+ <div class="doc-feedback flex items-center gap-3 text-sm text-[var(--bd-text-muted)]" data-endpoint={feedbackEndpoint}>
138
138
  <span>Was this page helpful?</span>
139
- <button type="button" class="feedback-btn inline-flex items-center gap-1 px-2 py-1 rounded border border-[var(--color-border)] hover:bg-[var(--color-bg-secondary)] transition-colors" data-value="yes" aria-label="Yes">
139
+ <button type="button" class="feedback-btn inline-flex items-center gap-1 px-2 py-1 rounded border border-[var(--bd-border)] hover:bg-[var(--bd-bg-subtle)] transition-colors" data-value="yes" aria-label="Yes">
140
140
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 9V5a3 3 0 00-3-3l-4 9v11h11.28a2 2 0 002-1.7l1.38-9a2 2 0 00-2-2.3H14z" /></svg>
141
141
  </button>
142
- <button type="button" class="feedback-btn inline-flex items-center gap-1 px-2 py-1 rounded border border-[var(--color-border)] hover:bg-[var(--color-bg-secondary)] transition-colors" data-value="no" aria-label="No">
142
+ <button type="button" class="feedback-btn inline-flex items-center gap-1 px-2 py-1 rounded border border-[var(--bd-border)] hover:bg-[var(--bd-bg-subtle)] transition-colors" data-value="no" aria-label="No">
143
143
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 15v3.586a1 1 0 01-.293.707l-2 2A1 1 0 016 20.586V15m4 0h5.17a2 2 0 001.98-1.742l1.08-7.56A1 1 0 0017.242 4.5H10m0 10.5V4.5m0 0H7.5A2.5 2.5 0 005 7v3" /></svg>
144
144
  </button>
145
145
  <span class="feedback-thanks hidden text-green-600 dark:text-green-400">Thanks for your feedback!</span>
@@ -151,8 +151,8 @@ const feedbackEndpoint = config.feedback?.endpoint;
151
151
 
152
152
  <!-- Table of Contents -->
153
153
  {headings.length > 0 && (
154
- <aside class="hidden xl:block w-[180px] shrink-0">
155
- <div class="sticky top-14 h-[calc(100vh-3.5rem)] overflow-y-auto py-6 pl-6">
154
+ <aside class="hidden xl:block w-[220px] shrink-0">
155
+ <div class="sticky top-14 h-[calc(100vh-3.5rem)] overflow-y-auto py-10 pl-8">
156
156
  <TableOfContents headings={headings} />
157
157
  </div>
158
158
  </aside>
@@ -166,6 +166,23 @@ const feedbackEndpoint = config.feedback?.endpoint;
166
166
  <!-- Code copy functionality -->
167
167
  <CodeCopy />
168
168
 
169
+ <!-- Heading anchor links -->
170
+ <script>
171
+ function initHeadingAnchors() {
172
+ document.querySelectorAll('.prose h2[id], .prose h3[id], .prose h4[id]').forEach((heading) => {
173
+ if (heading.querySelector('.heading-anchor')) return;
174
+ const anchor = document.createElement('a');
175
+ anchor.className = 'heading-anchor';
176
+ anchor.href = `#${heading.id}`;
177
+ anchor.textContent = '#';
178
+ anchor.setAttribute('aria-label', `Link to ${heading.textContent}`);
179
+ heading.appendChild(anchor);
180
+ });
181
+ }
182
+ initHeadingAnchors();
183
+ document.addEventListener('astro:page-load', initHeadingAnchors);
184
+ </script>
185
+
169
186
  {hasFeedback && (
170
187
  <script>
171
188
  function initFeedback() {
@@ -8,10 +8,10 @@ const pathname = new URL(Astro.request.url).pathname;
8
8
  <BaseLayout title={`${config.name} · Page not found`} description="The page you are looking for does not exist.">
9
9
  <div class="min-h-screen flex flex-col items-center justify-center px-4">
10
10
  <div class="text-center max-w-md">
11
- <p class="text-8xl font-bold text-[var(--color-text-muted)] select-none" aria-hidden="true">404</p>
12
- <h1 class="text-2xl font-semibold text-[var(--color-text)] mt-4">Page not found</h1>
13
- <p class="text-[var(--color-text-secondary)] mt-2">
14
- The page at <code class="text-sm bg-[var(--color-bg-secondary)] px-2 py-1 rounded break-all">{pathname}</code> does not exist.
11
+ <p class="text-8xl font-bold text-[var(--bd-text-muted)] select-none" aria-hidden="true">404</p>
12
+ <h1 class="text-2xl font-semibold text-[var(--bd-text)] mt-4">Page not found</h1>
13
+ <p class="text-[var(--bd-text-secondary)] mt-2">
14
+ The page at <code class="text-sm bg-[var(--bd-bg-subtle)] px-2 py-1 rounded break-all">{pathname}</code> does not exist.
15
15
  </p>
16
16
  <div class="flex flex-col sm:flex-row items-center justify-center gap-3 mt-8">
17
17
  <a
@@ -22,7 +22,7 @@ const pathname = new URL(Astro.request.url).pathname;
22
22
  </a>
23
23
  <a
24
24
  href="/docs/introduction"
25
- class="px-5 py-2.5 border border-[var(--color-border)] text-[var(--color-text)] rounded-xl hover:bg-[var(--color-bg-secondary)] transition-colors font-medium"
25
+ class="px-5 py-2.5 border border-[var(--bd-border)] text-[var(--bd-text)] rounded-xl hover:bg-[var(--bd-bg-subtle)] transition-colors font-medium"
26
26
  >
27
27
  Documentation
28
28
  </a>
@@ -124,13 +124,13 @@ breadcrumbs.push({ label: doc.data.title });
124
124
  breadcrumbs={breadcrumbs}
125
125
  >
126
126
  {category && (
127
- <p class="text-xs font-medium uppercase tracking-wider text-primary-600 dark:text-primary-400 mb-2">
127
+ <p class="text-xs font-semibold uppercase tracking-widest text-primary-600 dark:text-primary-400 mb-3">
128
128
  {category}
129
129
  </p>
130
130
  )}
131
131
  <h1>{doc.data.title}</h1>
132
132
  {doc.data.description && (
133
- <p class="lead text-sm text-[var(--color-text-secondary)] mt-1 mb-4">
133
+ <p class="lead text-base text-[var(--bd-text-secondary)] mt-2 mb-6 leading-relaxed">
134
134
  {doc.data.description}
135
135
  </p>
136
136
  )}