brewlog/templates/partials/tab_bar.html
Jon Seager 920931ba17
refactor: fix template review findings (security, macros, tokens)
Address findings from the templates code review:

- Fix XSS in admin.html onclick handlers via data attributes
- Fix XSS in 5 edit page signal initializations via JSON serialization
- Fix register.html token exposure by moving to data attribute
- Add entity_icon, quick_notes_toggles, add_form_submit macros
- Replace hardcoded colors with design tokens (warning, error, success)
- Add warning design tokens to CSS theme
- Scope MutationObserver to main element
- Add defer to webauthn.js script tags
- Refactor login/register JS to arrow functions
- Guard lightbox script behind image_url check
- Fix else-if to elif in 5 templates
2026-02-13 16:20:30 +00:00

71 lines
2.5 KiB
HTML

{% import "partials/icons.html" as icons %}
{% import "partials/entity_icon.html" as ei %}
<div
data-signals:{{ tab_signal }}="'{{ active_type }}'"
data-signals:_tabs-open="false"
>
<!-- Desktop tabs -->
<nav class="hidden md:flex gap-1.5" role="tablist">
{% for tab in tabs %}
<button
type="button"
role="tab"
class="tab"
data-class:tab-active="{{ tab_signal_js }} === '{{ tab.key }}'"
data-on:click="{{ tab_signal_js }} = '{{ tab.key }}'{% if !tab_base_url.is_empty() %}
; history.pushState(null, '', '{{ tab_base_url }}{{ tab.key }}');
@get('{{ tab_base_url }}{{ tab.key }}', {responseOverrides: {selector:
'{{ tab_fetch_target }}', mode: '{{ tab_fetch_mode }}'}})
{% endif %}"
>
{{ ei::entity_icon(tab.key, "h-4 w-4 shrink-0") }}
{{ tab.label }}
</button>
{% endfor %}
</nav>
<!-- Mobile tab selector -->
<div class="md:hidden">
<button
type="button"
class="flex w-full items-center justify-between rounded-md border border-accent p-3 text-sm font-medium text-accent"
data-on:click="$_tabsOpen = !$_tabsOpen"
>
<span>
{% for tab in tabs %}
<span
data-show="{{ tab_signal_js }} === '{{ tab.key }}'"
class="inline-flex items-center gap-1.5"
>{{ ei::entity_icon(tab.key, "h-4 w-4 shrink-0") }}
{{ tab.label }}</span
>
{% endfor %}
</span>
<span data-show="!$_tabsOpen">{{ icons::chevron_down("h-5 w-5") }}</span>
<span data-show="$_tabsOpen" style="display:none"
>{{ icons::chevron_up("h-5 w-5") }}</span
>
</button>
<div
class="mt-1 flex flex-col rounded-md border overflow-hidden"
data-show="$_tabsOpen"
style="display:none"
>
{% for tab in tabs %}
<button
type="button"
class="tab-mobile"
data-class:tab-mobile-active="{{ tab_signal_js }} === '{{ tab.key }}'"
data-on:click="{{ tab_signal_js }} = '{{ tab.key }}'; $_tabsOpen = false{% if !tab_base_url.is_empty() %}
; history.pushState(null, '', '{{ tab_base_url }}{{ tab.key }}');
@get('{{ tab_base_url }}{{ tab.key }}', {responseOverrides:
{selector: '{{ tab_fetch_target }}', mode: '{{ tab_fetch_mode }}'}})
{% endif %}"
>
{{ ei::entity_icon(tab.key, "h-4 w-4 shrink-0") }}
{{ tab.label }}
</button>
{% endfor %}
</div>
</div>
</div>