|
| 1 | +--- |
| 2 | +outline: deep |
| 3 | +--- |
| 4 | + |
1 | 5 | # Extending the Default Theme
|
2 | 6 |
|
3 | 7 | VitePress' default theme is optimized for documentation, and can be customized. Consult the [Default Theme Config Overview](../reference/default-theme-config) for a comprehensive list of options.
|
@@ -195,6 +199,102 @@ Full list of slots available in the default theme layout:
|
195 | 199 | - `nav-screen-content-before`
|
196 | 200 | - `nav-screen-content-after`
|
197 | 201 |
|
| 202 | +## Using View Transitions API |
| 203 | + |
| 204 | +### On Appearance Toggle |
| 205 | + |
| 206 | +You can extend the default theme to provide a custom transition when the color mode is toggled. An example: |
| 207 | + |
| 208 | +```vue |
| 209 | +<!-- .vitepress/theme/Layout.vue --> |
| 210 | +
|
| 211 | +<script setup lang="ts"> |
| 212 | +import { useData } from 'vitepress' |
| 213 | +import DefaultTheme from 'vitepress/theme' |
| 214 | +import { nextTick, provide } from 'vue' |
| 215 | +
|
| 216 | +const { isDark } = useData() |
| 217 | +
|
| 218 | +const enableTransitions = () => |
| 219 | + 'startViewTransition' in document && |
| 220 | + window.matchMedia('(prefers-reduced-motion: no-preference)').matches |
| 221 | +
|
| 222 | +provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => { |
| 223 | + if (!enableTransitions()) { |
| 224 | + isDark.value = !isDark.value |
| 225 | + return |
| 226 | + } |
| 227 | +
|
| 228 | + const clipPath = [ |
| 229 | + `circle(0px at ${x}px ${y}px)`, |
| 230 | + `circle(${Math.hypot( |
| 231 | + Math.max(x, innerWidth - x), |
| 232 | + Math.max(y, innerHeight - y) |
| 233 | + )}px at ${x}px ${y}px)` |
| 234 | + ] |
| 235 | +
|
| 236 | + await document.startViewTransition(async () => { |
| 237 | + isDark.value = !isDark.value |
| 238 | + await nextTick() |
| 239 | + }).ready |
| 240 | +
|
| 241 | + document.documentElement.animate( |
| 242 | + { clipPath: isDark.value ? clipPath.reverse() : clipPath }, |
| 243 | + { |
| 244 | + duration: 300, |
| 245 | + easing: 'ease-in', |
| 246 | + pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)` |
| 247 | + } |
| 248 | + ) |
| 249 | +}) |
| 250 | +</script> |
| 251 | +
|
| 252 | +<template> |
| 253 | + <DefaultTheme.Layout /> |
| 254 | +</template> |
| 255 | +
|
| 256 | +<style> |
| 257 | +::view-transition-old(root), |
| 258 | +::view-transition-new(root) { |
| 259 | + animation: none; |
| 260 | + mix-blend-mode: normal; |
| 261 | +} |
| 262 | +
|
| 263 | +::view-transition-old(root), |
| 264 | +.dark::view-transition-new(root) { |
| 265 | + z-index: 1; |
| 266 | +} |
| 267 | +
|
| 268 | +::view-transition-new(root), |
| 269 | +.dark::view-transition-old(root) { |
| 270 | + z-index: 9999; |
| 271 | +} |
| 272 | +
|
| 273 | +.VPSwitchAppearance { |
| 274 | + width: 22px !important; |
| 275 | +} |
| 276 | +
|
| 277 | +.VPSwitchAppearance .check { |
| 278 | + transform: none !important; |
| 279 | +} |
| 280 | +</style> |
| 281 | +``` |
| 282 | + |
| 283 | +Result (**warning!**: flashing colors, sudden movements, bright lights): |
| 284 | + |
| 285 | +<details> |
| 286 | +<summary>Demo</summary> |
| 287 | + |
| 288 | + |
| 289 | + |
| 290 | +</details> |
| 291 | + |
| 292 | +Refer [Chrome Docs](https://developer.chrome.com/docs/web-platform/view-transitions/) from more details on view transitions. |
| 293 | + |
| 294 | +### On Route Change |
| 295 | + |
| 296 | +Coming soon. |
| 297 | + |
198 | 298 | ## Overriding Internal Components
|
199 | 299 |
|
200 | 300 | You can use Vite's [aliases](https://vitejs.dev/config/shared-options.html#resolve-alias) to replace default theme components with your custom ones:
|
|
0 commit comments