11<script setup lang="ts">
22import { formatDuration , intervalToDuration } from ' date-fns'
3+ import { getFieldTooltip , getCacheNameTooltip , getForwardReasonTooltip , formatTooltip } from ' ~/utils/tooltips'
34
45const props = defineProps <{
56 cacheHeaders: Record <string , string >
@@ -61,10 +62,20 @@ onUnmounted(() => {
6162<template >
6263 <div class =" container" >
6364 <div >
64- Served by: <strong >{{ cacheAnalysis.servedBy.source }}</strong >
65+ <span
66+ class =" tooltip-trigger"
67+ tabindex =" 0"
68+ :title =" formatTooltip(getFieldTooltip('served-by'))"
69+ :aria-label =" `Served by: ${getFieldTooltip('served-by').text}`"
70+ >Served by:</span > <strong >{{ cacheAnalysis.servedBy.source }}</strong >
6571 </div >
6672 <div >
67- CDN node(s): <code >{{ cacheAnalysis.servedBy.cdnNodes }}</code >
73+ <span
74+ class =" tooltip-trigger"
75+ tabindex =" 0"
76+ :title =" formatTooltip(getFieldTooltip('cdn-nodes'))"
77+ :aria-label =" `CDN nodes: ${getFieldTooltip('cdn-nodes').text}`"
78+ >CDN node(s):</span > <code >{{ cacheAnalysis.servedBy.cdnNodes }}</code >
6879 </div >
6980
7081 <hr />
@@ -88,17 +99,25 @@ onUnmounted(() => {
8899 <!-- This is a bit of a hack to use the pretty <dt> styling but with sections. -->
89100 <!-- I should probably just do something custom instead. -->
90101 <dt class =" cache-heading" >
91- <h4 >
102+ <h4
103+ tabindex =" 0"
104+ class =" cache-name-heading"
105+ :title =" formatTooltip(getCacheNameTooltip(cacheName))"
106+ >
92107 ↳ <em >{{ cacheName }}</em > cache
93108 </h4 >
94109 </dt >
95110 <dd />
96111
97112 <dt
98113 class =" data-key"
114+ tabindex =" 0"
99115 :class =" { 'key-highlighted': isKeyHovered(`Hit-${cacheIndex}`) }"
116+ :title =" formatTooltip(getFieldTooltip('hit'))"
100117 @mouseenter =" handleDataKeyHover(`Hit-${cacheIndex}`, parameters.hit)"
101118 @mouseleave =" handleDataKeyLeave"
119+ @focus =" handleDataKeyHover(`Hit-${cacheIndex}`, parameters.hit)"
120+ @blur =" handleDataKeyLeave"
102121 >
103122 Hit
104123 </dt >
@@ -116,9 +135,13 @@ onUnmounted(() => {
116135 <template v-if =" parameters .fwd " >
117136 <dt
118137 class =" data-key"
138+ tabindex =" 0"
119139 :class =" { 'key-highlighted': isKeyHovered(`Forwarded because-${cacheIndex}`) }"
140+ :title =" formatTooltip(getFieldTooltip('forwarded-because'))"
120141 @mouseenter =" handleDataKeyHover(`Forwarded because-${cacheIndex}`, parameters.fwd)"
121142 @mouseleave =" handleDataKeyLeave"
143+ @focus =" handleDataKeyHover(`Forwarded because-${cacheIndex}`, parameters.fwd)"
144+ @blur =" handleDataKeyLeave"
122145 >
123146 Forwarded because
124147 </dt >
@@ -129,6 +152,7 @@ onUnmounted(() => {
129152 'value-matching': isKeyHovered(`Forwarded because-${cacheIndex}`) && isValueMatching(parameters.fwd),
130153 'value-different': isKeyHovered(`Forwarded because-${cacheIndex}`) && !isValueMatching(parameters.fwd),
131154 }"
155+ :title =" formatTooltip(getForwardReasonTooltip(parameters.fwd))"
132156 >
133157 {{ parameters.fwd }}
134158 </dd >
@@ -137,9 +161,13 @@ onUnmounted(() => {
137161 <template v-if =" parameters [' fwd-status' ]" >
138162 <dt
139163 class =" data-key"
164+ tabindex =" 0"
140165 :class =" { 'key-highlighted': isKeyHovered(`Forwarded status-${cacheIndex}`) }"
166+ :title =" formatTooltip(getFieldTooltip('forwarded-status'))"
141167 @mouseenter =" handleDataKeyHover(`Forwarded status-${cacheIndex}`, parameters['fwd-status'])"
142168 @mouseleave =" handleDataKeyLeave"
169+ @focus =" handleDataKeyHover(`Forwarded status-${cacheIndex}`, parameters['fwd-status'])"
170+ @blur =" handleDataKeyLeave"
143171 >
144172 Forwarded status
145173 </dt >
@@ -158,9 +186,13 @@ onUnmounted(() => {
158186 <template v-if =" parameters .ttl " >
159187 <dt
160188 class =" data-key"
189+ tabindex =" 0"
161190 :class =" { 'key-highlighted': isKeyHovered(`TTL-${cacheIndex}`) }"
191+ :title =" formatTooltip(getFieldTooltip('ttl'))"
162192 @mouseenter =" handleDataKeyHover(`TTL-${cacheIndex}`, parameters.ttl)"
163193 @mouseleave =" handleDataKeyLeave"
194+ @focus =" handleDataKeyHover(`TTL-${cacheIndex}`, parameters.ttl)"
195+ @blur =" handleDataKeyLeave"
164196 >
165197 TTL
166198 </dt >
@@ -186,9 +218,13 @@ onUnmounted(() => {
186218 <template v-if =" parameters .stored " >
187219 <dt
188220 class =" data-key"
221+ tabindex =" 0"
189222 :class =" { 'key-highlighted': isKeyHovered(`Stored the response-${cacheIndex}`) }"
223+ :title =" formatTooltip(getFieldTooltip('stored-response'))"
190224 @mouseenter =" handleDataKeyHover(`Stored the response-${cacheIndex}`, parameters.stored)"
191225 @mouseleave =" handleDataKeyLeave"
226+ @focus =" handleDataKeyHover(`Stored the response-${cacheIndex}`, parameters.stored)"
227+ @blur =" handleDataKeyLeave"
192228 >
193229 Stored the response
194230 </dt >
@@ -207,9 +243,13 @@ onUnmounted(() => {
207243 <template v-if =" parameters .collapsed " >
208244 <dt
209245 class =" data-key"
246+ tabindex =" 0"
210247 :class =" { 'key-highlighted': isKeyHovered(`Collapsed w/ other reqs-${cacheIndex}`) }"
248+ :title =" formatTooltip(getFieldTooltip('collapsed-requests'))"
211249 @mouseenter =" handleDataKeyHover(`Collapsed w/ other reqs-${cacheIndex}`, parameters.collapsed)"
212250 @mouseleave =" handleDataKeyLeave"
251+ @focus =" handleDataKeyHover(`Collapsed w/ other reqs-${cacheIndex}`, parameters.collapsed)"
252+ @blur =" handleDataKeyLeave"
213253 >
214254 Collapsed w/ other reqs
215255 </dt >
@@ -228,9 +268,13 @@ onUnmounted(() => {
228268 <template v-if =" parameters .key " >
229269 <dt
230270 class =" data-key"
271+ tabindex =" 0"
231272 :class =" { 'key-highlighted': isKeyHovered(`Cache key-${cacheIndex}`) }"
273+ :title =" formatTooltip(getFieldTooltip('cache-key'))"
232274 @mouseenter =" handleDataKeyHover(`Cache key-${cacheIndex}`, parameters.key)"
233275 @mouseleave =" handleDataKeyLeave"
276+ @focus =" handleDataKeyHover(`Cache key-${cacheIndex}`, parameters.key)"
277+ @blur =" handleDataKeyLeave"
234278 >
235279 Cache key
236280 </dt >
@@ -249,9 +293,13 @@ onUnmounted(() => {
249293 <template v-if =" parameters .detail " >
250294 <dt
251295 class =" data-key"
296+ tabindex =" 0"
252297 :class =" { 'key-highlighted': isKeyHovered(`Extra details-${cacheIndex}`) }"
298+ :title =" formatTooltip(getFieldTooltip('extra-details'))"
253299 @mouseenter =" handleDataKeyHover(`Extra details-${cacheIndex}`, parameters.detail)"
254300 @mouseleave =" handleDataKeyLeave"
301+ @focus =" handleDataKeyHover(`Extra details-${cacheIndex}`, parameters.detail)"
302+ @blur =" handleDataKeyLeave"
255303 >
256304 Extra details
257305 </dt >
@@ -279,9 +327,13 @@ onUnmounted(() => {
279327
280328 <dt
281329 class =" data-key"
330+ tabindex =" 0"
282331 :class =" { 'key-highlighted': isKeyHovered('Cacheable') }"
332+ :title =" formatTooltip(getFieldTooltip('cacheable'))"
283333 @mouseenter =" handleDataKeyHover('Cacheable', cacheAnalysis.cacheControl.isCacheable)"
284334 @mouseleave =" handleDataKeyLeave"
335+ @focus =" handleDataKeyHover('Cacheable', cacheAnalysis.cacheControl.isCacheable)"
336+ @blur =" handleDataKeyLeave"
285337 >
286338 Cacheable
287339 </dt >
@@ -299,9 +351,13 @@ onUnmounted(() => {
299351 <template v-if =" cacheAnalysis .cacheControl .age " >
300352 <dt
301353 class =" data-key"
354+ tabindex =" 0"
302355 :class =" { 'key-highlighted': isKeyHovered('Age') }"
356+ :title =" formatTooltip(getFieldTooltip('age'))"
303357 @mouseenter =" handleDataKeyHover('Age', cacheAnalysis.cacheControl.age)"
304358 @mouseleave =" handleDataKeyLeave"
359+ @focus =" handleDataKeyHover('Age', cacheAnalysis.cacheControl.age)"
360+ @blur =" handleDataKeyLeave"
305361 >
306362 Age
307363 </dt >
@@ -327,9 +383,13 @@ onUnmounted(() => {
327383 <template v-if =" cacheAnalysis .cacheControl .date " >
328384 <dt
329385 class =" data-key"
386+ tabindex =" 0"
330387 :class =" { 'key-highlighted': isKeyHovered('Date') }"
388+ :title =" formatTooltip(getFieldTooltip('date'))"
331389 @mouseenter =" handleDataKeyHover('Date', cacheAnalysis.cacheControl.date)"
332390 @mouseleave =" handleDataKeyLeave"
391+ @focus =" handleDataKeyHover('Date', cacheAnalysis.cacheControl.date)"
392+ @blur =" handleDataKeyLeave"
333393 >
334394 Date
335395 </dt >
@@ -354,9 +414,13 @@ onUnmounted(() => {
354414 <template v-if =" cacheAnalysis .cacheControl .etag " >
355415 <dt
356416 class =" data-key"
417+ tabindex =" 0"
357418 :class =" { 'key-highlighted': isKeyHovered('ETag') }"
419+ :title =" formatTooltip(getFieldTooltip('etag'))"
358420 @mouseenter =" handleDataKeyHover('ETag', cacheAnalysis.cacheControl.etag)"
359421 @mouseleave =" handleDataKeyLeave"
422+ @focus =" handleDataKeyHover('ETag', cacheAnalysis.cacheControl.etag)"
423+ @blur =" handleDataKeyLeave"
360424 >
361425 ETag
362426 </dt >
@@ -375,9 +439,13 @@ onUnmounted(() => {
375439 <template v-if =" cacheAnalysis .cacheControl .expiresAt " >
376440 <dt
377441 class =" data-key"
442+ tabindex =" 0"
378443 :class =" { 'key-highlighted': isKeyHovered('Expires at') }"
444+ :title =" formatTooltip(getFieldTooltip('expires-at'))"
379445 @mouseenter =" handleDataKeyHover('Expires at', cacheAnalysis.cacheControl.expiresAt)"
380446 @mouseleave =" handleDataKeyLeave"
447+ @focus =" handleDataKeyHover('Expires at', cacheAnalysis.cacheControl.expiresAt)"
448+ @blur =" handleDataKeyLeave"
381449 >
382450 Expires at
383451 </dt >
@@ -402,9 +470,13 @@ onUnmounted(() => {
402470 <template v-if =" cacheAnalysis .cacheControl .ttl " >
403471 <dt
404472 class =" data-key"
473+ tabindex =" 0"
405474 :class =" { 'key-highlighted': isKeyHovered('TTL (browser)') }"
475+ :title =" formatTooltip(getFieldTooltip('ttl-browser'))"
406476 @mouseenter =" handleDataKeyHover('TTL (browser)', cacheAnalysis.cacheControl.ttl)"
407477 @mouseleave =" handleDataKeyLeave"
478+ @focus =" handleDataKeyHover('TTL (browser)', cacheAnalysis.cacheControl.ttl)"
479+ @blur =" handleDataKeyLeave"
408480 >
409481 TTL{{
410482 cacheAnalysis.cacheControl.netlifyCdnTtl
@@ -435,9 +507,13 @@ onUnmounted(() => {
435507 <template v-if =" cacheAnalysis .cacheControl .cdnTtl " >
436508 <dt
437509 class =" data-key"
510+ tabindex =" 0"
438511 :class =" { 'key-highlighted': isKeyHovered('TTL (CDN)') }"
512+ :title =" formatTooltip(getFieldTooltip('ttl-cdn'))"
439513 @mouseenter =" handleDataKeyHover('TTL (CDN)', cacheAnalysis.cacheControl.cdnTtl)"
440514 @mouseleave =" handleDataKeyLeave"
515+ @focus =" handleDataKeyHover('TTL (CDN)', cacheAnalysis.cacheControl.cdnTtl)"
516+ @blur =" handleDataKeyLeave"
441517 >
442518 TTL ({{
443519 cacheAnalysis.cacheControl.netlifyCdnTtl
@@ -467,9 +543,13 @@ onUnmounted(() => {
467543 <template v-if =" cacheAnalysis .cacheControl .netlifyCdnTtl " >
468544 <dt
469545 class =" data-key"
546+ tabindex =" 0"
470547 :class =" { 'key-highlighted': isKeyHovered('TTL (Netlify CDN)') }"
548+ :title =" formatTooltip(getFieldTooltip('ttl-netlify-cdn'))"
471549 @mouseenter =" handleDataKeyHover('TTL (Netlify CDN)', cacheAnalysis.cacheControl.netlifyCdnTtl)"
472550 @mouseleave =" handleDataKeyLeave"
551+ @focus =" handleDataKeyHover('TTL (Netlify CDN)', cacheAnalysis.cacheControl.netlifyCdnTtl)"
552+ @blur =" handleDataKeyLeave"
473553 >
474554 TTL (Netlify CDN)
475555 </dt >
@@ -495,9 +575,13 @@ onUnmounted(() => {
495575 <template v-if =" cacheAnalysis .cacheControl .vary " >
496576 <dt
497577 class =" data-key"
578+ tabindex =" 0"
498579 :class =" { 'key-highlighted': isKeyHovered('Vary') }"
580+ :title =" formatTooltip(getFieldTooltip('vary'))"
499581 @mouseenter =" handleDataKeyHover('Vary', cacheAnalysis.cacheControl.vary)"
500582 @mouseleave =" handleDataKeyLeave"
583+ @focus =" handleDataKeyHover('Vary', cacheAnalysis.cacheControl.vary)"
584+ @blur =" handleDataKeyLeave"
501585 >
502586 Vary
503587 </dt >
@@ -516,9 +600,13 @@ onUnmounted(() => {
516600 <template v-if =" cacheAnalysis .cacheControl .netlifyVary " >
517601 <dt
518602 class =" data-key"
603+ tabindex =" 0"
519604 :class =" { 'key-highlighted': isKeyHovered('Netlify-Vary') }"
605+ :title =" formatTooltip(getFieldTooltip('netlify-vary'))"
520606 @mouseenter =" handleDataKeyHover('Netlify-Vary', cacheAnalysis.cacheControl.netlifyVary)"
521607 @mouseleave =" handleDataKeyLeave"
608+ @focus =" handleDataKeyHover('Netlify-Vary', cacheAnalysis.cacheControl.netlifyVary)"
609+ @blur =" handleDataKeyLeave"
522610 >
523611 Netlify-Vary
524612 </dt >
@@ -537,9 +625,13 @@ onUnmounted(() => {
537625 <template v-if =" cacheAnalysis .cacheControl .revalidate " >
538626 <dt
539627 class =" data-key"
628+ tabindex =" 0"
540629 :class =" { 'key-highlighted': isKeyHovered('Revalidation') }"
630+ :title =" formatTooltip(getFieldTooltip('revalidation'))"
541631 @mouseenter =" handleDataKeyHover('Revalidation', cacheAnalysis.cacheControl.revalidate)"
542632 @mouseleave =" handleDataKeyLeave"
633+ @focus =" handleDataKeyHover('Revalidation', cacheAnalysis.cacheControl.revalidate)"
634+ @blur =" handleDataKeyLeave"
543635 >
544636 Revalidation
545637 </dt >
@@ -583,6 +675,18 @@ dt.cache-heading h4 {
583675 font-size : 1.1em ;
584676}
585677
678+ dt .cache-heading h4 .cache-name-heading {
679+ cursor : help ;
680+ display : inline-block ;
681+ }
682+
683+ dt .cache-heading h4 .cache-name-heading :focus {
684+ outline : 2px solid rgb (59 , 130 , 246 );
685+ outline-offset : 2px ;
686+ border-radius : 4px ;
687+ background-color : rgba (59 , 130 , 246 , 0.1 );
688+ }
689+
586690/* Default Netlify Examples styles add ": " */
587691.cache-heading ::after {
588692 content : none ;
@@ -603,6 +707,12 @@ dd code {
603707 background-color : rgba (59 , 130 , 246 , 0.1 );
604708}
605709
710+ .data-key :focus {
711+ outline : 2px solid rgb (59 , 130 , 246 );
712+ outline-offset : 2px ;
713+ background-color : rgba (59 , 130 , 246 , 0.15 );
714+ }
715+
606716.data-key.key-highlighted {
607717 background-color : rgba (59 , 130 , 246 , 0.2 );
608718 font-weight : 600 ;
@@ -631,4 +741,24 @@ dd code {
631741 color : rgb (107 , 114 , 128 );
632742 margin-left : 0.25em ;
633743}
744+
745+ /* Tooltip trigger accessibility styles */
746+ .tooltip-trigger {
747+ cursor : help ;
748+ text-decoration : underline ;
749+ text-decoration-style : dotted ;
750+ text-decoration-color : rgba (107 , 114 , 128 , 0.5 );
751+ text-underline-offset : 2px ;
752+ }
753+
754+ .tooltip-trigger :focus {
755+ outline : 2px solid rgb (59 , 130 , 246 );
756+ outline-offset : 2px ;
757+ border-radius : 2px ;
758+ background-color : rgba (59 , 130 , 246 , 0.1 );
759+ }
760+
761+ .tooltip-trigger :hover {
762+ text-decoration-color : rgba (107 , 114 , 128 , 0.8 );
763+ }
634764 </style >
0 commit comments