Skip to content

Commit fb03429

Browse files
committed
Improve example theme rendering performance and continuity
1 parent 673f8cc commit fb03429

14 files changed

Lines changed: 756 additions & 277 deletions

File tree

example/app.css

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,124 @@ body {
310310
scroll-margin-top: 1.25rem;
311311
}
312312

313+
@supports (content-visibility: auto) {
314+
.card {
315+
content-visibility: auto;
316+
contain-intrinsic-size: auto 48rem;
317+
}
318+
}
319+
320+
:root[data-theme-animating] {
321+
transition:
322+
--background var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
323+
--foreground var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
324+
--card var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
325+
--card-foreground var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
326+
--popover var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
327+
--popover-foreground var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
328+
--primary var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
329+
--primary-foreground var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
330+
--secondary var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
331+
--secondary-foreground var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
332+
--muted var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
333+
--muted-foreground var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
334+
--accent var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
335+
--accent-foreground var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
336+
--destructive var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
337+
--destructive-foreground var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
338+
--border var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
339+
--input var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1),
340+
--ring var(--theme-skin-transition-duration, 620ms) cubic-bezier(0.22, 1, 0.36, 1);
341+
}
342+
343+
.theme-transition-overlay {
344+
--theme-transition-origin-x: calc(100% - 24px);
345+
--theme-transition-origin-y: 24px;
346+
--theme-transition-overlay-color: var(--background);
347+
--theme-transition-overlay-contrast-color: var(--foreground);
348+
--theme-transition-duration: 620ms;
349+
350+
position: fixed;
351+
inset: 0;
352+
z-index: 2147483647;
353+
pointer-events: none;
354+
overflow: hidden;
355+
}
356+
357+
.theme-transition-overlay::before,
358+
.theme-transition-overlay::after {
359+
content: "";
360+
position: absolute;
361+
inset: -24vmax;
362+
transform-origin: var(--theme-transition-origin-x) var(--theme-transition-origin-y);
363+
will-change: transform, opacity;
364+
}
365+
366+
.theme-transition-overlay::before {
367+
background: radial-gradient(
368+
circle 8rem at var(--theme-transition-origin-x) var(--theme-transition-origin-y),
369+
color-mix(in oklab, var(--theme-transition-overlay-color) 20%, transparent) 0%,
370+
color-mix(in oklab, var(--theme-transition-overlay-color) 12%, transparent) 20%,
371+
color-mix(in oklab, var(--theme-transition-overlay-color) 6%, transparent) 38%,
372+
transparent 72%
373+
);
374+
opacity: 0;
375+
transform: scale(0.55);
376+
}
377+
378+
.theme-transition-overlay::after {
379+
background: radial-gradient(
380+
circle 7rem at var(--theme-transition-origin-x) var(--theme-transition-origin-y),
381+
color-mix(in oklab, var(--theme-transition-overlay-contrast-color) 10%, transparent) 0%,
382+
color-mix(in oklab, var(--theme-transition-overlay-contrast-color) 6%, transparent) 16%,
383+
transparent 66%
384+
);
385+
opacity: 0;
386+
transform: scale(0.6);
387+
}
388+
389+
.theme-transition-overlay.is-running::before {
390+
animation: example-theme-fog var(--theme-transition-duration) cubic-bezier(0.22, 1, 0.36, 1) forwards;
391+
}
392+
393+
.theme-transition-overlay.is-running::after {
394+
animation: example-theme-ring var(--theme-transition-duration) cubic-bezier(0.22, 1, 0.36, 1) forwards;
395+
}
396+
397+
@keyframes example-theme-fog {
398+
0% {
399+
opacity: 0.06;
400+
transform: scale(0.55);
401+
}
402+
403+
24% {
404+
opacity: 0.22;
405+
transform: scale(1.02);
406+
}
407+
408+
100% {
409+
opacity: 0;
410+
transform: scale(2.25);
411+
}
412+
}
413+
414+
@keyframes example-theme-ring {
415+
0% {
416+
opacity: 0.04;
417+
transform: scale(0.6);
418+
}
419+
420+
28% {
421+
opacity: 0.14;
422+
transform: scale(1.04);
423+
}
424+
425+
100% {
426+
opacity: 0;
427+
transform: scale(2.05);
428+
}
429+
}
430+
313431
body.layout-constrained .card {
314432
width: min(100%, 40rem);
315433
}
@@ -397,6 +515,10 @@ body.layout-fluid .card {
397515
justify-content: center;
398516
}
399517

