@specglass/theme-default 0.0.9 → 0.0.11

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 (45) hide show
  1. package/dist/__tests__/design-tokens.test.d.ts +1 -0
  2. package/dist/__tests__/design-tokens.test.js +107 -0
  3. package/dist/islands/CopyButton.js +2 -6
  4. package/dist/islands/LanguageToggle.d.ts +16 -0
  5. package/dist/islands/LanguageToggle.js +88 -0
  6. package/dist/islands/SearchPalette.js +57 -8
  7. package/dist/islands/ThemeToggle.js +1 -1
  8. package/dist/scripts/code-block-enhancer.js +6 -3
  9. package/dist/themes/notdiamond-dark.json +168 -0
  10. package/dist/themes/notdiamond-light.json +168 -0
  11. package/dist/ui/command.js +2 -2
  12. package/dist/ui/dialog.js +2 -2
  13. package/dist/utils/shiki.d.ts +1 -1
  14. package/dist/utils/shiki.js +5 -3
  15. package/package.json +5 -3
  16. package/src/components/ApiAuth.astro +31 -4
  17. package/src/components/ApiEndpoint.astro +67 -44
  18. package/src/components/ApiNavigation.astro +8 -11
  19. package/src/components/ApiParameters.astro +113 -162
  20. package/src/components/ApiResponse.astro +1 -1
  21. package/src/components/Callout.astro +59 -18
  22. package/src/components/Card.astro +4 -4
  23. package/src/components/CodeBlock.astro +7 -7
  24. package/src/components/CodeBlockGroup.astro +3 -3
  25. package/src/components/CodeExample.astro +183 -0
  26. package/src/components/EditLink.astro +53 -0
  27. package/src/components/Footer.astro +87 -25
  28. package/src/components/Header.astro +63 -7
  29. package/src/components/Sidebar.astro +43 -11
  30. package/src/components/TableOfContents.astro +5 -5
  31. package/src/components/Tabs.astro +51 -20
  32. package/src/islands/CopyButton.tsx +36 -34
  33. package/src/islands/LanguageToggle.tsx +214 -0
  34. package/src/islands/SearchPalette.tsx +121 -39
  35. package/src/islands/ThemeToggle.tsx +45 -48
  36. package/src/layouts/ApiReferencePage.astro +67 -56
  37. package/src/layouts/DocPage.astro +32 -27
  38. package/src/layouts/LandingPage.astro +348 -27
  39. package/src/scripts/code-block-enhancer.ts +8 -3
  40. package/src/styles/global.css +388 -59
  41. package/src/themes/notdiamond-dark.json +168 -0
  42. package/src/themes/notdiamond-light.json +168 -0
  43. package/src/ui/command.tsx +1 -2
  44. package/src/ui/dialog.tsx +8 -5
  45. package/src/utils/shiki.ts +5 -3
