v0.151.0
  1{% if toolbar.should_render() %}
  2{% set items=toolbar.get_items() %}
  3<script defer src="{{ asset('toolbar/toolbar.js') }}" nonce="{{ request.csp_nonce }}"></script>
  4<div id="plaintoolbar"
  5     data-collapsed="true"
  6     data-expanded="false"
  7     data-items-open="false"
  8     data-position="left"
  9     class="group data-[hidden]:hidden! print:hidden text-stone-300 fixed bottom-0 w-full z-50 flex flex-col">
 10
 11    {#
 12        Details panel. Visibility is driven entirely by data attributes on the
 13        wrapper (no JS class toggling): shown when data-expanded=true, but
 14        force-hidden on desktop while the bar is a collapsed pill.
 15    #}
 16    <div id="plaintoolbar-details" class="hidden group-data-[expanded=true]:block sm:group-data-[collapsed=true]:hidden! relative text-sm border-white/5 shadow-xl border-t inset-shadow-xs inset-shadow-stone-800 rounded-t-xl bg-stone-950/95 backdrop-blur-sm">
 17
 18        <div class="flex border-b border-white/5 px-2">
 19            {# Mobile: scrollable tabs #}
 20            <div id="plaintoolbar-tabs" class="flex flex-grow overflow-x-auto scrollbar-none">
 21                {% for item in items %}
 22                {% if item.name and item.panel_template_name %}
 23                <button {% if loop.first %}data-active="true"{% endif %} data-toolbar-tab="{{ item.name }}" class="data-active:border-yellow-500 px-3 sm:px-4 py-3 sm:py-2.5 -mb-px cursor-pointer border-b-2 border-transparent hover:border-yellow-600 whitespace-nowrap text-sm" type="button">{{ item.name }}</button>
 24                {% endif %}
 25                {% endfor %}
 26                <button data-plaintoolbar-expand class="flex-grow cursor-pointer inline-flex h-full min-w-[2rem]" type="button"></button>
 27            </div>
 28            <div class="px-2 sm:px-4 flex items-center gap-3 flex-shrink-0">
 29                <button title="Hide toolbar for 1 hour" class="cursor-pointer hover:text-white text-white/50" type="button" data-plaintoolbar-hideuntil>
 30                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-4 h-4" viewBox="0 0 16 16">
 31                        <path d="M8.515 1.019A7 7 0 0 0 8 1V0a8 8 0 0 1 .589.022zm2.004.45a7 7 0 0 0-.985-.299l.219-.976q.576.129 1.126.342zm1.37.71a7 7 0 0 0-.439-.27l.493-.87a8 8 0 0 1 .979.654l-.615.789a7 7 0 0 0-.418-.302zm1.834 1.79a7 7 0 0 0-.653-.796l.724-.69q.406.429.747.91zm.744 1.352a7 7 0 0 0-.214-.468l.893-.45a8 8 0 0 1 .45 1.088l-.95.313a7 7 0 0 0-.179-.483m.53 2.507a7 7 0 0 0-.1-1.025l.985-.17q.1.58.116 1.17zm-.131 1.538q.05-.254.081-.51l.993.123a8 8 0 0 1-.23 1.155l-.964-.267q.069-.247.12-.501m-.952 2.379q.276-.436.486-.908l.914.405q-.24.54-.555 1.038zm-.964 1.205q.183-.183.35-.378l.758.653a8 8 0 0 1-.401.432z"/>
 32                        <path d="M8 1a7 7 0 1 0 4.95 11.95l.707.707A8.001 8.001 0 1 1 8 0z"/>
 33                        <path d="M7.5 3a.5.5 0 0 1 .5.5v5.21l3.248 1.856a.5.5 0 0 1-.496.868l-3.5-2A.5.5 0 0 1 7 9V3.5a.5.5 0 0 1 .5-.5"/>
 34                    </svg>
 35                </button>
 36            </div>
 37        </div>
 38
 39        {# Resize handle - hidden on mobile (touch resize not supported) #}
 40        <div data-resizer class="hidden sm:block cursor-grab w-20 h-1.5 bg-white/15 rounded-full absolute top-1 left-1/2 -translate-x-1/2"></div>
 41
 42        {# Panel content - taller on mobile for better usability #}
 43        <div class="overflow-auto h-[50vh] sm:h-[30vh] flex flex-col">
 44            {% for item in items %}
 45            {% if item.name and item.panel_template_name %}
 46            <div data-toolbar-tab="{{ item.name }}" class="h-full {% if not loop.first %}hidden{% endif %}">
 47                {{ item.render_panel() }}
 48            </div>
 49            {% endif %}
 50            {% endfor %}
 51        </div>
 52
 53    </div>
 54
 55    {#
 56        Bar layout:
 57        - Mobile (always): floating pill at the chosen position
 58        - Desktop collapsed pill: floating pill at the chosen position
 59        - Desktop uncollapsed (group-data-[collapsed=false]): full-width bottom bar
 60    #}
 61    {#
 62        The pill's three positions are pure CSS translateX off a fixed left-0
 63        anchor, so resize needs no JS. data-animate (set by toolbar.js only for
 64        a snap or cycle) gates the slide transition; drag/dock stay instant.
 65    #}
 66    <div
 67        id="plaintoolbar-bar"
 68        class="fixed bottom-3 left-0 z-50 w-fit rounded-full py-2.5 cursor-grab
 69               group-data-[position=left]:[transform:translateX(0.75rem)]
 70               group-data-[position=center]:[transform:translateX(calc(50vw_-_50%))]
 71               group-data-[position=right]:[transform:translateX(calc(100vw_-_100%_-_0.75rem))]
 72               data-[animate]:transition-transform data-[animate]:duration-200 data-[animate]:ease-out
 73               border border-white/10
 74               sm:group-data-[collapsed=false]:relative sm:group-data-[collapsed=false]:inset-auto sm:group-data-[collapsed=false]:z-auto
 75               sm:group-data-[collapsed=false]:[transform:none]
 76               sm:group-data-[collapsed=false]:w-auto sm:group-data-[collapsed=false]:rounded-none sm:group-data-[collapsed=false]:py-2
 77               sm:group-data-[collapsed=false]:border-0 sm:group-data-[collapsed=false]:border-t sm:group-data-[collapsed=false]:border-white/5
 78               sm:group-data-[collapsed=false]:cursor-default
 79               flex px-3 text-xs gap-3
 80               bg-stone-950 shadow-xl"
 81    >
 82        {# Version: tappable toggle on mobile / desktop pill #}
 83        <button id="plaintoolbar-version" class="flex sm:group-data-[collapsed=false]:hidden items-center flex-shrink-0 cursor-pointer whitespace-nowrap" type="button">
 84            {{ toolbar.version }}
 85        </button>
 86        {# Version: selectable, non-interactive text on the desktop full bar #}
 87        <span class="hidden sm:group-data-[collapsed=false]:flex items-center flex-shrink-0 whitespace-nowrap select-all">{{ toolbar.version }}</span>
 88
 89        {# Filler that expands the panel - desktop full bar only #}
 90        <button type="button" data-plaintoolbar-expand class="hidden sm:group-data-[collapsed=false]:block flex-grow cursor-pointer min-w-0" title="Toggle panel"></button>
 91
 92        {#
 93            Items list:
 94            - desktop full bar: always shown
 95            - mobile: shown when data-items-open=true (toggled by the version button)
 96            - desktop pill: hidden
 97        #}
 98        <div id="plaintoolbar-items" class="hidden max-sm:group-data-[items-open=true]:flex sm:group-data-[collapsed=false]:flex items-center min-w-0">
 99            <div class="flex items-center gap-3 transition-all min-w-0 [&>button]:max-w-[200px] sm:[&>button]:max-w-none">
100
101                {% for item in items %}
102                {% if item.button_template_name %}
103                {{ item.render_button() }}
104                {% endif %}
105                {% endfor %}
106
107                {% include "toolbar/links.html" ignore missing %}
108
109                <button data-plaintoolbar-expand class="hidden sm:group-data-[collapsed=false]:inline-flex hover:text-white text-white/50 cursor-pointer" type="button" title="Toggle panel">
110                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-3.5 h-3.5 transition-transform group-data-[expanded=true]:rotate-180" viewBox="0 0 16 16">
111                        <path fill-rule="evenodd" d="M7.646 4.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1-.708.708L8 5.707l-5.646 5.647a.5.5 0 0 1-.708-.708z"/>
112                    </svg>
113                </button>
114
115                <button data-plaintoolbar-collapse class="hidden sm:group-data-[collapsed=false]:inline-flex hover:text-white text-white/50 cursor-pointer" type="button" title="Collapse to pill">
116                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-3.5 h-3.5" viewBox="0 0 16 16">
117                        <path fill-rule="evenodd" d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8"/>
118                    </svg>
119                </button>
120
121                <button data-plaintoolbar-hide class="hover:text-red-500 text-white/50 cursor-pointer" type="button" title="Hide toolbar">
122                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="w-4 h-4 sm:w-3.5 sm:h-3.5" viewBox="0 0 16 16">
123                        <path d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8z"/>
124                    </svg>
125                </button>
126
127            </div>
128        </div>
129    </div>
130
131</div>
132{% endif %}