518+
.card-preview[data-mounted="false"] {
519+
min-height: var(--preview-placeholder-height, 20rem);
520+
}
521+
400522
.card-code-view {
401523
padding-inline: 0.25rem;
402524
padding-bottom: 0.25rem;

example/main.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ function scrollContentToCard(
136136
updateHash = true,
137137
keepVisible = true,
138138
) {
139+
harness.ensurePreviewMounted(elementId);
140+
139141
const targetCard = document.getElementById(`${elementId}-card`);
140142
if (!(targetCard instanceof HTMLElement)) {
141143
return;
@@ -385,7 +387,7 @@ const preferencesPanelReceipt = harness.mustGetReceipt("preferences-panel-receip
385387
const itemCarouselReceipt = harness.mustGetReceipt("item-carousel-receipt");
386388
const questionFlowReceipt = harness.mustGetReceipt("question-flow-receipt");
387389

388-
const { refreshCardCode, refreshAllCardCode } = createCodeViewSync(MINI_TOOLUI_EXAMPLE_HARNESS_CARDS, harness);
390+
const { refreshCardCode } = createCodeViewSync(MINI_TOOLUI_EXAMPLE_HARNESS_CARDS, harness);
389391

390392
const themeToggle = document.querySelector("#theme-toggle");
391393
const themeToggleLabel = document.querySelector("#theme-toggle-label");
@@ -409,7 +411,7 @@ applyTheme(initialTheme, themeElements);
409411

410412
if (themeToggle) {
411413
themeToggle.addEventListener("click", () => {
412-
const isCurrentlyDark = document.documentElement.classList.contains("dark");
414+
const isCurrentlyDark = document.documentElement.getAttribute("data-theme") === "dark";
413415
const nextTheme = isCurrentlyDark ? "light" : "dark";
414416
window.localStorage.setItem(THEME_STORAGE_KEY, nextTheme);
415417
changeThemeWithTransition(nextTheme, themeElements);
@@ -522,8 +524,6 @@ const {
522524
initialQuestionFlowPayload,
523525
} = applyInitialPayloads(harness.mustGetComponentElement, clonePayload);
524526

525-
refreshAllCardCode();
526-
527527
const unbindMiniToolActions = bindMiniToolUiExampleActions({
528528
optionListElement,
529529
approvalCardElement,

example/runtime/code-view.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { buildMiniToolUiExampleSnippetKey, renderMiniToolUiExampleSnippet } from "../code-snippets.js";
22
import type { MiniToolUiExampleHarnessCard } from "../harness-config.js";
3-
import type { MiniToolUiExampleHarnessRuntime, RefreshCardCode } from "./types.js";
3+
import type {
4+
MiniToolUiExampleHarnessRuntime,
5+
MiniToolUiExampleModeChangeEventDetail,
6+
RefreshCardCode,
7+
} from "./types.js";
48

59
export function createCodeViewSync(
610
cards: readonly MiniToolUiExampleHarnessCard[],
@@ -44,6 +48,17 @@ export function createCodeViewSync(
4448
}
4549
};
4650

51+
document.addEventListener("mini-toolui:card-mode-change", (event) => {
52+
const customEvent = event as CustomEvent<MiniToolUiExampleModeChangeEventDetail>;
53+
const detail = customEvent.detail;
54+
if (!detail || detail.mode !== "code") {
55+
return;
56+
}
57+
58+
harness.ensureCodeRenderer(detail.elementId);
59+
refreshCardCode(detail.elementId);
60+
});
61+
4762
return {
4863
refreshCardCode,
4964
refreshAllCardCode,

0 commit comments

Comments
 (0)