Introduces a widget system where domains register UI fragments into named slots (container_nav, container_card, account_page, account_link). Host apps iterate widgets generically without naming any domain. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
39 lines
1.7 KiB
HTML
39 lines
1.7 KiB
HTML
{# Calendar entries nav items — loaded via widget registry #}
|
||
{% set entry_list = ctx.entries if ctx.entries is defined else [] %}
|
||
{% set current_page = ctx.page if ctx.page is defined else 1 %}
|
||
{% set has_more_entries = ctx.has_more if ctx.has_more is defined else False %}
|
||
|
||
{% for entry in entry_list %}
|
||
{% set _entry_path = '/' + post.slug + '/calendars/' + entry.calendar_slug + '/' + entry.start_at.year|string + '/' + entry.start_at.month|string + '/' + entry.start_at.day|string + '/entries/' + entry.id|string + '/' %}
|
||
<a
|
||
href="{{ events_url(_entry_path) }}"
|
||
class="{{styles.nav_button_less_pad}}"
|
||
>
|
||
{% if post.feature_image %}
|
||
<img src="{{ post.feature_image }}"
|
||
alt="{{ post.title }}"
|
||
class="w-8 h-8 rounded object-cover flex-shrink-0" />
|
||
{% else %}
|
||
<div class="w-8 h-8 rounded bg-stone-200 flex-shrink-0"></div>
|
||
{% endif %}
|
||
<div class="flex-1 min-w-0">
|
||
<div class="font-medium truncate">{{ entry.name }}</div>
|
||
<div class="text-xs text-stone-600 truncate">
|
||
{{ entry.start_at.strftime('%b %d, %Y at %H:%M') }}
|
||
{% if entry.end_at %} – {{ entry.end_at.strftime('%H:%M') }}{% endif %}
|
||
</div>
|
||
</div>
|
||
</a>
|
||
{% endfor %}
|
||
|
||
{# Load more entries one at a time until container is full #}
|
||
{% if has_more_entries %}
|
||
<div id="entries-load-sentinel-{{ current_page }}"
|
||
hx-get="{{ url_for('blog.post.widget_paginate', slug=post.slug, widget_domain='calendar', page=current_page + 1) }}"
|
||
hx-trigger="intersect once"
|
||
hx-swap="beforebegin"
|
||
_="on htmx:afterRequest trigger scroll on #associated-entries-container"
|
||
class="flex-shrink-0 w-1">
|
||
</div>
|
||
{% endif %}
|