<div class="theme-demo">
<header>
<h2>Modern Dashboard</h2>
<button id="theme-switcher" aria-label="Toggle Theme">
<svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
</header>
<div class="demo-card">
<h3>Welcome back!</h3>
<p>This layout uses the native View Transitions API to create a stunning ripple effect when you toggle the theme.</p>
</div>
</div>
*, *::before, *::after {
box-sizing: border-box;
}
:root {
--bg: #ffffff;
--text: #111827;
--card-bg: #f3f4f6;
--primary: #3b82f6;
}
:root.dark {
--bg: #0f172a;
--text: #f8fafc;
--card-bg: #1e293b;
--primary: #60a5fa;
}
body {
font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
background: var(--bg);
color: var(--text);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
padding: 20px;
}
.theme-demo {
width: 100%;
max-width: 500px;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
}
header h2 {
margin: 0;
}
#theme-switcher {
background: transparent;
border: 1px solid var(--text);
color: var(--text);
padding: 8px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
width: 44px;
height: 44px;
}
.demo-card {
background: var(--card-bg);
padding: 30px;
border-radius: 16px;
text-align: center;
}
.demo-card h3 {
color: var(--primary);
margin-top: 0;
}
/* View Transition Styles */
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
::view-transition-old(root) {
z-index: 1;
}
::view-transition-new(root) {
z-index: 9999;
animation: circle-in 0.7s forwards cubic-bezier(0.4, 0, 0.2, 1);
}
.dark::view-transition-old(root) {
z-index: 9999;
animation: circle-out 0.7s forwards cubic-bezier(0.4, 0, 0.2, 1);
}
.dark::view-transition-new(root) {
z-index: 1;
animation: none;
}
@keyframes circle-in {
from {
clip-path: circle(0% at var(--click-x, 50%) var(--click-y, 50%));
}
to {
clip-path: circle(150% at var(--click-x, 50%) var(--click-y, 50%));
}
}
@keyframes circle-out {
from {
clip-path: circle(150% at var(--click-x, 50%) var(--click-y, 50%));
}
to {
clip-path: circle(0% at var(--click-x, 50%) var(--click-y, 50%));
}
}
document.getElementById("theme-switcher").addEventListener("click", (e) => {
document.documentElement.style.setProperty("--click-x", e.clientX + "px");
document.documentElement.style.setProperty("--click-y", e.clientY + "px");
if (!document.startViewTransition) {
document.documentElement.classList.toggle("dark");
return;
}
document.startViewTransition(() => {
document.documentElement.classList.toggle("dark");
});
});