radiant-docs 0.1.47 → 0.1.49

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.
@@ -16,6 +16,7 @@ interface Props {
16
16
  showLineNumbers?: boolean | string;
17
17
  hideLanguageIcon?: boolean | string;
18
18
  inCodeGroup?: boolean | string;
19
+ flushTop?: boolean | string;
19
20
  highlightedLines?: string;
20
21
  collapsedLines?: string;
21
22
  }
@@ -28,6 +29,7 @@ const {
28
29
  showLineNumbers = false,
29
30
  hideLanguageIcon = false,
30
31
  inCodeGroup = false,
32
+ flushTop = false,
31
33
  highlightedLines = "",
32
34
  collapsedLines = "",
33
35
  } = Astro.props as Props;
@@ -191,6 +193,7 @@ const parsedShowFilename = parsedInCodeGroup
191
193
  : toBoolean(showFilename, false);
192
194
  const parsedShowLineNumbers = toBoolean(showLineNumbers, false);
193
195
  const parsedHideLanguageIcon = toBoolean(hideLanguageIcon, false);
196
+ const parsedFlushTop = !parsedInCodeGroup && toBoolean(flushTop, false);
194
197
  const shouldRenderLanguageIcon = !parsedHideLanguageIcon;
195
198
 
196
199
  const trimmedFilename = filename.trim();
@@ -199,10 +202,14 @@ const displayFilename =
199
202
  ? trimmedFilename
200
203
  : buildDefaultCodeFileName(normalizedLanguage);
201
204
 
202
- const { lines: tokenLines } = await getCodeLineTokens({
205
+ const { lines: tokenLines, themeColors } = await getCodeLineTokens({
203
206
  code: raw,
204
207
  language: normalizedLanguage,
205
208
  });
209
+ const codeThemeStyle = [
210
+ `--rd-code-line-highlight-theme-bg-light:${themeColors.lineHighlightBackground.light}`,
211
+ `--rd-code-line-highlight-theme-bg-dark:${themeColors.lineHighlightBackground.dark}`,
212
+ ].join(";");
206
213
 
207
214
  const rawLines = raw.split("\n");
208
215
  const normalizedRawLines = rawLines.length > 0 ? rawLines : [""];
@@ -244,20 +251,23 @@ const renderedCodeLinesHtml = normalizedTokenLines
244
251
 
245
252
  const lineContentClass = parsedShowLineNumbers
246
253
  ? "flex-1 whitespace-pre pr-4"
247
- : "flex-1 whitespace-pre pr-4 pl-4";
248
- const lineClass = isHighlighted
249
- ? "flex min-w-full bg-neutral-100/80 dark:bg-neutral-800/70"
250
- : "flex min-w-full";
254
+ : !parsedInCodeGroup && !parsedShowFilename
255
+ ? "flex-1 whitespace-pre pl-4 pr-8.5"
256
+ : "flex-1 whitespace-pre pl-4 pr-4";
257
+ const lineHighlightAttribute = isHighlighted
258
+ ? ' data-rd-code-line-highlighted="true"'
259
+ : "";
251
260
 
252
- return `<span class="${lineClass}">${lineNumberHtml}<span class="${lineContentClass}">${tokenHtml}</span></span>`;
261
+ return `<span class="flex min-w-full"${lineHighlightAttribute}>${lineNumberHtml}<span class="${lineContentClass}">${tokenHtml}</span></span>`;
253
262
  })
254
263
  .join("");
255
264
  ---
256
265
 
257
266
  <div
258
267
  class:list={[
259
- "group/prose-code not-prose relative w-full max-w-full min-w-0 rounded-xl",
260
- parsedInCodeGroup ? "my-0" : "rd-prose-block shadow-xs",
268
+ "group/prose-code not-prose relative w-full max-w-full min-w-0",
269
+ parsedFlushTop ? "rounded-b-xl" : "rounded-xl",
270
+ parsedInCodeGroup ? "my-0" : "rd-prose-block",
261
271
  ]}
262
272
  data-rd-code-block-root="true"