@@ -0,0 +1,168 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/shikijs/textmate-grammars-themes/main/packages/tm-themes/themes/light-plus.json",
3
+ "name": "notdiamond-light",
4
+ "displayName": "Not Diamond Light",
5
+ "type": "light",
6
+ "colors": {
7
+ "editor.background": "#fafafa",
8
+ "editor.foreground": "#18181b",
9
+ "editorLineNumber.foreground": "#a1a1aa",
10
+ "editorLineNumber.activeForeground": "#52525b",
11
+ "editor.selectionBackground": "#77e54430",
12
+ "editor.lineHighlightBackground": "#f4f4f5"
13
+ },
14
+ "tokenColors": [
15
+ {
16
+ "scope": ["comment", "punctuation.definition.comment"],
17
+ "settings": {
18
+ "foreground": "#71717a",
19
+ "fontStyle": "italic"
20
+ }
21
+ },
22
+ {
23
+ "scope": ["keyword", "storage.type", "storage.modifier"],
24
+ "settings": {
25
+ "foreground": "#16a34a"
26
+ }
27
+ },
28
+ {
29
+ "scope": ["keyword.operator", "keyword.operator.assignment"],
30
+ "settings": {
31
+ "foreground": "#52525b"
32
+ }
33
+ },
34
+ {
35
+ "scope": ["keyword.control.import", "keyword.control.export", "keyword.control.from"],
36
+ "settings": {
37
+ "foreground": "#16a34a"
38
+ }
39
+ },
40
+ {
41
+ "scope": ["string", "string.quoted"],
42
+ "settings": {
43
+ "foreground": "#c2410c"
44
+ }
45
+ },
46
+ {
47
+ "scope": ["string.template", "punctuation.definition.string.template"],
48
+ "settings": {
49
+ "foreground": "#c2410c"
50
+ }
51
+ },
52
+ {
53
+ "scope": ["constant.numeric"],
54
+ "settings": {
55
+ "foreground": "#7c3aed"
56
+ }
57
+ },
58
+ {
59
+ "scope": ["constant.language"],
60
+ "settings": {
61
+ "foreground": "#7c3aed"
62
+ }
63
+ },
64
+ {
65
+ "scope": ["variable", "variable.other"],
66
+ "settings": {
67
+ "foreground": "#18181b"
68
+ }
69
+ },
70
+ {
71
+ "scope": ["variable.parameter"],
72
+ "settings": {
73
+ "foreground": "#dc2626"
74
+ }
75
+ },
76
+ {
77
+ "scope": ["entity.name.function", "support.function"],
78
+ "settings": {
79
+ "foreground": "#0284c7"
80
+ }
81
+ },
82
+ {
83
+ "scope": ["entity.name.type", "entity.name.class", "support.type", "support.class"],
84
+ "settings": {
85
+ "foreground": "#0891b2"
86
+ }
87
+ },
88
+ {
89
+ "scope": ["entity.name.tag"],
90
+ "settings": {
91
+ "foreground": "#16a34a"
92
+ }
93
+ },
94
+ {
95
+ "scope": ["entity.other.attribute-name"],
96
+ "settings": {
97
+ "foreground": "#b45309"
98
+ }
99
+ },
100
+ {
101
+ "scope": ["punctuation"],
102
+ "settings": {
103
+ "foreground": "#52525b"
104
+ }
105
+ },
106
+ {
107
+ "scope": ["meta.brace"],
108
+ "settings": {
109
+ "foreground": "#52525b"
110
+ }
111
+ },
112
+ {
113
+ "scope": ["punctuation.definition.tag"],
114
+ "settings": {
115
+ "foreground": "#71717a"
116
+ }
117
+ },
118
+ {
119
+ "scope": ["support.type.property-name"],
120
+ "settings": {
121
+ "foreground": "#0284c7"
122
+ }
123
+ },
124
+ {
125
+ "scope": ["meta.object-literal.key"],
126
+ "settings": {
127
+ "foreground": "#18181b"
128
+ }
129
+ },
130
+ {
131
+ "scope": ["variable.other.property"],
132
+ "settings": {
133
+ "foreground": "#18181b"
134
+ }
135
+ },
136
+ {
137
+ "scope": ["markup.heading"],
138
+ "settings": {
139
+ "foreground": "#16a34a",
140
+ "fontStyle": "bold"
141
+ }
142
+ },
143
+ {
144
+ "scope": ["markup.bold"],
145
+ "settings": {
146
+ "fontStyle": "bold"
147
+ }
148
+ },
149
+ {
150
+ "scope": ["markup.italic"],
151
+ "settings": {
152
+ "fontStyle": "italic"
153
+ }
154
+ },
155
+ {
156
+ "scope": ["markup.inline.raw"],
157
+ "settings": {
158
+ "foreground": "#c2410c"
159
+ }
160
+ },
161
+ {
162
+ "scope": ["markup.list"],
163
+ "settings": {
164
+ "foreground": "#52525b"
165
+ }
166
+ }
167
+ ]
168
+ }
@@ -6,9 +6,9 @@ import { Dialog, DialogContent, DialogTitle } from "./dialog";
6
6
  const Command = React.forwardRef(({ className, ...props }, ref) => (_jsx(CommandPrimitive, { ref: ref, className: cn("flex h-full w-full flex-col overflow-hidden rounded-md bg-surface text-text", className), ...props })));
