WIP PWA for Grain
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add fallback avatar when image URL is missing or fails to load

Shows a person silhouette SVG when no src is provided or when the image
fails to load, with proper accessibility attributes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+40 -3
+40 -3
src/components/atoms/grain-avatar.js
··· 4 4 static properties = { 5 5 src: { type: String }, 6 6 alt: { type: String }, 7 - size: { type: String } 7 + size: { type: String }, 8 + _hasError: { type: Boolean, state: true } 8 9 }; 9 10 10 11 static styles = css` ··· 12 13 display: block; 13 14 flex-shrink: 0; 14 15 } 15 - img { 16 + img, .fallback { 16 17 display: block; 17 18 border-radius: 50%; 18 19 object-fit: cover; 19 20 background: var(--color-bg-elevated); 20 21 } 22 + .fallback { 23 + display: flex; 24 + align-items: center; 25 + justify-content: center; 26 + color: var(--color-text-tertiary, #666); 27 + } 28 + .fallback svg { 29 + width: 60%; 30 + height: 60%; 31 + } 21 32 .sm { 22 33 width: var(--avatar-size-sm); 23 34 height: var(--avatar-size-sm); ··· 36 47 super(); 37 48 this.size = 'sm'; 38 49 this.alt = ''; 50 + this._hasError = false; 51 + } 52 + 53 + updated(changedProperties) { 54 + if (changedProperties.has('src')) { 55 + this._hasError = false; 56 + } 57 + } 58 + 59 + _onError() { 60 + this._hasError = true; 61 + } 62 + 63 + _renderFallback() { 64 + return html` 65 + <div class="fallback ${this.size}" role="img" aria-label=${this.alt || 'Avatar'}> 66 + <svg viewBox="0 0 24 24" fill="currentColor"> 67 + <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/> 68 + </svg> 69 + </div> 70 + `; 39 71 } 40 72 41 73 render() { 74 + if (!this.src || this._hasError) { 75 + return this._renderFallback(); 76 + } 77 + 42 78 return html` 43 79 <img 44 80 class=${this.size} 45 - src=${this.src || ''} 81 + src=${this.src} 46 82 alt=${this.alt} 47 83 loading="lazy" 84 + @error=${this._onError} 48 85 > 49 86 `; 50 87 }