263
273
  data-rd-collapsed-lines={collapsedLinesValue}
@@ -268,21 +278,26 @@ const renderedCodeLinesHtml = normalizedTokenLines
268
278
  data-rd-tab-hide-icon={parsedInCodeGroup && parsedHideLanguageIcon
269
279
  ? "true"
270
280
  : undefined}
281
+ style={codeThemeStyle}
271
282
  >
272
283
  <div
273
284
  class:list={[
274
- "w-full max-w-full min-w-0 overflow-hidden border border-neutral-200 bg-white dark:border-neutral-800 dark:bg-(--rd-code-surface)",
275
- parsedInCodeGroup ? "rounded-t-none rounded-b-xl" : "rounded-xl",
285
+ "w-full max-w-full min-w-0 bg-(--rd-code-surface)",
286
+ parsedInCodeGroup
287
+ ? "rounded-tr-none rounded-xl"
288
+ : parsedFlushTop
289
+ ? "rounded-b-xl"
290
+ : "rounded-xl",
276
291
  ]}
277
292
  >
278
293
  {
279
294
  !parsedInCodeGroup && parsedShowFilename ? (
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">
295
+ <div class="flex items-center justify-between gap-2 border-b-[0.5px] border-(--rd-code-tab-edge-border)">
281
296
  <div class="min-w-0 flex-1">
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)" />
284
- <CodeTabEdge className="pointer-events-none absolute -top-px left-full z-10 h-[calc(100%+2px)]" />
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">
297
+ <div class="relative h-9 w-fit max-w-full rounded-tl-xl bg-(--rd-code-surface)">
298
+ <div class="absolute inset-x-0 -bottom-px h-px bg-(--rd-code-surface)" />
299
+ <CodeTabEdge className="pointer-events-none absolute -top-[0.5px] left-full z-10 h-[calc(100%+1.5px)]" />
300
+ <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 rounded-tl-xl border-t-[0.5px] border-l-[0.5px] border-(--rd-code-tab-edge-border)">
286
301
  {shouldRenderLanguageIcon ? (
287
302
  <CodeLanguageIcon
288
303
  language={normalizedLanguage}
@@ -294,8 +309,8 @@ const renderedCodeLinesHtml = normalizedTokenLines
294
309
  </div>
295
310
  </div>
296
311
  </div>
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)" />
312
+ <div class="relative h-9 w-5 shrink-0 rounded-tr-xl bg-(--rd-code-surface) border-t-[0.5px] border-r-[0.5px] border-(--rd-code-tab-edge-border)">
313
+ <div class="absolute inset-x-0 -bottom-px h-px bg-(--rd-code-surface)" />
299
314
  <CodeTabEdge className="pointer-events-none absolute -top-px right-full z-10 h-[calc(100%+2px)] rotate-y-180" />
300
315
  <button
301
316
  type="button"
@@ -323,7 +338,13 @@ const renderedCodeLinesHtml = normalizedTokenLines
323
338
  }
324
339
 
325
340
  <div
326
- class="relative min-w-0"
341
+ class:list={[
342
+ "relative min-w-0 border-[0.5px] overflow-hidden border-(--rd-code-tab-edge-border)",
343
+ parsedFlushTop ? "rounded-b-xl" : "rounded-xl",
344
+ parsedFlushTop && "border-t-0",
345
+ parsedShowFilename && "border-t-0 rounded-t-none",
346
+ parsedInCodeGroup && "rounded-tl-xl border-0!",
347
+ ]}
327
348
  data-rd-code-group-panel={parsedInCodeGroup ? "true" : undefined}
328
349
  >
329
350
  {
@@ -331,7 +352,7 @@ const renderedCodeLinesHtml = normalizedTokenLines
331
352
  <div class="pointer-events-none absolute right-2 top-2 z-20">
332
353
  <button
333
354
  type="button"
334
- 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"
355
+ class="pointer-events-none inline-flex size-7 appearance-none items-center justify-center rounded-md bg-(--rd-code-surface)/40 backdrop-blur-sm text-neutral-500/80 outline-none ring-0 transition-colors duration-150 hover:text-neutral-700 focus:outline-none focus-visible:outline-none focus:ring-0 focus-visible:ring-0 cursor-pointer group-hover/prose-code:pointer-events-auto group-focus-within/prose-code:pointer-events-auto dark:text-neutral-400 dark:hover:text-neutral-200 relative before:absolute before:inset-1 hover:before:inset-0 before:rounded-md hover:before:bg-neutral-900/4 dark:hover:before:bg-white/4 before:duration-150"
335
356
  data-rd-copy-trigger="true"
336
357
  data-rd-copy-content={encodedRaw}
337
358
  aria-label="Copy code"
@@ -344,7 +365,7 @@ const renderedCodeLinesHtml = normalizedTokenLines
344
365
  />
345
366
  <Icon
346
367
  name="lucide:check"
347
- 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"
368
+ class="absolute size-3.5 stroke-3 origin-center scale-25 rotate-6 opacity-0 text-green-800/70 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"
348
369
  data-rd-copy-check
349
370
  aria-hidden="true"
350
371
  />
@@ -372,7 +393,7 @@ const renderedCodeLinesHtml = normalizedTokenLines
372
393
  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"
373
394
  >
374
395
  <pre
375
- 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>
396
+ class="relative m-0 min-w-full bg-(--rd-code-surface) p-0 text-[13px] leading-6"><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>
376
397
  </div>
377
398
  </div>
378
399
  </div>
@@ -4,33 +4,29 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
4
4
  ---
5
5
 
6
6
  <div
7
- class="rd-prose-block group/prose-code-group not-prose relative w-full max-w-full min-w-0 shadow-xs rounded-xl"
7
+ class="rd-prose-block group/prose-code-group not-prose relative w-full max-w-full min-w-0 rounded-xl"
8
8
  data-rd-code-group-root="true"
9
9
  >
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 dark:border-neutral-800 dark:bg-neutral-900/60 dark:inset-shadow-neutral-900/80"
12
- >
10
+ <div class="relative z-10 overflow-visible rounded-t-xl">
13
11
  <div class="flex min-w-0 items-end justify-between gap-2">
14
12
  <div class="min-w-0 flex-1 overflow-hidden rounded-t-xl">
15
13
  <div
16
14
  data-rd-code-group-tabs
17
- class="relative flex min-w-0 items-end gap-1 overflow-x-auto pl-1 pr-8 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
15
+ class="relative flex min-w-0 items-end gap-1 overflow-x-auto overscroll-x-contain pl-1 pr-8 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
18
16
  >
19
17
  <div
20
18
  data-rd-code-group-pill
21
19
  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 opacity-0 transition-[left,width,opacity] duration-200 ease-out dark:border-neutral-700/70 dark:bg-(--rd-code-surface)"
20
+ class="pointer-events-none absolute top-0 z-0 h-[28px] rounded-[9px] border-[0.5px] border-(--rd-code-tab-edge-border) bg-(--rd-code-surface) opacity-0 transition-[left,width,opacity] duration-200 ease-out"
23
21
  >
24
22
  </div>
25
23
  </div>
26
24
  </div>
27
25
 
28
26
  <div
29
- class="relative h-9 w-5 shrink-0 rounded-tr-xl bg-white dark:bg-(--rd-code-surface)"
27
+ class="relative h-9 w-5 shrink-0 rounded-tr-xl bg-(--rd-code-surface) border-t-[0.5px] border-r-[0.5px] border-(--rd-code-tab-edge-border)"
30
28
  >
31
- <div
32
- class="absolute inset-x-0 -bottom-px h-px bg-white dark:bg-(--rd-code-surface)"
33
- >
29
+ <div class="absolute inset-x-0 -bottom-px h-px bg-(--rd-code-surface)">
34
30
  </div>
35
31
  <CodeTabEdge
36
32
  className="pointer-events-none absolute -top-px right-full z-10 h-[calc(100%+2px)] rotate-y-180"
@@ -49,7 +45,7 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
49
45
  />
50
46
  <Icon
51
47
  name="lucide:check"
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
+ class="absolute size-3.5 stroke-3 origin-center scale-25 rotate-6 opacity-0 text-green-800/70 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"
53
49
  data-rd-copy-check
54
50
  aria-hidden="true"
55
51
  />
@@ -60,7 +56,8 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
60
56
 
61
57
  <div
62
58
  data-rd-code-group-content
63
- class="relative min-w-0 overflow-hidden transition-[height] duration-300 ease-in-out"
59
+ class="relative min-w-0 overflow-hidden transition-[height] bg-(--rd-code-surface) rounded-xl rounded-tr-none border-[0.5px] border-(--rd-code-tab-edge-border)"
60
+ style="transition-duration: var(--rd-panel-transition-duration); transition-timing-function: var(--rd-panel-transition-easing);"
64
61
  >
65
62
  <slot />
66
63
  </div>
@@ -93,7 +90,20 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
93
90
  const prefersReducedMotion =
94
91
  typeof window.matchMedia === "function" &&
95
92
  window.matchMedia("(prefers-reduced-motion: reduce)").matches;
96
- const TRANSITION_DURATION_MS = prefersReducedMotion ? 0 : 300;
93
+ const rootStyles = window.getComputedStyle(document.documentElement);
94
+ const configuredDurationMs = Number.parseFloat(
95
+ rootStyles.getPropertyValue("--rd-panel-transition-duration-ms"),
96
+ );
97
+ const configuredEasing = rootStyles
98
+ .getPropertyValue("--rd-panel-transition-easing")
99
+ .trim();
100
+ const TRANSITION_DURATION_MS = prefersReducedMotion
101
+ ? 0
102
+ : Number.isFinite(configuredDurationMs)
103
+ ? configuredDurationMs
104
+ : 400;
105
+ const TRANSITION_EASING =
106
+ configuredEasing || "cubic-bezier(0.22, 1, 0.36, 1)";
97
107
 
98
108
  let activeIndex = 0;
99
109
  let transitionTimeoutId = null;
@@ -139,10 +149,14 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
139
149
 
140
150
  const tabButton = document.createElement("button");
141
151
  tabButton.type = "button";
142
- 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" : ""}`;
152
+ tabButton.className =
153
+ "relative inline-flex h-9 items-start border-0 bg-transparent px-3 py-0 text-xs font-medium transition-colors duration-150 focus:outline-none focus-visible:outline-none cursor-pointer";
143
154
  tabButton.setAttribute("aria-label", filename);
144
155
  tabButton.setAttribute("data-rd-code-group-tab", String(index));
145
156
 
157
+ const tabContent = document.createElement("span");
158
+ tabContent.className = `pointer-events-none inline-flex h-[28px] items-center ${hasTabIcon ? "gap-2" : ""}`;
159
+
146
160
  let iconContainer = null;
147
161
  if (hasTabIcon) {
148
162
  iconContainer = document.createElement("span");
@@ -156,9 +170,10 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
156
170
  labelElement.textContent = filename;
157
171
 
158
172
  if (iconContainer) {
159
- tabButton.appendChild(iconContainer);
173
+ tabContent.appendChild(iconContainer);
160
174
  }
161
- tabButton.appendChild(labelElement);
175
+ tabContent.appendChild(labelElement);
176
+ tabButton.appendChild(tabContent);
162
177
  tabWrapper.appendChild(tabButton);
163
178
  tabsElement.appendChild(tabWrapper);
164
179
 
@@ -183,6 +198,7 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
183
198
  });
184
199
 
185
200
  contentElement.style.transitionDuration = `${TRANSITION_DURATION_MS}ms`;
201
+ contentElement.style.transitionTimingFunction = TRANSITION_EASING;
186
202
 
187
203
  const syncPill = () => {
188
204
  const activeTab = tabs[activeIndex]?.tabWrapper;
@@ -205,12 +221,11 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
205
221
  const updateTabButtonStates = () => {
206
222
  tabs.forEach(({ tabButton, iconContainer }, index) => {
207
223
  const isActive = index === activeIndex;
208
- tabButton.classList.toggle("text-foreground", isActive);
209
- tabButton.classList.toggle("text-muted-foreground", !isActive);
210
-
224
+ tabButton.classList.toggle("text-neutral-500/80", !isActive);
225
+ tabButton.classList.toggle("dark:text-neutral-400/80", !isActive);
211
226
  if (!iconContainer) return;
212
- iconContainer.classList.toggle("opacity-100", isActive);
213
227
  iconContainer.classList.toggle("opacity-80", !isActive);
228
+ iconContainer.classList.toggle("grayscale-100", !isActive);
214
229
  });
215
230
  syncPill();
216
231
  };
@@ -269,15 +284,31 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
269
284
  activeItemResizeObserver.observe(activeItem);
270
285
  };
271
286
 
287
+ const setItemToTransitionPosition = (itemElement) => {
288
+ itemElement.style.position = "absolute";
289
+ itemElement.style.inset = "";
290
+ itemElement.style.top = "0";
291
+ itemElement.style.right = "0";
292
+ itemElement.style.bottom = "";
293
+ itemElement.style.left = "0";
294
+ };
295
+
272
296
  const setPanelsToRestState = () => {
273
297
  tabs.forEach(({ itemElement, panelElement, frameElement }, index) => {
274
298
  const isActive = index === activeIndex;
275
299
  itemElement.style.position = isActive ? "relative" : "absolute";
276
- itemElement.style.inset = isActive ? "" : "0";
300
+ itemElement.style.inset = "";
301
+ itemElement.style.top = isActive ? "" : "0";
302
+ itemElement.style.right = isActive ? "" : "0";
303
+ itemElement.style.bottom = isActive ? "" : "0";
304
+ itemElement.style.left = isActive ? "" : "0";
277
305
  itemElement.style.opacity = isActive ? "1" : "0";
278
306
  itemElement.style.visibility = isActive ? "visible" : "hidden";
279
307
  itemElement.style.pointerEvents = isActive ? "auto" : "none";
280
308
  itemElement.style.zIndex = isActive ? "1" : "0";
309
+ itemElement.style.transform = "translateX(0)";
310
+ itemElement.style.animation = "none";
311
+ itemElement.style.willChange = "auto";
281
312
  panelElement.style.transform = "translateX(0)";
282
313
  panelElement.style.animation = "none";
283
314
  panelElement.style.willChange = "auto";
@@ -313,8 +344,6 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
313
344
  const nextItem = nextTab?.itemElement;
314
345
  const previousPanel = previousTab?.panelElement;
315
346
  const nextPanel = nextTab?.panelElement;
316
- const previousFrame = previousTab?.frameElement;
317
- const nextFrame = nextTab?.frameElement;
318
347
  if (!previousItem || !nextItem || !previousPanel || !nextPanel) {
319
348
  normalizeToCurrentState();
320
349
  return;
@@ -331,37 +360,35 @@ import CodeTabEdge from "../ui/CodeTabEdge.astro";
331
360
  });
332
361
  }
333
362
 
334
- previousItem.style.position = "absolute";
335
- previousItem.style.inset = "0";
363
+ setItemToTransitionPosition(previousItem);
336
364
  previousItem.style.opacity = "1";
337
365
  previousItem.style.visibility = "visible";
338
366
  previousItem.style.pointerEvents = "none";
339
367
  previousItem.style.zIndex = "1";
368
+ previousItem.style.transform = "translateX(0)";
369
+ previousItem.style.willChange = "transform, opacity";
340
370
  previousPanel.style.transform = "translateX(0)";
341
- previousPanel.style.willChange = "transform";
342
- if (previousFrame) {
343
- previousFrame.style.height = "100%";
344
- }
345
- previousPanel.style.animation =
371
+ previousPanel.style.animation = "none";
372
+ previousPanel.style.willChange = "auto";
373
+ previousItem.style.animation =
346
374
  direction === 1
347
- ? `rd-code-group-slide-out-to-left ${TRANSITION_DURATION_MS}ms ease-in-out both`
348
- : `rd-code-group-slide-out-to-right ${TRANSITION_DURATION_MS}ms ease-in-out both`;
375
+ ? `rd-code-group-slide-out-to-left ${TRANSITION_DURATION_MS}ms ${TRANSITION_EASING} both`
376
+ : `rd-code-group-slide-out-to-right ${TRANSITION_DURATION_MS}ms ${TRANSITION_EASING} both`;
349
377
 
350
- nextItem.style.position = "absolute";
351
- nextItem.style.inset = "0";
378
+ setItemToTransitionPosition(nextItem);
352
379
  nextItem.style.opacity = "1";
353
380
  nextItem.style.visibility = "visible";
354
381
  nextItem.style.pointerEvents = "auto";
355
382
  nextItem.style.zIndex = "2";
383
+ nextItem.style.transform = "translateX(0)";
384
+ nextItem.style.willChange = "transform, opacity";
356
385
  nextPanel.style.transform = "translateX(0)";
357
- nextPanel.style.willChange = "transform";
358
- if (nextFrame) {
359
- nextFrame.style.height = "100%";
360
- }
361
- nextPanel.style.animation =
386
+ nextPanel.style.animation = "none";
387
+ nextPanel.style.willChange = "auto";
388
+ nextItem.style.animation =
362
389
  direction === 1
363
- ? `rd-code-group-slide-in-from-right ${TRANSITION_DURATION_MS}ms ease-in-out both`
364
- : `rd-code-group-slide-in-from-left ${TRANSITION_DURATION_MS}ms ease-in-out both`;
390
+ ? `rd-code-group-slide-in-from-right ${TRANSITION_DURATION_MS}ms ${TRANSITION_EASING} both`
391
+ : `rd-code-group-slide-in-from-left ${TRANSITION_DURATION_MS}ms ${TRANSITION_EASING} both`;
365
392
 
366
393
  transitionTimeoutId = window.setTimeout(() => {
367
394
  transitionTimeoutId = null;
@@ -60,16 +60,20 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
60
60
  ---
61
61
 
62
62
  <div
63
- class="rd-prose-block rd-component-preview flex w-full max-w-full min-w-0 flex-col"
63
+ class="rd-prose-block rd-component-preview isolate flex w-full max-w-full min-w-0 flex-col"
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 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!"
67
+ class="relative z-10 w-full max-w-full min-w-0 rounded-t-xl border-[0.5px] border-b-0 border-(--rd-code-tab-edge-border) bg-(--rd-code-surface) p-2"
68
68
  >
69
- <slot />
69
+ <div
70
+ class="bg-white dark:bg-neutral-900/70 rounded-xl border-[0.5px] border-neutral-900/10 dark:border-white/8 p-4 xs:p-6 sm:p-9 sm:px-12 *:first:mt-0! *:last:mb-0! shadow-[0_.5px_1px_rgba(0,0,0,0.15),0_5px_12px_-8px_rgba(0,0,0,0.08)] dark:shadow-[0_-0.5px_1px_rgba(255,255,255,0.1),0_5px_12px_-4px_rgba(0,0,0,0.15)] overflow-x-auto"
71
+ >
72
+ <slot />
73
+ </div>
70
74
  </div>
71
75
  <div
72
- class="rd-component-preview__code not-prose relative overflow-hidden rounded-b-xl bg-neutral-50 dark:bg-(--rd-code-surface)"
76
+ class="rd-component-preview__code not-prose relative z-0 overflow-hidden rounded-b-xl"
73
77
  data-rd-preview-expanded={isInitiallyExpanded ? "true" : "false"}
74
78
  style={{ "--rd-preview-visible-lines": String(visibleLines) }}
75
79
  >
@@ -82,16 +86,19 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
82
86
  hideLanguageIcon={hideLanguageIcon}
83
87
  highlightedLines={highlightedLines}
84
88
  collapsedLines={collapsedLines}
89
+ flushTop
85
90
  />
86
91
  <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 pb-4"
92
+ class="rd-component-preview__overlay pointer-events-none absolute inset-0 hidden items-end justify-center rounded-b-xl pb-4"
88
93
  data-rd-preview-overlay
89
94
  aria-hidden="true"
90
95
  >
91
- <div class="bg-white dark:bg-neutral-800">
96
+ <div
97
+ class="bg-white dark:bg-neutral-800 rounded-xl [corner-shape:superellipse(1.2)]"
98
+ >
92
99
  <button
93
100
  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"
101
+ class="pointer-events-auto inline-flex h-8 items-center justify-center rounded-xl [corner-shape:superellipse(1.2)] border-[0.5px] border-neutral-900/10 dark:border-white/8 bg-linear-to-br from-white via-white/10 to-neutral-900/5 dark:from-white/7 dark:via-white/6 dark:to-white/2 px-3 text-sm font-medium text-neutral-600 hover:text-neutral-900 dark:text-neutral-300/90 hover:dark:text-neutral-200 transition-colors duration-200 hover:bg-neutral-50/80 cursor-pointer dark:hover:bg-neutral-700/30 shadow-[0_.5px_1px_rgba(0,0,0,0.15),0_5px_12px_-4px_rgba(0,0,0,0.08)] dark:shadow-[0_-0.5px_0px_rgba(255,255,255,0.15),0_5px_12px_-4px_rgba(0,0,0,0.6)]"
95
102
  data-rd-preview-expand
96
103
  >
97
104
  View code
@@ -174,36 +181,37 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
174
181
  .rd-component-preview__code[data-rd-preview-expanded="false"]
175
182
  .rd-component-preview__overlay {
176
183
  display: flex;
177
- background: linear-gradient(
178
- to top,
179
- rgb(250 250 250 / 90%),
180
- rgb(250 250 250 / 30%)
181
- );
182
- }
183
-
184
- :global(.dark)
185
- .rd-component-preview__code[data-rd-preview-expanded="false"]
186
- .rd-component-preview__overlay {
187
- background: linear-gradient(
188
- to top,
189
- color-mix(in srgb, var(--rd-code-surface) 90%, transparent),
190
- color-mix(in srgb, var(--rd-code-surface) 35%, transparent)
191
- );
192
184
  }
193
185
 
194
186
  .rd-component-preview__code :global([data-rd-code-scroll-area]) {
195
187
  overflow-y: hidden;
196
- transition: max-height 280ms cubic-bezier(0.22, 1, 0.36, 1);
188
+ transition:
189
+ max-height 280ms cubic-bezier(0.22, 1, 0.36, 1),
190
+ mask-image 180ms ease-out;
197
191
  }
198
192
 
199
193
  .rd-component-preview__code[data-rd-preview-expanded="false"]
200
194
  :global([data-rd-code-scroll-area]) {
201
- max-height: calc(var(--rd-preview-visible-lines, 5) * 1.5rem + 1.25rem);
195
+ max-height: calc(var(--rd-preview-visible-lines, 5) * 1.5rem + 0.75rem);
196
+ -webkit-mask-image: linear-gradient(
197
+ to bottom,
198
+ rgb(0 0 0 / 80%) 0%,
199
+ rgb(0 0 0 / 32%) 82%,
200
+ transparent 110%
201
+ );
202
+ mask-image: linear-gradient(
203
+ to bottom,
204
+ rgb(0 0 0 / 80%) 0%,
205
+ rgb(0 0 0 / 32%) 82%,
206
+ transparent 110%
207
+ );
202
208
  }
203
209
 
204
210
  .rd-component-preview__code[data-rd-preview-expanded="true"]
205
211
  :global([data-rd-code-scroll-area]) {
206
212
  max-height: var(--rd-preview-expanded-height, 200rem);
213
+ -webkit-mask-image: none;
214
+ mask-image: none;
207
215
  }
208
216
  </style>
209
217