7
7
  Command.displayName = CommandPrimitive.displayName;
8
8
  const CommandDialog = ({ children, shouldFilter, dialogTitle = "Search", ...props }) => {
9
- return (_jsx(Dialog, { ...props, children: _jsxs(DialogContent, { className: "overflow-hidden p-0 shadow-lg", children: [_jsx(DialogTitle, { className: "sr-only", children: dialogTitle }), _jsx(Command, { shouldFilter: shouldFilter, className: cn("[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-text-muted", "[&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2", "[&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5", "[&_[cmdk-input]]:h-12", "[&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3", "[&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"), children: children })] }) }));
9
+ return (_jsx(Dialog, { ...props, children: _jsxs(DialogContent, { className: "overflow-hidden p-0 shadow-lg", children: [_jsx(DialogTitle, { className: "sr-only", children: dialogTitle }), _jsx(Command, { shouldFilter: shouldFilter, className: cn("[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-text-muted", "[&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2", "[&_[cmdk-input]]:h-12", "[&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3", "[&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"), children: children })] }) }));
10
10
  };
11
- const CommandInput = React.forwardRef(({ className, ...props }, ref) => (_jsxs("div", { className: "flex items-center border-b border-border px-3", "cmdk-input-wrapper": "", children: [_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", className: "mr-2 h-4 w-4 shrink-0 opacity-50", children: [_jsx("circle", { cx: "11", cy: "11", r: "8" }), _jsx("path", { d: "m21 21-4.3-4.3" })] }), _jsx(CommandPrimitive.Input, { ref: ref, className: cn("flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-text-muted disabled:cursor-not-allowed disabled:opacity-50", className), ...props })] })));
11
+ const CommandInput = React.forwardRef(({ className, ...props }, ref) => (_jsxs("div", { className: "flex items-center border-b border-border px-3", "cmdk-input-wrapper": "", children: [_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", className: "mr-2 h-4 w-4 shrink-0 opacity-50", children: [_jsx("circle", { cx: "11", cy: "11", r: "8" }), _jsx("path", { d: "m21 21-4.3-4.3" })] }), _jsx(CommandPrimitive.Input, { ref: ref, className: cn("flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none focus-visible:outline-none placeholder:text-text-muted disabled:cursor-not-allowed disabled:opacity-50", className), ...props })] })));
12
12
  CommandInput.displayName = CommandPrimitive.Input.displayName;
13
13
  const CommandList = React.forwardRef(({ className, ...props }, ref) => (_jsx(CommandPrimitive.List, { ref: ref, className: cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className), ...props })));
14
14
  CommandList.displayName = CommandPrimitive.List.displayName;
package/dist/ui/dialog.js CHANGED
@@ -6,9 +6,9 @@ const Dialog = DialogPrimitive.Root;
6
6
  const DialogTrigger = DialogPrimitive.Trigger;
7
7
  const DialogPortal = DialogPrimitive.Portal;
8
8
  const DialogClose = DialogPrimitive.Close;
9
- const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Overlay, { ref: ref, className: cn("fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", className), ...props })));
9
+ const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Overlay, { ref: ref, className: cn("fixed inset-0 z-50 bg-black/60 backdrop-blur-sm transition-opacity duration-150 data-[state=open]:opacity-100 data-[state=closed]:opacity-0", className), ...props })));
10
10
  DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
11
- const DialogContent = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Content, { ref: ref, className: cn("fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-border bg-surface 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", className), ...props, children: [children, _jsxs(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-surface transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-hover-bg data-[state=open]:text-text-muted", children: [_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M18 6 6 18" }), _jsx("path", { d: "m6 6 12 12" })] }), _jsx("span", { className: "sr-only", children: "Close" })] })] })] })));
11
+ const DialogContent = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Content, { ref: ref, className: cn("fixed left-[50%] top-[20%] z-50 grid w-full max-w-lg translate-x-[-50%] gap-4 border border-border bg-surface p-6 shadow-2xl sm:rounded-xl", "transition-all duration-150 ease-out", "data-[state=open]:opacity-100 data-[state=open]:scale-100", "data-[state=closed]:opacity-0 data-[state=closed]:scale-[0.98]", className), ...props, children: [children, _jsxs(DialogPrimitive.Close, { className: "absolute right-3 top-3 rounded-sm opacity-70 ring-offset-surface transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-hover-bg data-[state=open]:text-text-muted", children: [_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M18 6 6 18" }), _jsx("path", { d: "m6 6 12 12" })] }), _jsx("span", { className: "sr-only", children: "Close" })] })] })] })));
12
12
  DialogContent.displayName = DialogPrimitive.Content.displayName;
13
13
  const DialogHeader = ({ className, ...props }) => (_jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props }));
14
14
  DialogHeader.displayName = "DialogHeader";
@@ -13,7 +13,7 @@ export interface HighlightOptions {
13
13
  highlightLines?: number[];
14
14
  }
15
15
  /**
16
- * Syntax-highlight `code` using Shiki dual-theme (github-light / github-dark).
16
+ * Syntax-highlight `code` using Shiki dual-theme (notdiamond-light / notdiamond-dark).
17
17
  * Returns raw HTML string with CSS variable tokens — ready for `set:html`.
18
18
  */
19
19
  export declare function highlight(code: string, lang: string, options?: HighlightOptions): Promise<string>;
@@ -9,6 +9,8 @@
9
9
  * inline colors — matching the fenced code block rendering path.
10
10
  */
11
11
  import { createHighlighter } from "shiki";
12
+ import notdiamondDark from "../themes/notdiamond-dark.json";
13
+ import notdiamondLight from "../themes/notdiamond-light.json";
12
14
  let highlighter = null;
13
15
  /**
14
16
  * Common language shorthand aliases that Shiki may not auto-resolve.
@@ -25,13 +27,13 @@ const LANG_ALIASES = {
25
27
  mdx: "markdown",
26
28
  };
27
29
  /**
28
- * Syntax-highlight `code` using Shiki dual-theme (github-light / github-dark).
30
+ * Syntax-highlight `code` using Shiki dual-theme (notdiamond-light / notdiamond-dark).
29
31
  * Returns raw HTML string with CSS variable tokens — ready for `set:html`.
30
32
  */
31
33
  export async function highlight(code, lang, options) {
32
34
  if (!highlighter) {
33
35
  highlighter = await createHighlighter({
34
- themes: ["github-light", "github-dark"],
36
+ themes: [notdiamondLight, notdiamondDark],
35
37
  langs: [
36
38
  "typescript",
37
39
  "javascript",
@@ -76,7 +78,7 @@ export async function highlight(code, lang, options) {
76
78
  }));
77
79
  return highlighter.codeToHtml(code, {
78
80
  lang,
79
- themes: { light: "github-light", dark: "github-dark" },
81
+ themes: { light: "notdiamond-light", dark: "notdiamond-dark" },
80
82
  defaultColor: false,
81
83
  ...(decorations?.length ? { decorations } : {}),
82
84
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@specglass/theme-default",
3
- "version": "0.0.9",
3
+ "version": "0.0.11",
4
4
  "description": "Default theme for Specglass — layouts, components, React islands, and styles",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -25,7 +25,8 @@
25
25
  "./styles/*": "./src/styles/*",
26
26
  "./utils/*": "./src/utils/*",
27
27
  "./ui/*": "./src/ui/*",
28
- "./scripts/*": "./src/scripts/*"
28
+ "./scripts/*": "./src/scripts/*",
29
+ "./themes/*": "./src/themes/*"
29
30
  },
30
31
  "files": [
31
32
  "dist",
@@ -36,7 +37,8 @@
36
37
  "src/styles",
37
38
  "src/utils",
38
39
  "src/ui",
39
- "src/scripts"
40
+ "src/scripts",
41
+ "src/themes"
40
42
  ],
41
43
  "scripts": {
42
44
  "build": "tsc",
@@ -19,6 +19,16 @@ const schemeTypeLabels: Record<string, string> = {
19
19
  openIdConnect: "OpenID Connect",
20
20
  };
21
21
 
22
+ const schemeTypeColors: Record<string, string> = {
23
+ apiKey: "bg-amber-500/15 text-amber-700 dark:text-amber-400 border-amber-500/30",
24
+ http: "bg-emerald-500/15 text-emerald-700 dark:text-emerald-400 border-emerald-500/30",
25
+ oauth2: "bg-blue-500/15 text-blue-700 dark:text-blue-400 border-blue-500/30",
26
+ openIdConnect: "bg-purple-500/15 text-purple-700 dark:text-purple-400 border-purple-500/30",
27
+ };
28
+
29
+ const defaultBadgeColor =
30
+ "bg-purple-500/15 text-purple-700 dark:text-purple-400 border-purple-500/30";
31
+
22
32
  const hasAuth = security.length > 0;
23
33
  const hasGlobalSchemes = securitySchemes && Object.keys(securitySchemes).length > 0;
24
34
  ---
@@ -26,8 +36,15 @@ const hasGlobalSchemes = securitySchemes && Object.keys(securitySchemes).length
26
36
  {
27
37
  (hasAuth || hasGlobalSchemes) && (
28
38
  <div class="mb-8">
29
- <h3 class="text-sm font-semibold text-text-muted uppercase tracking-wider mb-3">
30
- <span class="mr-1.5">🔒</span> Authentication
39
+ <h3 class="text-sm font-semibold text-text-muted uppercase tracking-wider mb-3 flex items-center gap-1.5">
40
+ <svg class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
41
+ <path
42
+ fill-rule="evenodd"
43
+ d="M10 1a4.5 4.5 0 00-4.5 4.5V9H5a2 2 0 00-2 2v6a2 2 0 002 2h10a2 2 0 002-2v-6a2 2 0 00-2-2h-.5V5.5A4.5 4.5 0 0010 1zm3 8V5.5a3 3 0 10-6 0V9h6z"
44
+ clip-rule="evenodd"
45
+ />
46
+ </svg>
47
+ Authentication
31
48
  </h3>
32
49
 
33
50
  {/* Per-endpoint security requirements */}
@@ -44,7 +61,12 @@ const hasGlobalSchemes = securitySchemes && Object.keys(securitySchemes).length
44
61
  ]}
45
62
  >
46
63
  {/* Scheme type badge */}
47
- <span class="inline-flex shrink-0 items-center px-2 py-0.5 rounded text-xs font-medium bg-purple-500/15 text-purple-700 dark:text-purple-400 border border-purple-500/30 mt-0.5">
64
+ <span
65
+ class:list={[
66
+ "inline-flex shrink-0 items-center px-2 py-0.5 rounded-full text-xs font-medium border mt-0.5",
67
+ schemeTypeColors[req.type] ?? defaultBadgeColor,
68
+ ]}
69
+ >
48
70
  {schemeTypeLabels[req.type] ?? req.type}
49
71
  </span>
50
72
 
@@ -93,7 +115,12 @@ const hasGlobalSchemes = securitySchemes && Object.keys(securitySchemes).length
93
115
  idx > 0 && "border-t border-border/50",
94
116
  ]}
95
117
  >
96
- <span class="inline-flex shrink-0 items-center px-2 py-0.5 rounded text-xs font-medium bg-purple-500/15 text-purple-700 dark:text-purple-400 border border-purple-500/30 mt-0.5">
118
+ <span
119
+ class:list={[
120
+ "inline-flex shrink-0 items-center px-2 py-0.5 rounded-full text-xs font-medium border mt-0.5",
121
+ schemeTypeColors[scheme.type] ?? defaultBadgeColor,
122
+ ]}
123
+ >
97
124
  {schemeTypeLabels[scheme.type] ?? scheme.type}
98
125
  </span>
99
126
  <div class="min-w-0">
@@ -24,52 +24,75 @@ const methodColors: Record<string, string> = {
24
24
  const methodColor = methodColors[endpoint.method.toLowerCase()] ?? methodColors.get;
25
25
  ---
26
26
 
27
- <div id={`endpoint-${endpoint.method}-${endpoint.path.replace(/[{}\\/]/g, "-")}`} class="mb-8">
28
- {/* Deprecated banner */}
29
- {
30
- endpoint.deprecated && (
31
- <div class="mb-4 rounded-lg border border-amber-500/30 bg-amber-500/10 px-4 py-3 text-amber-700 dark:text-amber-300 text-sm">
32
- <span class="font-semibold">⚠ Deprecated</span> — This endpoint is deprecated and may be
33
- removed in a future version.
34
- </div>
35
- )
36
- }
37
-
38
- {/* Method + Path header */}
39
- <div class="flex items-center gap-3 mb-4">
40
- <span
41
- class:list={[
42
- "inline-flex items-center px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider border",
43
- methodColor,
44
- ]}
45
- >
46
- {endpoint.method.toUpperCase()}
47
- </span>
48
- <code class="text-lg font-mono text-text font-semibold break-all">
49
- {endpoint.path}
50
- </code>
27
+ <div
28
+ id={`endpoint-${endpoint.method}-${endpoint.path.replace(/[{}\\\/]/g, "-")}`}
29
+ class="mb-8 rounded-lg border border-border bg-surface-1 overflow-hidden"
30
+ >
31
+ {/* Method color accent bar at top */}
32
+ <div
33
+ class:list={[
34
+ "h-1",
35
+ {
36
+ "bg-emerald-500": endpoint.method.toLowerCase() === "get",
37
+ "bg-blue-500": endpoint.method.toLowerCase() === "post",
38
+ "bg-amber-500":
39
+ endpoint.method.toLowerCase() === "put" || endpoint.method.toLowerCase() === "patch",
40
+ "bg-red-500": endpoint.method.toLowerCase() === "delete",
41
+ "bg-purple-500": endpoint.method.toLowerCase() === "options",
42
+ "bg-gray-500": endpoint.method.toLowerCase() === "head",
43
+ },
44
+ ]}
45
+ aria-hidden="true"
46
+ >
51
47
  </div>
52
48
 
53
- {/* Summary */}
54
- {
55
- endpoint.summary && (
56
- <h1 class="text-xl font-semibold text-text mb-2 mt-0">{endpoint.summary}</h1>
57
- )
58
- }
49
+ <div class="p-6">
50
+ {/* Deprecated banner */}
51
+ {
52
+ endpoint.deprecated && (
53
+ <div class="mb-4 rounded-lg border border-amber-500/30 bg-amber-500/10 px-4 py-3 text-amber-700 dark:text-amber-300 text-sm">
54
+ <span class="font-semibold">⚠ Deprecated</span> — This endpoint is deprecated and may be
55
+ removed in a future version.
56
+ </div>
57
+ )
58
+ }
59
+
60
+ {/* Method + Path header */}
61
+ <div class="flex items-center gap-3 mb-4">
62
+ <span
63
+ class:list={[
64
+ "inline-flex items-center px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider border",
65
+ methodColor,
66
+ ]}
67
+ >
68
+ {endpoint.method.toUpperCase()}
69
+ </span>
70
+ <code class="text-lg font-mono text-text font-semibold break-all">
71
+ {endpoint.path}
72
+ </code>
73
+ </div>
59
74
 
60
- {/* Description */}
61
- {
62
- endpoint.description && (
63
- <p class="text-text-muted text-sm leading-relaxed mb-4">{endpoint.description}</p>
64
- )
65
- }
75
+ {/* Summary */}
76
+ {
77
+ endpoint.summary && (
78
+ <h1 class="text-xl font-semibold text-text mb-2 mt-0">{endpoint.summary}</h1>
79
+ )
80
+ }
66
81
 
67
- {/* Operation ID */}
68
- {
69
- endpoint.operationId && (
70
- <p class="text-xs text-text-muted/60 font-mono mb-4">
71
- Operation ID: <code class="text-text-muted/80">{endpoint.operationId}</code>
72
- </p>
73
- )
74
- }
82
+ {/* Description */}
83
+ {
84
+ endpoint.description && (
85
+ <p class="text-text-muted text-sm leading-relaxed mb-4">{endpoint.description}</p>
86
+ )
87
+ }
88
+
89
+ {/* Operation ID */}
90
+ {
91
+ endpoint.operationId && (
92
+ <p class="text-xs text-text-muted/60 font-mono mb-0">
93
+ Operation ID: <code class="text-text-muted/80">{endpoint.operationId}</code>
94
+ </p>
95
+ )
96
+ }
97
+ </div>
75
98
  </div>
@@ -45,7 +45,7 @@ const methodBadgeColors: Record<string, string> = {
45
45
  data-api-nav-group={tag}
46
46
  >
47
47
  <svg
48
- class="h-3 w-3 shrink-0 transition-transform"
48
+ class="h-3 w-3 shrink-0 rotate-90"
49
49
  viewBox="0 0 12 12"
50
50
  fill="currentColor"
51
51
  aria-hidden="true"
@@ -66,10 +66,10 @@ const methodBadgeColors: Record<string, string> = {
66
66
  <a
67
67
  href={`${basePath}/${slug}`}
68
68
  class:list={[
69
- "flex items-center gap-2 px-3 py-1.5 rounded-md text-xs transition-colors group",
69
+ "flex items-center gap-2 px-3 py-1.5 rounded-md text-xs group",
70
70
  isActive
71
- ? "bg-primary/10 text-primary font-medium"
72
- : "text-text-muted hover:bg-surface-raised hover:text-text",
71
+ ? "bg-surface-2 text-text font-medium"
72
+ : "text-text-muted hover:bg-surface-2 hover:text-text",
73
73
  ]}
74
74
  aria-current={isActive ? "page" : undefined}
75
75
  >
@@ -100,7 +100,7 @@ const methodBadgeColors: Record<string, string> = {
100
100
  data-api-nav-group="unsupported"
101
101
  >
102
102
  <svg
103
- class="h-3 w-3 shrink-0 transition-transform rotate-90"
103
+ class="h-3 w-3 shrink-0 rotate-90"
104
104
  viewBox="0 0 12 12"
105
105
  fill="currentColor"
106
106
  aria-hidden="true"
@@ -124,10 +124,10 @@ const methodBadgeColors: Record<string, string> = {
124
124
  <a
125
125
  href={`${basePath}/${slug}`}
126
126
  class:list={[
127
- "flex items-center gap-2 px-3 py-1.5 rounded-md text-xs transition-colors group",
127
+ "flex items-center gap-2 px-3 py-1.5 rounded-md text-xs group border-l-2",
128
128
  isActive
129
- ? "bg-amber-500/10 text-amber-700 dark:text-amber-400 font-medium"
130
- : "text-text-muted/60 hover:bg-surface-raised hover:text-text-muted",
129
+ ? "bg-amber-500/10 text-amber-700 dark:text-amber-400 font-medium border-amber-500"
130
+ : "text-text-muted/60 hover:bg-surface-raised hover:text-text-muted border-transparent",
131
131
  ]}
132
132
  aria-current={isActive ? "page" : undefined}
133
133
  title={`Unsupported: ${err.reason}`}
@@ -170,8 +170,5 @@ const methodBadgeColors: Record<string, string> = {
170
170
  arrow?.classList.toggle("rotate-90", !isHidden);
171
171
  }
172
172
  });
173
- // Default to expanded
174
- const arrow = btn.querySelector("svg");
175
- arrow?.classList.add("rotate-90");
176
173
  });
177
174
  </script>