Files
rose-ash/shared/browser/templates/macros/nav_entries.html
giles 22802bd36b
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 5m35s
Send all responses as sexp wire format with client-side rendering
- Server sends sexp source text, client (sexp.js) renders everything
- SexpExpr marker class for nested sexp composition in serialize()
- sexp_page() HTML shell with data-mount="body" for full page loads
- sexp_response() returns text/sexp for OOB/partial responses
- ~app-body layout component replaces ~app-layout (no raw!)
- ~rich-text is the only component using raw! (for CMS HTML content)
- Fragment endpoints return text/sexp, auto-wrapped in SexpExpr
- All _*_html() helpers converted to _*_sexp() returning sexp source
- Head auto-hoist: sexp.js moves meta/title/link/script[ld+json]
  from rendered body to document.head automatically
- Unknown components render warning box instead of crashing page
- Component kwargs preserve AST for lazy rendering (fixes <> in kwargs)
- Fix unterminated paren in events/sexp/tickets.sexpr

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 09:45:07 +00:00

51 lines
2.1 KiB
HTML

{#
Composable scrollable nav entries container.
Usage:
{% call nav_entries_oob(has_items=True) %}
<a href="..." class="{{styles.nav_button_less_pad}}">...</a>
<a href="..." class="{{styles.nav_button_less_pad}}">...</a>
{% endcall %}
Each domain (events, blog, market) provides its own items via the caller block.
#}
{% macro nav_entries_oob(has_items) %}
{% if has_items %}
<div class="flex flex-col sm:flex-row sm:items-center gap-2 border-r border-stone-200 mr-2 sm:max-w-2xl"
id="entries-calendars-nav-wrapper"
sx-swap-oob="true">
<button
class="entries-nav-arrow hidden flex-shrink-0 p-2 hover:bg-stone-200 rounded"
aria-label="Scroll left"
onclick="document.getElementById('associated-items-container').scrollLeft -= 200">
<i class="fa fa-chevron-left"></i>
</button>
<div id="associated-items-container"
class="overflow-y-auto sm:overflow-x-auto sm:overflow-y-visible scrollbar-hide max-h-[50vh] sm:max-h-none"
style="scroll-behavior: smooth;"
data-scroll-arrows="entries-nav-arrow"
onscroll="(function(el){var arrows=document.getElementsByClassName('entries-nav-arrow');var show=window.innerWidth>=640&&el.scrollWidth>el.clientWidth;for(var i=0;i<arrows.length;i++){if(show){arrows[i].classList.remove('hidden');arrows[i].classList.add('flex')}else{arrows[i].classList.add('hidden');arrows[i].classList.remove('flex')}}})(this)">
<div class="flex flex-col sm:flex-row gap-1">
{{ caller() }}
</div>
</div>
<style>
.scrollbar-hide::-webkit-scrollbar { display: none; }
.scrollbar-hide { -ms-overflow-style: none; scrollbar-width: none; }
</style>
<button
class="entries-nav-arrow hidden flex-shrink-0 p-2 hover:bg-stone-200 rounded"
aria-label="Scroll right"
onclick="document.getElementById('associated-items-container').scrollLeft += 200">
<i class="fa fa-chevron-right"></i>
</button>
</div>
{% else %}
<div id="entries-calendars-nav-wrapper" sx-swap-oob="true"></div>
{% endif %}
{% endmacro %}