radiant-docs 0.1.37 → 0.1.38

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 (38) hide show
  1. package/package.json +1 -1
  2. package/template/astro.config.mjs +2 -0
  3. package/template/src/components/Footer.astro +1 -1
  4. package/template/src/components/Header.astro +8 -8
  5. package/template/src/components/OpenApiPage.astro +18 -18
  6. package/template/src/components/Search.astro +18 -18
  7. package/template/src/components/Sidebar.astro +4 -2
  8. package/template/src/components/SidebarDropdown.astro +82 -79
  9. package/template/src/components/SidebarSegmented.astro +5 -5
  10. package/template/src/components/TableOfContents.astro +24 -15
  11. package/template/src/components/ThemeSwitcher.astro +15 -8
  12. package/template/src/components/chat/AskAiWidget.tsx +4 -3
  13. package/template/src/components/endpoint/PlaygroundBar.astro +3 -3
  14. package/template/src/components/endpoint/PlaygroundButton.astro +2 -2
  15. package/template/src/components/endpoint/PlaygroundField.astro +53 -53
  16. package/template/src/components/endpoint/PlaygroundForm.astro +38 -22
  17. package/template/src/components/endpoint/RequestSnippets.astro +54 -21
  18. package/template/src/components/endpoint/ResponseDisplay.astro +24 -24
  19. package/template/src/components/endpoint/ResponseFieldTree.astro +12 -12
  20. package/template/src/components/endpoint/ResponseFields.astro +19 -19
  21. package/template/src/components/endpoint/ResponseSnippets.astro +66 -29
  22. package/template/src/components/ui/CodeTabEdge.astro +6 -4
  23. package/template/src/components/ui/Field.astro +7 -7
  24. package/template/src/components/ui/demo/Demo.astro +1 -1
  25. package/template/src/components/user/Accordion.astro +3 -3
  26. package/template/src/components/user/Callout.astro +8 -8
  27. package/template/src/components/user/CodeBlock.astro +57 -22
  28. package/template/src/components/user/CodeGroup.astro +14 -10
  29. package/template/src/components/user/ComponentPreviewBlock.astro +38 -12
  30. package/template/src/components/user/Image.astro +2 -2
  31. package/template/src/components/user/Step.astro +4 -4
  32. package/template/src/components/user/Tab.astro +1 -1
  33. package/template/src/components/user/Tabs.astro +15 -20
  34. package/template/src/layouts/Layout.astro +1 -1
  35. package/template/src/lib/code/code-block.ts +150 -15
  36. package/template/src/lib/mdx/remark-resolve-internal-links.ts +639 -0
  37. package/template/src/pages/404.astro +44 -0
  38. package/template/src/styles/global.css +28 -19
