|
18 | 18 | </div> |
19 | 19 | <div class="examples"> |
20 | 20 | <template v-for="group in groupedExamples" :key="group.category"> |
21 | | - <div v-if="selectedCategory === 'all'" class="group-header"> |
22 | | - <span class="pill" :data-cat="group.category">{{ pillLabel(group.category) }}</span> |
| 21 | + <div class="group-header" :data-cat="group.category"> |
| 22 | + <span class="group-accent" aria-hidden="true"></span> |
23 | 23 | <span class="group-label">{{ categoryLabel(group.category) }}</span> |
24 | 24 | <span class="group-count">{{ group.items.length }}</span> |
25 | 25 | </div> |
26 | 26 | <ul class="example-list"> |
27 | 27 | <li |
28 | 28 | v-for="ex in group.items" |
29 | 29 | :key="ex.id" |
30 | | - :class="{ active: ex.id === currentExample.id }" |
31 | | - @click="selectExample(ex.id)" |
32 | 30 | > |
33 | | - <span class="pill" :data-cat="ex.category">{{ pillLabel(ex.category) }}</span> |
34 | | - <span class="title">{{ ex.title }}</span> |
| 31 | + <button |
| 32 | + class="example-link" |
| 33 | + :class="{ active: ex.id === currentExample.id }" |
| 34 | + :data-cat="ex.category" |
| 35 | + type="button" |
| 36 | + :aria-current="ex.id === currentExample.id ? 'true' : undefined" |
| 37 | + @click="selectExample(ex.id)" |
| 38 | + > |
| 39 | + <span class="example-mark" aria-hidden="true"></span> |
| 40 | + <span class="title">{{ ex.title }}</span> |
| 41 | + </button> |
35 | 42 | </li> |
36 | 43 | </ul> |
37 | 44 | </template> |
@@ -3104,7 +3111,6 @@ const CATEGORY_LABELS = { |
3104 | 3111 | pixi: 'Pixi.js', |
3105 | 3112 | }; |
3106 | 3113 | function categoryLabel(c){ return CATEGORY_LABELS[c] || c; } |
3107 | | -function pillLabel(c){ return c === 'three' ? 'three' : c === 'pixi' ? 'pixi' : c; } |
3108 | 3114 | const selectedCategory = ref('all'); |
3109 | 3115 | // Fixed category order used for grouping in the sidebar. |
3110 | 3116 | const CATEGORY_ORDER = ['2d', 'webgl', 'webgpu', 'three', 'pixi']; |
@@ -3311,14 +3317,33 @@ function ensureExampleIsVisible(example){ |
3311 | 3317 | } |
3312 | 3318 | } |
3313 | 3319 |
|
| 3320 | +function scrollCurrentExampleIntoView(){ |
| 3321 | + if (typeof window === 'undefined') return; |
| 3322 | + const active = rootRef.value?.querySelector('.example-link.active'); |
| 3323 | + const scrollArea = rootRef.value?.querySelector('.examples'); |
| 3324 | + if (!active || !scrollArea) return; |
| 3325 | + const activeRect = active.getBoundingClientRect(); |
| 3326 | + const areaRect = scrollArea.getBoundingClientRect(); |
| 3327 | + if (activeRect.top < areaRect.top || activeRect.bottom > areaRect.bottom) { |
| 3328 | + const activeCenter = activeRect.top - areaRect.top + scrollArea.scrollTop + activeRect.height / 2; |
| 3329 | + scrollArea.scrollTo({ |
| 3330 | + top: Math.max(0, activeCenter - scrollArea.clientHeight / 2), |
| 3331 | + behavior: 'auto', |
| 3332 | + }); |
| 3333 | + } |
| 3334 | +} |
| 3335 | +
|
3314 | 3336 | function selectExample(id, { syncUrl = true, replaceUrl = false } = {}){ |
3315 | 3337 | const ex = examples.find(e => e.id === id); |
3316 | 3338 | if (!ex) return; |
3317 | 3339 | ensureExampleIsVisible(ex); |
3318 | 3340 | currentExample.value = ex; |
3319 | 3341 | code.value = ex.code; |
3320 | 3342 | if (syncUrl) syncSelectedExampleToUrl(ex.id, { replace: replaceUrl }); |
3321 | | - nextTick(runSelected); |
| 3343 | + nextTick(() => { |
| 3344 | + scrollCurrentExampleIntoView(); |
| 3345 | + runSelected(); |
| 3346 | + }); |
3322 | 3347 | } |
3323 | 3348 |
|
3324 | 3349 | function resetCode(){ |
@@ -3923,49 +3948,121 @@ onUnmounted(() => { |
3923 | 3948 | font-variant-numeric: tabular-nums; |
3924 | 3949 | } |
3925 | 3950 | .canvas-playground .subtitle { margin: 6px 0 0; font-size: 12px; color: var(--vp-c-text-2); line-height: 1.5; } |
3926 | | -.canvas-playground .examples { flex: 1; overflow: auto; padding: 4px 10px 10px; scrollbar-width: thin; } |
| 3951 | +.canvas-playground .examples { flex: 1; overflow: auto; padding: 8px 10px 12px; scrollbar-width: thin; } |
3927 | 3952 | .canvas-playground .examples::-webkit-scrollbar { width: 8px; } |
3928 | 3953 | .canvas-playground .examples::-webkit-scrollbar-thumb { background: var(--vp-c-divider); border-radius: 4px; } |
3929 | 3954 | .canvas-playground .examples::-webkit-scrollbar-track { background: transparent; } |
3930 | 3955 | .canvas-playground .group-header { |
3931 | 3956 | display: flex; align-items: center; gap: 8px; |
3932 | | - padding: 10px 6px 6px; |
| 3957 | + padding: 12px 6px 7px; |
3933 | 3958 | position: sticky; top: 0; |
3934 | | - background: var(--vp-c-bg); |
| 3959 | + background: linear-gradient(180deg, var(--vp-c-bg) 72%, color-mix(in srgb, var(--vp-c-bg), transparent 100%)); |
3935 | 3960 | z-index: 2; |
3936 | 3961 | } |
3937 | | -.canvas-playground .group-header .group-label { font-size: 11px; color: var(--vp-c-text-2); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; } |
| 3962 | +.canvas-playground .group-accent { |
| 3963 | + width: 7px; height: 7px; border-radius: 999px; |
| 3964 | + background: var(--example-accent, var(--vp-c-brand-1)); |
| 3965 | + box-shadow: 0 0 0 3px var(--example-soft, var(--vp-c-brand-soft)); |
| 3966 | + flex-shrink: 0; |
| 3967 | +} |
| 3968 | +.canvas-playground .group-header .group-label { |
| 3969 | + font-size: 11px; color: var(--vp-c-text-1); font-weight: 700; |
| 3970 | + letter-spacing: 0.08em; text-transform: uppercase; |
| 3971 | +} |
3938 | 3972 | .canvas-playground .group-header .group-count { |
3939 | 3973 | margin-left: auto; font-size: 10px; color: var(--vp-c-text-3); |
3940 | 3974 | background: var(--vp-c-default-soft); padding: 1px 7px; border-radius: 999px; |
3941 | 3975 | font-variant-numeric: tabular-nums; |
3942 | 3976 | } |
3943 | | -.canvas-playground .example-list { list-style: none; padding: 0; margin: 0 0 4px 0; } |
3944 | | -.canvas-playground .example-list li { |
3945 | | - padding: 7px 10px; border-radius: 8px; margin-bottom: 2px; cursor: pointer; |
3946 | | - display: flex; align-items: center; gap: 8px; font-size: 13.5px; |
| 3977 | +.canvas-playground .example-list { list-style: none; padding: 0; margin: 0 0 6px 0; } |
| 3978 | +.canvas-playground .example-list li { margin: 0 0 2px 0; } |
| 3979 | +.canvas-playground .example-link { |
| 3980 | + width: 100%; min-height: 36px; |
| 3981 | + padding: 8px 9px; border-radius: 8px; border: 1px solid transparent; |
| 3982 | + background: transparent; |
3947 | 3983 | color: var(--vp-c-text-2); |
3948 | | - transition: background 100ms ease, color 100ms ease; |
3949 | | - border-left: 3px solid transparent; |
3950 | | -} |
3951 | | -.canvas-playground .example-list li .title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
3952 | | -.canvas-playground .example-list li:hover { background: var(--vp-c-default-soft); color: var(--vp-c-text-1); } |
3953 | | -.canvas-playground .example-list li.active { |
3954 | | - background: var(--vp-c-brand-soft); |
3955 | | - border-left-color: var(--vp-c-brand-1); |
| 3984 | + display: flex; align-items: center; gap: 10px; |
| 3985 | + font: inherit; font-size: 13px; font-weight: 500; text-align: left; |
| 3986 | + cursor: pointer; |
| 3987 | + transition: background 120ms ease, border-color 120ms ease, color 120ms ease, box-shadow 120ms ease; |
| 3988 | +} |
| 3989 | +.canvas-playground .example-link .title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } |
| 3990 | +.canvas-playground .example-link:hover { |
| 3991 | + background: var(--vp-c-default-soft); |
| 3992 | + border-color: var(--vp-c-divider); |
3956 | 3993 | color: var(--vp-c-text-1); |
3957 | | - padding-left: 7px; |
3958 | | -} |
3959 | | -.canvas-playground .pill { |
3960 | | - font-size: 10px; text-transform: uppercase; letter-spacing: 0.04em; |
3961 | | - padding: 2px 6px; border-radius: 999px; background: rgba(255,255,255,0.06); |
3962 | | - color: #cbd5e1; |
3963 | | -} |
3964 | | -.canvas-playground .pill[data-cat="webgl"] { background: rgba(244,114,182,0.15); color: #f9a8d4; } |
3965 | | -.canvas-playground .pill[data-cat="webgpu"] { background: rgba(168,85,247,0.18); color: #d8b4fe; } |
3966 | | -.canvas-playground .pill[data-cat="2d"] { background: rgba(34,211,238,0.15); color: #67e8f9; } |
3967 | | -.canvas-playground .pill[data-cat="three"] { background: rgba(74,222,128,0.16); color: #86efac; } |
3968 | | -.canvas-playground .pill[data-cat="pixi"] { background: rgba(251,146,60,0.16); color: #fdba74; } |
| 3994 | +} |
| 3995 | +.canvas-playground .example-link:focus-visible { |
| 3996 | + outline: 2px solid var(--vp-c-brand-1); |
| 3997 | + outline-offset: 2px; |
| 3998 | +} |
| 3999 | +.canvas-playground .example-link.active { |
| 4000 | + background: var(--example-soft, var(--vp-c-brand-soft)); |
| 4001 | + border-color: var(--example-border, var(--vp-c-brand-1)); |
| 4002 | + color: var(--vp-c-text-1); |
| 4003 | +} |
| 4004 | +.canvas-playground .example-mark { |
| 4005 | + width: 2px; height: 16px; border-radius: 999px; |
| 4006 | + background: var(--example-accent, var(--vp-c-brand-1)); |
| 4007 | + opacity: 0; flex-shrink: 0; |
| 4008 | + transition: opacity 120ms ease; |
| 4009 | +} |
| 4010 | +.canvas-playground .example-link:hover .example-mark { |
| 4011 | + opacity: 0.35; |
| 4012 | +} |
| 4013 | +.canvas-playground .example-link.active .example-mark { |
| 4014 | + opacity: 1; |
| 4015 | +} |
| 4016 | +.canvas-playground [data-cat="2d"] { |
| 4017 | + --example-accent: #0891b2; |
| 4018 | + --example-soft: rgba(8,145,178,0.11); |
| 4019 | + --example-border: rgba(8,145,178,0.32); |
| 4020 | +} |
| 4021 | +.canvas-playground [data-cat="webgl"] { |
| 4022 | + --example-accent: #db2777; |
| 4023 | + --example-soft: rgba(219,39,119,0.10); |
| 4024 | + --example-border: rgba(219,39,119,0.30); |
| 4025 | +} |
| 4026 | +.canvas-playground [data-cat="webgpu"] { |
| 4027 | + --example-accent: #7c3aed; |
| 4028 | + --example-soft: rgba(124,58,237,0.11); |
| 4029 | + --example-border: rgba(124,58,237,0.30); |
| 4030 | +} |
| 4031 | +.canvas-playground [data-cat="three"] { |
| 4032 | + --example-accent: #16a34a; |
| 4033 | + --example-soft: rgba(22,163,74,0.11); |
| 4034 | + --example-border: rgba(22,163,74,0.30); |
| 4035 | +} |
| 4036 | +.canvas-playground [data-cat="pixi"] { |
| 4037 | + --example-accent: #ea580c; |
| 4038 | + --example-soft: rgba(234,88,12,0.11); |
| 4039 | + --example-border: rgba(234,88,12,0.30); |
| 4040 | +} |
| 4041 | +.canvas-playground.is-dark [data-cat="2d"] { |
| 4042 | + --example-accent: #22d3ee; |
| 4043 | + --example-soft: rgba(34,211,238,0.14); |
| 4044 | + --example-border: rgba(34,211,238,0.32); |
| 4045 | +} |
| 4046 | +.canvas-playground.is-dark [data-cat="webgl"] { |
| 4047 | + --example-accent: #f472b6; |
| 4048 | + --example-soft: rgba(244,114,182,0.14); |
| 4049 | + --example-border: rgba(244,114,182,0.32); |
| 4050 | +} |
| 4051 | +.canvas-playground.is-dark [data-cat="webgpu"] { |
| 4052 | + --example-accent: #a78bfa; |
| 4053 | + --example-soft: rgba(167,139,250,0.15); |
| 4054 | + --example-border: rgba(167,139,250,0.34); |
| 4055 | +} |
| 4056 | +.canvas-playground.is-dark [data-cat="three"] { |
| 4057 | + --example-accent: #4ade80; |
| 4058 | + --example-soft: rgba(74,222,128,0.14); |
| 4059 | + --example-border: rgba(74,222,128,0.32); |
| 4060 | +} |
| 4061 | +.canvas-playground.is-dark [data-cat="pixi"] { |
| 4062 | + --example-accent: #fb923c; |
| 4063 | + --example-soft: rgba(251,146,60,0.14); |
| 4064 | + --example-border: rgba(251,146,60,0.32); |
| 4065 | +} |
3969 | 4066 | .canvas-playground .category-select { padding: 12px 14px 6px; } |
3970 | 4067 | .canvas-playground .category-select label { |
3971 | 4068 | display: block; color: var(--vp-c-text-3); font-size: 11px; margin-bottom: 6px; |
|
0 commit comments