mirror of
https://github.com/svemagie/indiekit-endpoint-microsub.git
synced 2026-04-02 15:35:00 +02:00
feat: add CSS stacking avatar fallback to all templates (v1.0.49)
Phase 3 frontend harmonization: apply the same avatar fallback pattern used in ActivityPub to all Microsub templates. A fallback initials span is always rendered; when the <img> loads, it covers the fallback via absolute positioning. Broken images are removed by event delegation, revealing the initials underneath. Templates updated: item-card, item, actor, author (3 avatar sizes: 40px card, 48px detail, 80px profile). Error delegation script added to reader layout. Confab-Link: http://localhost:8080/sessions/bb4a6ec4-b711-48cd-b3d7-942ec2a9851d
This commit is contained in:
@@ -154,15 +154,40 @@
|
||||
margin-bottom: var(--space-s);
|
||||
}
|
||||
|
||||
.ms-item-card__avatar-wrap {
|
||||
flex-shrink: 0;
|
||||
height: 40px;
|
||||
position: relative;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.ms-item-card__avatar-wrap > img {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.ms-item-card__author-photo {
|
||||
border: var(--border-width-thin) solid var(--color-offset);
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
height: 40px;
|
||||
object-fit: cover;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.ms-item-card__author-photo--default {
|
||||
align-items: center;
|
||||
background: var(--color-offset);
|
||||
border-radius: 50%;
|
||||
color: var(--color-on-offset);
|
||||
display: flex;
|
||||
font-size: var(--font-size-s);
|
||||
font-weight: 600;
|
||||
height: 40px;
|
||||
justify-content: center;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.ms-item-card__author-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -496,6 +521,19 @@
|
||||
margin-bottom: var(--space-m);
|
||||
}
|
||||
|
||||
.ms-item__avatar-wrap {
|
||||
flex-shrink: 0;
|
||||
height: 48px;
|
||||
position: relative;
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
.ms-item__avatar-wrap > img {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.ms-item__author-photo {
|
||||
border-radius: 50%;
|
||||
height: 48px;
|
||||
@@ -503,6 +541,19 @@
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
.ms-item__author-photo--default {
|
||||
align-items: center;
|
||||
background: var(--color-offset);
|
||||
border-radius: 50%;
|
||||
color: var(--color-on-offset);
|
||||
display: flex;
|
||||
font-size: var(--font-size-m);
|
||||
font-weight: 600;
|
||||
height: 48px;
|
||||
justify-content: center;
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
.ms-item__author-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -1010,12 +1061,37 @@
|
||||
gap: var(--space-m);
|
||||
}
|
||||
|
||||
.ms-actor-profile__avatar-wrap {
|
||||
flex-shrink: 0;
|
||||
height: 80px;
|
||||
position: relative;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.ms-actor-profile__avatar-wrap > img {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.ms-actor-profile__avatar {
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.ms-actor-profile__avatar--default {
|
||||
align-items: center;
|
||||
background: var(--color-offset);
|
||||
border-radius: 50%;
|
||||
color: var(--color-on-offset);
|
||||
display: flex;
|
||||
font-size: var(--font-size-xl);
|
||||
font-weight: 600;
|
||||
height: 80px;
|
||||
justify-content: center;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.ms-actor-profile__info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@rmdes/indiekit-endpoint-microsub",
|
||||
"version": "1.0.48",
|
||||
"version": "1.0.49",
|
||||
"description": "Microsub endpoint for Indiekit. Enables subscribing to feeds and reading content using the Microsub protocol.",
|
||||
"keywords": [
|
||||
"indiekit",
|
||||
|
||||
@@ -11,13 +11,16 @@
|
||||
{# Actor profile card #}
|
||||
<div class="ms-actor-profile">
|
||||
<div class="ms-actor-profile__header">
|
||||
{% if actor.photo %}
|
||||
<img src="{{ actor.photo }}"
|
||||
alt=""
|
||||
class="ms-actor-profile__avatar"
|
||||
width="80"
|
||||
height="80">
|
||||
{% endif %}
|
||||
<div class="ms-actor-profile__avatar-wrap" data-avatar-fallback>
|
||||
{% if actor.photo %}
|
||||
<img src="{{ actor.photo }}"
|
||||
alt=""
|
||||
class="ms-actor-profile__avatar"
|
||||
width="80"
|
||||
height="80">
|
||||
{% endif %}
|
||||
<span class="ms-actor-profile__avatar ms-actor-profile__avatar--default" aria-hidden="true">{{ actor.name[0] | upper if actor.name else "?" }}</span>
|
||||
</div>
|
||||
<div class="ms-actor-profile__info">
|
||||
<h2 class="ms-actor-profile__name">{{ actor.name }}</h2>
|
||||
{% if actor.handle %}
|
||||
@@ -73,14 +76,17 @@
|
||||
{# Author #}
|
||||
{% if item.author %}
|
||||
<div class="ms-item-card__author" style="padding: 12px 16px 0;">
|
||||
{% if item.author.photo %}
|
||||
<img src="{{ item.author.photo }}"
|
||||
alt=""
|
||||
class="ms-item-card__author-photo"
|
||||
width="40"
|
||||
height="40"
|
||||
loading="lazy">
|
||||
{% endif %}
|
||||
<div class="ms-item-card__avatar-wrap" data-avatar-fallback>
|
||||
{% if item.author.photo %}
|
||||
<img src="{{ item.author.photo }}"
|
||||
alt=""
|
||||
class="ms-item-card__author-photo"
|
||||
width="40"
|
||||
height="40"
|
||||
loading="lazy">
|
||||
{% endif %}
|
||||
<span class="ms-item-card__author-photo ms-item-card__author-photo--default" aria-hidden="true">{{ item.author.name[0] | upper if item.author.name else "?" }}</span>
|
||||
</div>
|
||||
<div class="ms-item-card__author-info">
|
||||
<span class="ms-item-card__author-name">{{ item.author.name or "Unknown" }}</span>
|
||||
{% if item.author.url %}
|
||||
|
||||
@@ -8,14 +8,17 @@
|
||||
|
||||
{% if item.author %}
|
||||
<header class="ms-item__author">
|
||||
{% if item.author.photo %}
|
||||
<img src="{{ item.author.photo }}"
|
||||
alt=""
|
||||
class="ms-item__author-photo"
|
||||
width="48"
|
||||
height="48"
|
||||
loading="lazy">
|
||||
{% endif %}
|
||||
<div class="ms-item__avatar-wrap" data-avatar-fallback>
|
||||
{% if item.author.photo %}
|
||||
<img src="{{ item.author.photo }}"
|
||||
alt=""
|
||||
class="ms-item__author-photo"
|
||||
width="48"
|
||||
height="48"
|
||||
loading="lazy">
|
||||
{% endif %}
|
||||
<span class="ms-item__author-photo ms-item__author-photo--default" aria-hidden="true">{{ item.author.name[0] | upper if item.author.name else "?" }}</span>
|
||||
</div>
|
||||
<div class="ms-item__author-info">
|
||||
<span class="ms-item__author-name">
|
||||
{% if item.author.url %}
|
||||
|
||||
@@ -9,4 +9,6 @@
|
||||
{% include "partials/breadcrumbs.njk" %}
|
||||
{% include "partials/view-switcher.njk" %}
|
||||
{% block reader %}{% endblock %}
|
||||
{# Avatar fallback — remove broken images to reveal initials fallback underneath #}
|
||||
<script>document.addEventListener("error",function(e){var t=e.target;if(t.tagName==="IMG"&&t.closest("[data-avatar-fallback]"))t.remove()},true)</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
{# Author display #}
|
||||
{% if author %}
|
||||
<div class="author">
|
||||
{% if author.photo %}
|
||||
<img src="{{ author.photo }}" alt="" class="author__photo" width="48" height="48" loading="lazy">
|
||||
{% endif %}
|
||||
<div class="ms-item__avatar-wrap" data-avatar-fallback>
|
||||
{% if author.photo %}
|
||||
<img src="{{ author.photo }}" alt="" class="author__photo" width="48" height="48" loading="lazy">
|
||||
{% endif %}
|
||||
<span class="ms-item__author-photo ms-item__author-photo--default" aria-hidden="true">{{ author.name[0] | upper if author.name else "?" }}</span>
|
||||
</div>
|
||||
<div class="author__info">
|
||||
<span class="author__name">
|
||||
{% if author.url %}
|
||||
|
||||
@@ -53,14 +53,17 @@
|
||||
{# Author #}
|
||||
{% if item.author %}
|
||||
<div class="ms-item-card__author">
|
||||
{% if item.author.photo %}
|
||||
<img src="{{ item.author.photo }}"
|
||||
alt=""
|
||||
class="ms-item-card__author-photo"
|
||||
width="40"
|
||||
height="40"
|
||||
loading="lazy">
|
||||
{% endif %}
|
||||
<div class="ms-item-card__avatar-wrap" data-avatar-fallback>
|
||||
{% if item.author.photo %}
|
||||
<img src="{{ item.author.photo }}"
|
||||
alt=""
|
||||
class="ms-item-card__author-photo"
|
||||
width="40"
|
||||
height="40"
|
||||
loading="lazy">
|
||||
{% endif %}
|
||||
<span class="ms-item-card__author-photo ms-item-card__author-photo--default" aria-hidden="true">{{ item.author.name[0] | upper if item.author.name else "?" }}</span>
|
||||
</div>
|
||||
<div class="ms-item-card__author-info">
|
||||
<span class="ms-item-card__author-name">{{ item.author.name or "Unknown" }}</span>
|
||||
{% if item._source %}
|
||||
|
||||
Reference in New Issue
Block a user