@@ -116,25 +116,58 @@ function parseHighlightedLineNumbers(
116
116
 
117
117
  function buildTokenStyle(token: {
118
118
  color?: string;
119
+ darkColor?: string;
119
120
  bgColor?: string;
121
+ darkBgColor?: string;
120
122
  fontStyle?: number;
121
123
  htmlStyle?: Record<string, string>;
124
+ darkHtmlStyle?: Record<string, string>;
122
125
  }): string | undefined {
123
126
  const styleSegments: string[] = [];
124
127
 
125
- if (token.color) styleSegments.push(`color:${token.color}`);
126
- if (token.bgColor) styleSegments.push(`background-color:${token.bgColor}`);
128
+ const pushStyleVariable = (property: string, value?: string) => {
129
+ if (value) styleSegments.push(`${property}:${value}`);
130
+ };
131
+
132
+ pushStyleVariable("--rd-token-color", token.color);
133
+ pushStyleVariable("--rd-token-color-dark", token.darkColor);
134
+ pushStyleVariable("--rd-token-bg", token.bgColor);
135
+ pushStyleVariable("--rd-token-bg-dark", token.darkBgColor);
127
136
 
128
137
  const fontStyle = typeof token.fontStyle === "number" ? token.fontStyle : 0;
129
138
  if ((fontStyle & 1) === 1) styleSegments.push("font-style:italic");
130
139
  if ((fontStyle & 2) === 2) styleSegments.push("font-weight:600");
131
140
  if ((fontStyle & 4) === 4) styleSegments.push("text-decoration:underline");
132
141
 
133
- if (token.htmlStyle && typeof token.htmlStyle === "object") {
134
- for (const [property, value] of Object.entries(token.htmlStyle)) {
142
+ const pushHtmlStyle = (
143
+ styleObject: Record<string, string> | undefined,
144
+ isDarkStyle: boolean,
145
+ ) => {
146
+ if (!styleObject || typeof styleObject !== "object") return;
147
+
148
+ for (const [property, value] of Object.entries(styleObject)) {
149
+ const normalizedProperty = property.trim().toLowerCase();
150
+ if (normalizedProperty === "color") {
151
+ pushStyleVariable(
152
+ isDarkStyle ? "--rd-token-color-dark" : "--rd-token-color",
153
+ value,
154
+ );
155
+ continue;
156
+ }
157
+ if (normalizedProperty === "background-color") {
158
+ pushStyleVariable(
159
+ isDarkStyle ? "--rd-token-bg-dark" : "--rd-token-bg",
160
+ value,
161
+ );
162
+ continue;
163
+ }
164
+
135
165
  styleSegments.push(`${property}:${value}`);
136
166
  }
137
- }
167
+ };
168
+
169
+ pushHtmlStyle(token.htmlStyle, false);
170
+ pushHtmlStyle(token.darkHtmlStyle, true);
138
171
 
139
172
  if (!styleSegments.length) return undefined;
140
173
  return styleSegments.join(";");
@@ -198,7 +231,7 @@ const renderedCodeLinesHtml = normalizedTokenLines
198
231
  const tokenStyleAttribute = tokenStyle
199
232
  ? ` style="${escapeAttribute(tokenStyle)}"`
200
233
  : "";
201
- return `<span${tokenStyleAttribute}>${escapeHtml(token.content)}</span>`;
234
+ return `<span data-rd-token${tokenStyleAttribute}>${escapeHtml(token.content)}</span>`;
202
235
  })
203
236
  .join("")
204
237
  : fallbackLineContent.length > 0
@@ -206,14 +239,14 @@ const renderedCodeLinesHtml = normalizedTokenLines
206
239
  : "&nbsp;";
207
240
 
208
241
  const lineNumberHtml = parsedShowLineNumbers
209
- ? `<span class="w-10 shrink-0 select-none pl-4 pr-3 text-right tabular-nums text-neutral-400">${lineNumber}</span>`
242
+ ? `<span class="w-10 shrink-0 select-none pl-4 pr-3 text-right tabular-nums text-neutral-400 dark:text-neutral-500">${lineNumber}</span>`
210
243
  : "";
211
244
 
212
245
  const lineContentClass = parsedShowLineNumbers
213
246
  ? "flex-1 whitespace-pre pr-4"
214
247
  : "flex-1 whitespace-pre pr-4 pl-4";
215
248
  const lineClass = isHighlighted
216
- ? "flex min-w-full bg-neutral-100/80"
249
+ ? "flex min-w-full bg-neutral-100/80 dark:bg-neutral-800/70"
217
250
  : "flex min-w-full";
218
251
 
219
252
  return `<span class="${lineClass}">${lineNumberHtml}<span class="${lineContentClass}">${tokenHtml}</span></span>`;
@@ -238,18 +271,18 @@ const renderedCodeLinesHtml = normalizedTokenLines
238
271
  >
239
272
  <div
240
273
  class:list={[
241
- "w-full max-w-full min-w-0 overflow-hidden border border-neutral-200 bg-white shadow-xs",
274
+ "w-full max-w-full min-w-0 overflow-hidden border border-neutral-200 bg-white shadow-xs dark:border-neutral-800 dark:bg-(--rd-code-surface)",
242
275
  parsedInCodeGroup ? "rounded-t-none rounded-b-xl" : "rounded-xl",
243
276
  ]}
244
277
  >
245
278
  {
246
279
  !parsedInCodeGroup && parsedShowFilename ? (
247
- <div class="flex items-center justify-between gap-2 border-b border-neutral-200 bg-neutral-50 inset-shadow-sm inset-shadow-neutral-100/80">
280
+ <div class="flex items-center justify-between gap-2 border-b border-neutral-200 bg-neutral-50 inset-shadow-sm inset-shadow-neutral-100/80 dark:border-neutral-800 dark:bg-neutral-900/60 dark:inset-shadow-neutral-900/80">
248
281
  <div class="min-w-0 flex-1">
249
- <div class="relative h-9 w-fit max-w-full rounded-tl-xl bg-white">
250
- <div class="absolute inset-x-0 -bottom-px h-px bg-white" />
282
+ <div class="relative h-9 w-fit max-w-full rounded-tl-xl bg-white dark:bg-(--rd-code-surface)">
283
+ <div class="absolute inset-x-0 -bottom-px h-px bg-white dark:bg-(--rd-code-surface)" />
251
284
  <CodeTabEdge className="pointer-events-none absolute -top-px left-full z-10 h-[calc(100%+2px)]" />
252
- <div class="relative z-20 inline-flex h-9 max-w-full items-center gap-2 pl-5 py-1.5 text-xs font-medium text-neutral-700">
285
+ <div class="relative z-20 inline-flex h-9 max-w-full items-center gap-2 pl-5 py-1.5 text-xs font-medium text-neutral-700 dark:text-neutral-300">
253
286
  {shouldRenderLanguageIcon ? (
254
287
  <CodeLanguageIcon
255
288
  language={normalizedLanguage}
@@ -261,12 +294,12 @@ const renderedCodeLinesHtml = normalizedTokenLines
261
294
  </div>
262
295
  </div>
263
296
  </div>
264
- <div class="relative h-9 w-5 shrink-0 rounded-tr-xl bg-white">
265
- <div class="absolute inset-x-0 -bottom-px h-px bg-white" />
297
+ <div class="relative h-9 w-5 shrink-0 rounded-tr-xl bg-white dark:bg-(--rd-code-surface)">
298
+ <div class="absolute inset-x-0 -bottom-px h-px bg-white dark:bg-(--rd-code-surface)" />
266
299
  <CodeTabEdge className="pointer-events-none absolute -top-px right-full z-10 h-[calc(100%+2px)] rotate-y-180" />
267
300
  <button
268
301
  type="button"
269
- class="absolute right-2 top-1/2 z-20 inline-flex size-7 -translate-y-1/2 appearance-none items-center justify-center rounded-md border-0 bg-transparent text-neutral-500/80 shadow-none outline-none ring-0 transition-colors duration-150 hover:bg-neutral-50 hover:text-neutral-600 focus:outline-none focus-visible:outline-none focus:ring-0 focus-visible:ring-0 cursor-pointer"
302
+ class="absolute right-2 top-1/2 z-20 inline-flex size-7 -translate-y-1/2 appearance-none items-center justify-center rounded-md border-0 bg-transparent text-neutral-500/80 shadow-none outline-none ring-0 transition-colors duration-150 hover:bg-neutral-50 hover:text-neutral-600 focus:outline-none focus-visible:outline-none focus:ring-0 focus-visible:ring-0 cursor-pointer dark:text-neutral-400 dark:hover:bg-neutral-800 dark:hover:text-neutral-200"
270
303
  data-rd-copy-trigger="true"
271
304
  data-rd-copy-content={encodedRaw}
272
305
  aria-label="Copy code"
@@ -279,7 +312,7 @@ const renderedCodeLinesHtml = normalizedTokenLines
279
312
  />
280
313
  <Icon
281
314
  name="lucide:check"
282
- class="absolute size-3.5 stroke-3 origin-center scale-25 rotate-6 opacity-0 text-green-700/80 transition-all duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-transform motion-reduce:transition-none"
315
+ class="absolute size-3.5 stroke-3 origin-center scale-25 rotate-6 opacity-0 text-green-700/80 transition-all duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-transform motion-reduce:transition-none dark:text-green-400/90"
283
316
  data-rd-copy-check
284
317
  aria-hidden="true"
285
318
  />
@@ -295,7 +328,7 @@ const renderedCodeLinesHtml = normalizedTokenLines
295
328
  <div class="pointer-events-none absolute right-2 top-2 z-20">
296
329
  <button
297
330
  type="button"
298
- class="pointer-events-auto inline-flex size-7 appearance-none items-center justify-center rounded-md border border-neutral-200/80 text-neutral-500/80 bg-white/80 backdrop-blur-xs outline-none ring-0 transition-colors duration-150 hover:bg-neutral-50 hover:text-neutral-600 focus:outline-none focus-visible:outline-none focus:ring-0 focus-visible:ring-0 cursor-pointer"
331
+ class="pointer-events-auto inline-flex size-7 appearance-none items-center justify-center rounded-md border border-neutral-200/80 text-neutral-500/80 bg-white/80 backdrop-blur-xs outline-none ring-0 transition-colors duration-150 hover:bg-neutral-50 hover:text-neutral-600 focus:outline-none focus-visible:outline-none focus:ring-0 focus-visible:ring-0 cursor-pointer dark:border-neutral-700/50 dark:bg-(--rd-code-surface) dark:text-neutral-400 dark:hover:bg-neutral-800 dark:hover:text-neutral-200"
299
332
  data-rd-copy-trigger="true"
300
333
  data-rd-copy-content={encodedRaw}
301
334
  aria-label="Copy code"
@@ -308,7 +341,7 @@ const renderedCodeLinesHtml = normalizedTokenLines
308
341
  />
309
342
  <Icon
310
343
  name="lucide:check"
311
- class="absolute size-3.5 stroke-3 origin-center scale-25 rotate-6 opacity-0 text-green-700/80 transition-all duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-transform motion-reduce:transition-none"
344
+ class="absolute size-3.5 stroke-3 origin-center scale-25 rotate-6 opacity-0 text-green-700/80 transition-all duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-transform motion-reduce:transition-none dark:text-green-400/90"
312
345
  data-rd-copy-check
313
346
  aria-hidden="true"
314
347
  />
@@ -333,10 +366,10 @@ const renderedCodeLinesHtml = normalizedTokenLines
333
366
 
334
367
  <div
335
368
  data-rd-code-scroll-area
336
- class="relative overflow-x-auto [scrollbar-width:thin] [scrollbar-color:var(--color-neutral-300)_transparent] [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-neutral-300/70 hover:[&::-webkit-scrollbar-thumb]:bg-neutral-300/90"
369
+ class="relative overflow-x-auto [scrollbar-width:thin] [scrollbar-color:var(--color-neutral-300)_transparent] [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-neutral-300/70 hover:[&::-webkit-scrollbar-thumb]:bg-neutral-300/90 dark:[scrollbar-color:var(--color-neutral-700)_transparent] dark:[&::-webkit-scrollbar-thumb]:bg-neutral-700/70 dark:hover:[&::-webkit-scrollbar-thumb]:bg-neutral-700/90"
337
370
  >
338
371
  <pre
339
- class="relative m-0 min-w-full bg-white p-0 text-[13px] leading-6"><code class="block min-w-full py-2.5 font-mono text-neutral-800"><Fragment set:html={renderedCodeLinesHtml} /></code></pre>
372
+ class="relative m-0 min-w-full bg-white p-0 text-[13px] leading-6 dark:bg-(--rd-code-surface)"><code data-rd-code-theme class="block min-w-full py-2.5 font-mono text-neutral-800 dark:text-neutral-200"><Fragment set:html={renderedCodeLinesHtml} /></code></pre>
340
373
  </div>
341
374
  </div>
342
375
  </div>
@@ -348,7 +381,9 @@ const renderedCodeLinesHtml = normalizedTokenLines
348
381
  const root = script.closest("[data-rd-code-block-root='true']");
349
382
  if (!(root instanceof HTMLElement)) return;
350
383
 
351
- const copyButtons = root.querySelectorAll("[data-rd-copy-trigger='true']");
384
+ const copyButtons = root.querySelectorAll(
385
+ "[data-rd-copy-trigger='true']",
386
+ );
352
387
  if (copyButtons.length === 0) return;
353
388
 
354
389
  const setCopiedState = (button, copied) => {
@@ -8,7 +8,7 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
8
8
  data-rd-code-group-root="true"
9
9
  >
10
10
  <div
11
- class="relative z-10 overflow-visible rounded-t-xl border border-b-0 border-neutral-200 bg-neutral-50 inset-shadow-sm inset-shadow-neutral-100/80"
11
+ class="relative z-10 overflow-visible rounded-t-xl border border-b-0 border-neutral-200 bg-neutral-50 inset-shadow-sm inset-shadow-neutral-100/80 dark:border-neutral-800 dark:bg-neutral-900/60 dark:inset-shadow-neutral-900/80"
12
12
  >
13
13
  <div class="flex min-w-0 items-end justify-between gap-2">
14
14
  <div class="min-w-0 flex-1 overflow-hidden rounded-t-xl">
@@ -19,20 +19,25 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
19
19
  <div
20
20
  data-rd-code-group-pill
21
21
  aria-hidden="true"
22
- class="pointer-events-none absolute top-1/2 z-0 h-[28px] -translate-y-1/2 rounded-[9px] border-[0.5px] border-neutral-200 bg-white shadow-xs opacity-0 transition-[left,width,opacity] duration-200 ease-out"
22
+ class="pointer-events-none absolute top-1/2 z-0 h-[28px] -translate-y-1/2 rounded-[9px] border-[0.5px] border-neutral-200 bg-white shadow-xs opacity-0 transition-[left,width,opacity] duration-200 ease-out dark:border-neutral-700/70 dark:bg-(--rd-code-surface)"
23
23
  >
24
24
  </div>
25
25
  </div>
26
26
  </div>
27
27
 
28
- <div class="relative h-9 w-5 shrink-0 rounded-tr-xl bg-white">
29
- <div class="absolute inset-x-0 -bottom-px h-px bg-white"></div>
28
+ <div
29
+ class="relative h-9 w-5 shrink-0 rounded-tr-xl bg-white dark:bg-(--rd-code-surface)"
30
+ >
31
+ <div
32
+ class="absolute inset-x-0 -bottom-px h-px bg-white dark:bg-(--rd-code-surface)"
33
+ >
34
+ </div>
30
35
  <CodeTabEdge
31
36
  className="pointer-events-none absolute -top-px right-full z-10 h-[calc(100%+2px)] rotate-y-180"
32
37
  />
33
38
  <button
34
39
  type="button"
35
- class="absolute right-2 top-1/2 z-20 inline-flex size-7 -translate-y-1/2 appearance-none items-center justify-center rounded-md border-0 bg-transparent text-neutral-500/80 shadow-none outline-none ring-0 transition-colors duration-150 hover:bg-neutral-50 hover:text-neutral-600 focus:outline-none focus-visible:outline-none focus:ring-0 focus-visible:ring-0 cursor-pointer"
40
+ class="absolute right-2 top-1/2 z-20 inline-flex size-7 -translate-y-1/2 appearance-none items-center justify-center rounded-md border-0 bg-transparent text-neutral-500/80 shadow-none outline-none ring-0 transition-colors duration-150 hover:bg-neutral-50 hover:text-neutral-600 focus:outline-none focus-visible:outline-none focus:ring-0 focus-visible:ring-0 cursor-pointer dark:text-neutral-400 dark:hover:bg-neutral-800 dark:hover:text-neutral-200"
36
41
  data-rd-copy-trigger="true"
37
42
  aria-label="Copy code"
38
43
  >
@@ -44,7 +49,7 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
44
49
  />
45
50
  <Icon
46
51
  name="lucide:check"
47
- class="absolute size-3.5 stroke-3 origin-center scale-25 rotate-6 opacity-0 text-green-700/80 transition-all duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-transform motion-reduce:transition-none"
52
+ class="absolute size-3.5 stroke-3 origin-center scale-25 rotate-6 opacity-0 text-green-700/80 transition-all duration-250 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-transform motion-reduce:transition-none dark:text-green-400/90"
48
53
  data-rd-copy-check
49
54
  aria-hidden="true"
50
55
  />
@@ -118,8 +123,7 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
118
123
 
119
124
  const tabButton = document.createElement("button");
120
125
  tabButton.type = "button";
121
- tabButton.className =
122
- `relative inline-flex h-9 items-center border-0 bg-transparent px-3 py-1.5 text-xs font-medium text-neutral-600 transition-colors duration-150 focus:outline-none focus-visible:outline-none cursor-pointer ${hasTabIcon ? "gap-2" : ""}`;
126
+ tabButton.className = `relative inline-flex h-9 items-center border-0 bg-transparent px-3 py-1.5 text-xs font-medium text-muted-foreground transition-colors duration-150 focus:outline-none focus-visible:outline-none cursor-pointer ${hasTabIcon ? "gap-2" : ""}`;
123
127
  tabButton.setAttribute("aria-label", filename);
124
128
  tabButton.setAttribute("data-rd-code-group-tab", String(index));
125
129
 
@@ -172,8 +176,8 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
172
176
  tabs.forEach(({ itemElement, tabButton, iconContainer }, index) => {
173
177
  const isActive = index === activeIndex;
174
178
  itemElement.style.display = isActive ? "" : "none";
175
- tabButton.classList.toggle("text-neutral-900", isActive);
176
- tabButton.classList.toggle("text-neutral-600", !isActive);
179
+ tabButton.classList.toggle("text-foreground", isActive);
180
+ tabButton.classList.toggle("text-muted-foreground", !isActive);
177
181
 
178
182
  if (!iconContainer) return;
179
183
  iconContainer.classList.toggle("opacity-100", isActive);
@@ -64,12 +64,12 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
64
64
  data-rd-component-preview-root="true"
65
65
  >
66
66
  <div
67
- class="w-full max-w-full min-w-0 overflow-x-auto rounded-t-xl border border-b-0 border-neutral-200 bg-white p-4 xs:p-6 sm:p-12 shadow-xs [&>:first-child]:mt-0! [&>:last-child]:mb-0!"
67
+ class="w-full max-w-full min-w-0 overflow-x-auto rounded-t-xl border border-b-0 bg-white dark:bg-neutral-800/15 p-4 xs:p-6 sm:p-12 shadow-xs [&>:first-child]:mt-0! [&>:last-child]:mb-0!"
68
68
  >
69
69
  <slot />
70
70
  </div>
71
71
  <div
72
- class="rd-component-preview__code not-prose relative"
72
+ class="rd-component-preview__code not-prose relative overflow-hidden rounded-b-xl bg-white dark:bg-(--rd-code-surface)"
73
73
  data-rd-preview-expanded={isInitiallyExpanded ? "true" : "false"}
74
74
  style={{ "--rd-preview-visible-lines": String(visibleLines) }}
75
75
  >
@@ -84,17 +84,19 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
84
84
  collapsedLines={collapsedLines}
85
85
  />
86
86
  <div
87
- class="rd-component-preview__overlay pointer-events-none absolute inset-x-px inset-y-px hidden items-end justify-center rounded-b-xl bg-linear-to-t from-neutral-50/90 to-neutral-50/30 pb-4"
87
+ class="rd-component-preview__overlay pointer-events-none absolute inset-x-px inset-y-px hidden items-end justify-center rounded-b-xl pb-4"
88
88
  data-rd-preview-overlay
89
89
  aria-hidden="true"
90
90
  >
91
- <button
92
- type="button"
93
- class="pointer-events-auto inline-flex h-8 items-center justify-center rounded-md border border-neutral-200 bg-white px-3 text-sm font-medium text-neutral-700 shadow-md shadow-neutral-200 transition-colors duration-150 hover:bg-neutral-50 cursor-pointer"
94
- data-rd-preview-expand
95
- >
96
- View code
97
- </button>
91
+ <div class="bg-white dark:bg-neutral-800">
92
+ <button
93
+ type="button"
94
+ class="pointer-events-auto inline-flex h-8 items-center justify-center rounded-md border border-neutral-200 bg-white px-3 text-sm font-medium text-neutral-700 shadow-xl transition-colors duration-150 hover:bg-neutral-50 cursor-pointer dark:border-neutral-700 dark:bg-neutral-700/30 dark:text-neutral-200 dark:hover:bg-neutral-700/50"
95
+ data-rd-preview-expand
96
+ >
97
+ View code
98
+ </button>
99
+ </div>
98
100
  </div>
99
101
  </div>
100
102
  </div>
@@ -140,19 +142,43 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
140
142
  }
141
143
 
142
144
  .rd-component-preview__code :global(.group\/prose-code > div) {
143
- background-color: var(--color-neutral-50) !important;
145
+ background-color: #fff !important;
144
146
  border-top-left-radius: 0 !important;
145
147
  border-top-right-radius: 0 !important;
146
148
  }
147
149
 
150
+ :global(.dark) .rd-component-preview__code :global(.group\/prose-code > div) {
151
+ background-color: var(--rd-code-surface) !important;
152
+ }
153
+
148
154
  .rd-component-preview__code :global(.group\/prose-code pre),
149
155
  .rd-component-preview__code :global(.group\/prose-code code) {
150
- background-color: var(--color-neutral-50) !important;
156
+ background-color: #fff !important;
157
+ }
158
+
159
+ :global(.dark) .rd-component-preview__code :global(.group\/prose-code pre),
160
+ :global(.dark) .rd-component-preview__code :global(.group\/prose-code code) {
161
+ background-color: var(--rd-code-surface) !important;
151
162
  }
152
163
 
153
164
  .rd-component-preview__code[data-rd-preview-expanded="false"]
154
165
  .rd-component-preview__overlay {
155
166
  display: flex;
167
+ background: linear-gradient(
168
+ to top,
169
+ rgb(250 250 250 / 90%),
170
+ rgb(250 250 250 / 30%)
171
+ );
172
+ }
173
+
174
+ :global(.dark)
175
+ .rd-component-preview__code[data-rd-preview-expanded="false"]
176
+ .rd-component-preview__overlay {
177
+ background: linear-gradient(
178
+ to top,
179
+ color-mix(in srgb, var(--rd-code-surface) 90%, transparent),
180
+ color-mix(in srgb, var(--rd-code-surface) 35%, transparent)
181
+ );
156
182
  }
157
183
 
158
184
  .rd-component-preview__code :global([data-rd-code-scroll-area]) {
@@ -101,7 +101,7 @@ validateProps(
101
101
 
102
102
  <figure
103
103
  class:list={[
104
- "p-1.5 pb-1 xs:pb-1.5 group border border-neutral-200/80 dark:border-neutral-800 shadow-xs bg-neutral-50 dark:bg-neutral-900 rounded-2xl",
104
+ "p-1.5 pb-1 xs:pb-1.5 group border border-neutral-200 dark:border-neutral-800 shadow-xs bg-neutral-50 dark:bg-(--rd-code-surface) rounded-2xl",
105
105
  hasCustomImageWidth ? "w-fit max-w-full mx-auto" : "w-full",
106
106
  ]}
107
107
  x-data="{
@@ -204,7 +204,7 @@ validateProps(
204
204
  }"
205
205
  >
206
206
  <div
207
- class="overflow-hidden rounded-xl border border-neutral-200/50 dark:border-neutral-800/50 bg-neutral-100 dark:bg-black/20"
207
+ class="overflow-hidden rounded-xl border border-neutral-200 dark:border-neutral-800 bg-neutral-100 dark:bg-(--rd-code-surface)"
208
208
  >
209
209
  <img
210
210
  {...attrs}
@@ -14,24 +14,24 @@ validateProps(
14
14
  {
15
15
  title: { required: true, type: "string" },
16
16
  },
17
- Astro.url.pathname
17
+ Astro.url.pathname,
18
18
  );
19
19
  ---
20
20
 
21
21
  <div
22
22
  class:list={[
23
23
  "relative pl-10 step-item pb-4 last:pb-0 space-y-4",
24
- "before:absolute before:left-[10.5px] before:top-8 before:bottom-0 before:w-px before:bg-linear-[transparent,var(--color-neutral-200)_10%,var(--color-neutral-200)_90%,transparent]",
24
+ "before:absolute before:left-[10.5px] before:top-8 before:bottom-0 before:w-px before:bg-linear-[transparent,var(--color-neutral-200)_10%,var(--color-neutral-200)_90%,transparent] dark:before:bg-linear-[transparent,var(--color-neutral-700)_10%,var(--color-neutral-700)_90%,transparent]",
25
25
  ]}
26
26
  data-step-panel
27
27
  >
28
28
  <div
29
29
  class:list={[
30
30
  "flex items-center gap-1.5 not-prose",
31
- "step-number before:bg-neutral-900 before:size-[22px] before:rounded-full before:text-white before:flex before:items-center before:justify-center before:text-xs before:font-bold before:absolute before:left-px before:top-[3px] before:shadow-[inset_0_1px_0_rgb(255,255,255,0.2),0_0_0_1px_var(--color-neutral-800),var(--shadow-md)]",
31
+ "step-number before:size-6 before:bg-linear-to-b before:from-neutral-900/80 before:to-neutral-900 dark:before:from-neutral-100 dark:before:to-neutral-200 before:rounded-full before:text-white before:flex before:items-center before:justify-center before:text-xs before:font-bold dark:before:font-extrabold before:absolute before:left-px before:top-[3px] before:shadow-sm dark:before:bg-neutral-200 dark:before:text-neutral-900",
32
32
  ]}
33
33
  >
34
- <h3 class="text-lg font-semibold text-neutral-900">
34
+ <h3 class="text-lg font-semibold text-neutral-900 dark:text-neutral-100">
35
35
  {title}
36
36
  </h3>
37
37
  </div>
@@ -19,7 +19,7 @@ validateProps(
19
19
  ---
20
20
 
21
21
  <section data-label={label} data-icon={icon || ""}>
22
- <div class="*:m-0! *:mb-2">
22
+ <div class="*:first:mt-0! *:last:mb-0!">
23
23
  <slot />
24
24
  </div>
25
25
  </section>
@@ -3,16 +3,18 @@ import Icon from '../ui/Icon.astro';
3
3
 
4
4
  const html = await Astro.slots.render("default");
5
5
 
6
- const labelRegex = /label="([^"]+)"/g;
7
- const iconRegex = /icon="([^"]*)"/g;
6
+ const tabRegex = /<section\b([^>]*)\bdata-label="([^"]*)"([^>]*)>(.*?)<\/section>/gs;
7
+ const dataIconRegex = /\bdata-icon="([^"]*)"/;
8
8
  let labels = [];
9
9
  let icons = [];
10
+ let tabContents = [];
10
11
  let match;
11
- while ((match = labelRegex.exec(html)) !== null) {
12
- labels.push(match[1]);
13
- }
14
- while ((match = iconRegex.exec(html)) !== null) {
15
- icons.push(match[1]);
12
+ while ((match = tabRegex.exec(html)) !== null) {
13
+ const openingAttributes = `${match[1]} ${match[3]}`;
14
+ const iconMatch = openingAttributes.match(dataIconRegex);
15
+ labels.push(match[2]);
16
+ icons.push(iconMatch?.[1] ?? "");
17
+ tabContents.push(match[4]);
16
18
  }
17
19
 
18
20
  if (labels.length === 0) {
@@ -21,13 +23,6 @@ if (labels.length === 0) {
21
23
  `[USER_ERROR]: <Tabs>: Must contain at least two <Tab> children (in ${pagePath}.mdx)`
22
24
  );
23
25
  }
24
-
25
- const tabRegex = /<section[^>]*data-label="[^"]*"[^>]*>(.*?)<\/section>/gs;
26
- let tabContents = [];
27
- let contentMatch;
28
- while ((contentMatch = tabRegex.exec(html)) !== null) {
29
- tabContents.push(contentMatch[1]);
30
- }
31
26
  ---
32
27
 
33
28
  <div x-data="{
@@ -66,10 +61,10 @@ while ((contentMatch = tabRegex.exec(html)) !== null) {
66
61
  }"
67
62
  class="my-5">
68
63
  <ul
69
- class="relative isolate not-prose flex border border-neutral-200 w-fit bg-neutral-100/80 rounded-lg p-[3px] inset-shadow-sm"
64
+ class="relative isolate not-prose flex w-fit rounded-lg border border-neutral-200 bg-neutral-100/80 p-[3px] inset-shadow-sm dark:border-none dark:bg-neutral-800/50"
70
65
  >
71
66
  <div
72
- class="absolute top-[3px] bottom-[3px] bg-white rounded-md shadow-sm transition-all duration-300 ease-out -z-10 flex items-center justify-center"
67
+ class="absolute top-[3px] bottom-[3px] -z-10 flex items-center justify-center rounded-md bg-white shadow-sm transition-all duration-300 ease-out dark:bg-neutral-700/30 dark:border dark:border-neutral-700/40 dark:shadow-black/30."
73
68
  style="left: 3px;"
74
69
  :style="markerStyle.width ? `left: ${markerStyle.left}; width: ${markerStyle.width}` : ''"
75
70
  >
@@ -86,10 +81,10 @@ class="my-5">
86
81
  @click={`activeTab = ${index}`}
87
82
  class="relative px-3 h-[32px] font-medium text-sm transition-colors duration-200 cursor-pointer text-nowrap flex items-center gap-2"
88
83
  style={index === 0 ? "" : ""}
89
- class:list={[index === 0 ? "text-neutral-900" : "text-neutral-500"]}
84
+ class:list={[index === 0 ? "text-foreground" : "text-muted-foreground"]}
90
85
  :class={`{
91
- 'text-neutral-900': activeTab === ${index},
92
- 'text-neutral-500 hover:text-neutral-600': activeTab !== ${index}
86
+ 'text-foreground': activeTab === ${index},
87
+ 'text-muted-foreground hover:text-foreground': activeTab !== ${index}
93
88
  }`}
94
89
  >
95
90
  {icons[index] && <Icon name={icons[index]} class="size-4 shrink-0" />}
@@ -119,4 +114,4 @@ class="my-5">
119
114
  )) }
120
115
  </div>
121
116
  </div>
122
- </div>
117
+ </div>
@@ -180,7 +180,7 @@ if (isDev && hasAskAiDevConfig) {
180
180
  class="fixed top-1 inset-x-1 h-16 -z-10 bg-background-dark"
181
181
  data-vaul-scale-chrome
182
182
  >
183
- <div class="bg-white w-full h-full rounded-t-2xl"></div>
183
+ <div class="bg-background w-full h-full rounded-t-2xl"></div>
184
184
  </div>
185
185
  <div
186
186
  class="fixed top-[63px] z-30 w-[5px] right-0 bottom-0 bg-background-dark border-l border-l-border"