File tree Expand file tree Collapse file tree
packages/hub-ui/src/client Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -20,29 +20,40 @@ const iconifyParsed = computed(() => {
2020})
2121
2222const iconifyLoaded = ref <string | undefined >(undefined )
23- watchEffect (async () => {
24- if (! iconifyParsed .value ) {
25- iconifyLoaded .value = undefined
23+ const failed = ref (false )
24+ watchEffect (async (onCleanup ) => {
25+ let active = true
26+ onCleanup (() => {
27+ active = false
28+ })
29+ iconifyLoaded .value = undefined
30+ failed .value = false
31+ if (! iconifyParsed .value )
2632 return
27- }
2833 try {
29- iconifyLoaded .value = await getIconifySvg (iconifyParsed .value .collection , iconifyParsed .value .icon )
34+ const svg = await getIconifySvg (iconifyParsed .value .collection , iconifyParsed .value .icon )
35+ if (active )
36+ iconifyLoaded .value = svg
3037 }
3138 catch {
32- // A failed icon fetch (offline / flaky CDN) should degrade to a blank icon,
33- // not throw out of the async effect and crash the surrounding panel.
34- iconifyLoaded .value = undefined
39+ /** Keep fetch failures local to the icon so the surrounding panel remains usable. */
40+ if ( active )
41+ failed .value = true
3542 }
3643})
3744 </script >
3845
3946<template >
47+ <div v-if =" failed" class =" i-ph:warning-duotone w-full h-full" aria-hidden =" true" />
4048 <div
41- v-if =" iconifyParsed"
49+ v-else-if =" iconifyParsed"
50+ aria-hidden =" true"
4251 v-html =" iconifyLoaded"
4352 />
4453 <img
4554 v-else :src =" icon"
55+ alt =" "
56+ aria-hidden =" true"
4657 class =" w-full h-full m-auto"
4758 draggable =" false"
4859 >
Original file line number Diff line number Diff line change @@ -24,10 +24,10 @@ export async function getIconifySvg(collection: string, icon: string) {
2424
2525 async function _get ( ) {
2626 const url = `https://api.iconify.design/${ collection } /${ icon } .svg?color=currentColor&width=100%`
27- // Bound the request so a stalled connection (offline / flaky CDN / firewall
28- // black-holing the host) rejects instead of hanging forever; the caller
29- // already degrades a rejected fetch to a blank icon.
30- const svg = await fetch ( url , { signal : AbortSignal . timeout ( 10_000 ) } ) . then ( res => res . text ( ) )
31- return purify . sanitize ( svg )
27+ /** Bound stalled requests so the caller can display its failure glyph. */
28+ const response = await fetch ( url , { signal : AbortSignal . timeout ( 10_000 ) } )
29+ if ( ! response . ok )
30+ throw new Error ( `Iconify request failed: ${ response . status } ` )
31+ return purify . sanitize ( await response . text ( ) )
3232 }
3333}
You can’t perform that action at this time.
0 commit comments