fix(sys-bar): fix hover bounce, horizontal overflow, add collapsible sections
- Hover info strip is now absolute-positioned above the bar (opacity fade with delay-500) so it never shifts the bar layout — fixes the bounce - Panel widened to w-80 with overflow-x-hidden — fixes horizontal scroll caused by sub-components hardcoding w-72 inside the padded panel - All panel sections are now collapsible (Access open by default, others closed) — reduces vertical crowding; matches launcher_cfg pattern - Section headers show current state inline (access level, theme name/mode) - Admin section groups cfg + debug trigger together cleanly - Bar transitions use duration-200 for snappier feel without bounce Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -130,6 +130,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Panel section collapse state ─────────────────────────────────────────
|
||||||
|
// Open/closed per section — access open by default (most common action).
|
||||||
|
let sec_access = $state(true);
|
||||||
|
let sec_signin = $state(false);
|
||||||
|
let sec_appearance = $state(false);
|
||||||
|
let sec_admin = $state(false);
|
||||||
|
|
||||||
// ── Derived display helpers ──────────────────────────────────────────────
|
// ── Derived display helpers ──────────────────────────────────────────────
|
||||||
let font_label = $derived.by(() => {
|
let font_label = $derived.by(() => {
|
||||||
if ($ae_loc.font_size_mode === 'larger') return 'A+';
|
if ($ae_loc.font_size_mode === 'larger') return 'A+';
|
||||||
@@ -159,8 +166,8 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- ══════════════════════════════════════════════════════════════════════════
|
<!-- ══════════════════════════════════════════════════════════════════════════
|
||||||
OUTER WRAPPER — fixed bottom-right, hidden on print, hidden in iframe
|
OUTER WRAPPER — fixed bottom-right, hidden on print
|
||||||
(unless trusted_access — mirrors existing +layout.svelte condition)
|
Visibility when in iframe is controlled by +layout.svelte (trusted_access gate)
|
||||||
══════════════════════════════════════════════════════════════════════════ -->
|
══════════════════════════════════════════════════════════════════════════ -->
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
@@ -178,33 +185,34 @@
|
|||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
ae_sys_panel
|
ae_sys_panel
|
||||||
flex flex-col items-end gap-2
|
flex flex-col items-stretch gap-0
|
||||||
w-72 max-w-[92vw]
|
w-80 max-w-[94vw]
|
||||||
max-h-[80vh] overflow-y-auto
|
max-h-[80vh] overflow-y-auto overflow-x-hidden
|
||||||
bg-white dark:bg-gray-900
|
bg-white dark:bg-gray-900
|
||||||
border border-gray-200 dark:border-gray-700
|
border border-gray-200 dark:border-gray-700
|
||||||
rounded-xl shadow-2xl
|
rounded-xl shadow-2xl
|
||||||
px-2 py-3
|
|
||||||
text-sm
|
text-sm
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<!-- Close row -->
|
<!-- Panel header: person info + close -->
|
||||||
<div class="flex items-center justify-between w-full px-1">
|
<div class="flex items-center justify-between px-3 py-2 border-b border-gray-100 dark:border-gray-800 sticky top-0 bg-white dark:bg-gray-900 z-10">
|
||||||
<!-- Person + access summary in panel header -->
|
<div class="flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400 min-w-0">
|
||||||
<div class="flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400">
|
|
||||||
{#if $ae_loc?.person_id}
|
{#if $ae_loc?.person_id}
|
||||||
<User size="0.9em" class="shrink-0" />
|
<User size="0.9em" class="shrink-0" />
|
||||||
<span>{person_display ?? '—'}</span>
|
<span class="truncate">{person_display ?? '—'}</span>
|
||||||
{/if}
|
{/if}
|
||||||
{#if access_label}
|
{#if access_label}
|
||||||
<span class="font-semibold text-primary-600 dark:text-primary-400">
|
<span class="font-semibold text-primary-600 dark:text-primary-400 shrink-0">
|
||||||
· {access_label}
|
· {access_label}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if !$ae_loc?.person_id && !access_label}
|
||||||
|
<span class="italic opacity-50">Not signed in</span>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-icon btn-sm preset-tonal-surface hover:preset-filled-error transition-all"
|
class="btn btn-icon btn-sm preset-tonal-surface hover:preset-filled-error transition-all shrink-0 ml-2"
|
||||||
onclick={toggle_expand}
|
onclick={toggle_expand}
|
||||||
title="Close menu"
|
title="Close menu"
|
||||||
>
|
>
|
||||||
@@ -212,55 +220,121 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── Sign In / Out ────────────────────────────────────────────── -->
|
<!-- ── Sign In / Out (collapsible) ──────────────────────────────── -->
|
||||||
{#if $ae_loc?.app_cfg?.show_element__sign_in_out}
|
{#if $ae_loc?.app_cfg?.show_element__sign_in_out}
|
||||||
<div class="w-full border-t border-gray-100 dark:border-gray-800 pt-2">
|
<div class="border-b border-gray-100 dark:border-gray-800">
|
||||||
<Element_sign_in_out
|
|
||||||
{data}
|
|
||||||
hidden={$ae_loc.iframe || !$ae_loc.app_cfg?.show_element__sign_in_out}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- ── Access Level / Passcode ──────────────────────────────────── -->
|
|
||||||
{#if !$ae_loc?.sys_menu?.hide_access_type && !$ae_loc?.iframe}
|
|
||||||
<div class="w-full border-t border-gray-100 dark:border-gray-800 pt-2">
|
|
||||||
<Element_access_type
|
|
||||||
bind:hide={$ae_loc.sys_menu.hide_access_type}
|
|
||||||
bind:focus_input={$ae_sess.sys_menu.focus_passcode_input}
|
|
||||||
bind:expand={$ae_loc.sys_menu.expand_access_type}
|
|
||||||
bind:show_passcode_input={$ae_sess.app_cfg.show_element__passcode_input}
|
|
||||||
bind:trigger_clear_access
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- ── Appearance — theme name (always shown in panel) ─────────── -->
|
|
||||||
<div class="w-full border-t border-gray-100 dark:border-gray-800 pt-2">
|
|
||||||
<Element_theme
|
|
||||||
hide={false}
|
|
||||||
expand={true}
|
|
||||||
set_theme_mode={true}
|
|
||||||
set_theme_name={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ── Admin / Config (edit mode only) ─────────────────────────── -->
|
|
||||||
{#if $ae_loc.edit_mode}
|
|
||||||
<div class="w-full border-t border-gray-100 dark:border-gray-800 pt-2">
|
|
||||||
<Element_app_cfg hide={false} expand={true} />
|
|
||||||
</div>
|
|
||||||
<!-- Debug trigger — opens the e_app_debug_menu overlay (still managed in +layout.svelte) -->
|
|
||||||
<div class="w-full border-t border-gray-100 dark:border-gray-800 pt-2 flex justify-end">
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-sm preset-outlined-error-400-600 hover:preset-tonal-error transition-all group/dbg"
|
class="w-full flex items-center justify-between px-3 py-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
|
||||||
onclick={() => { $ae_loc.debug_menu.expand = !$ae_loc.debug_menu.expand; }}
|
onclick={() => sec_signin = !sec_signin}
|
||||||
title="Toggle debug overlay"
|
|
||||||
>
|
>
|
||||||
<Bug size="1em" class="shrink-0" />
|
<span class="flex items-center gap-1">
|
||||||
<span class="hidden group-hover/dbg:inline text-xs ml-0.5">Debug</span>
|
<span class="fas fa-sign-in-alt opacity-60"></span>
|
||||||
|
Sign In / Out
|
||||||
|
</span>
|
||||||
|
<span class="opacity-50">{sec_signin ? '▲' : '▼'}</span>
|
||||||
</button>
|
</button>
|
||||||
|
{#if sec_signin}
|
||||||
|
<div class="px-2 pb-2">
|
||||||
|
<Element_sign_in_out
|
||||||
|
{data}
|
||||||
|
hidden={$ae_loc.iframe || !$ae_loc.app_cfg?.show_element__sign_in_out}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<!-- ── Access Level / Passcode (collapsible) ────────────────────── -->
|
||||||
|
{#if !$ae_loc?.sys_menu?.hide_access_type && !$ae_loc?.iframe}
|
||||||
|
<div class="border-b border-gray-100 dark:border-gray-800">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="w-full flex items-center justify-between px-3 py-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
|
||||||
|
onclick={() => sec_access = !sec_access}
|
||||||
|
>
|
||||||
|
<span class="flex items-center gap-1">
|
||||||
|
<span class="fas fa-shield-alt opacity-60"></span>
|
||||||
|
Access / Passcode
|
||||||
|
{#if access_label}
|
||||||
|
<span class="normal-case font-normal text-primary-600 dark:text-primary-400 ml-1">({access_label})</span>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
<span class="opacity-50">{sec_access ? '▲' : '▼'}</span>
|
||||||
|
</button>
|
||||||
|
{#if sec_access}
|
||||||
|
<div class="px-2 pb-2">
|
||||||
|
<Element_access_type
|
||||||
|
bind:hide={$ae_loc.sys_menu.hide_access_type}
|
||||||
|
bind:focus_input={$ae_sess.sys_menu.focus_passcode_input}
|
||||||
|
bind:expand={$ae_loc.sys_menu.expand_access_type}
|
||||||
|
bind:show_passcode_input={$ae_sess.app_cfg.show_element__passcode_input}
|
||||||
|
bind:trigger_clear_access
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<!-- ── Appearance (collapsible) ─────────────────────────────────── -->
|
||||||
|
<div class="border-b border-gray-100 dark:border-gray-800">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="w-full flex items-center justify-between px-3 py-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
|
||||||
|
onclick={() => sec_appearance = !sec_appearance}
|
||||||
|
>
|
||||||
|
<span class="flex items-center gap-1">
|
||||||
|
<span class="fas fa-palette opacity-60"></span>
|
||||||
|
Appearance
|
||||||
|
<span class="normal-case font-normal opacity-60 ml-1">
|
||||||
|
({$ae_loc?.theme_name ?? '—'} · {$ae_loc?.theme_mode ?? '—'})
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span class="opacity-50">{sec_appearance ? '▲' : '▼'}</span>
|
||||||
|
</button>
|
||||||
|
{#if sec_appearance}
|
||||||
|
<div class="px-2 pb-2">
|
||||||
|
<Element_theme
|
||||||
|
hide={false}
|
||||||
|
expand={true}
|
||||||
|
set_theme_mode={true}
|
||||||
|
set_theme_name={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ── Admin / Config (edit mode only, collapsible) ─────────────── -->
|
||||||
|
{#if $ae_loc.edit_mode}
|
||||||
|
<div class="border-b border-gray-100 dark:border-gray-800">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="w-full flex items-center justify-between px-3 py-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
|
||||||
|
onclick={() => sec_admin = !sec_admin}
|
||||||
|
>
|
||||||
|
<span class="flex items-center gap-1">
|
||||||
|
<span class="fas fa-tools opacity-60"></span>
|
||||||
|
Admin / Config
|
||||||
|
</span>
|
||||||
|
<span class="opacity-50">{sec_admin ? '▲' : '▼'}</span>
|
||||||
|
</button>
|
||||||
|
{#if sec_admin}
|
||||||
|
<div class="px-2 pb-2 flex flex-col gap-2">
|
||||||
|
<Element_app_cfg hide={false} expand={true} />
|
||||||
|
<!-- Debug overlay trigger -->
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm w-full preset-outlined-error-400-600 hover:preset-tonal-error transition-all"
|
||||||
|
onclick={() => { $ae_loc.debug_menu.expand = !$ae_loc.debug_menu.expand; }}
|
||||||
|
title="Toggle debug overlay ($ae_loc dump)"
|
||||||
|
>
|
||||||
|
<Bug size="1em" class="shrink-0" />
|
||||||
|
<span class="text-xs ml-1">
|
||||||
|
{$ae_loc.debug_menu.expand ? 'Hide' : 'Show'} Debug Overlay
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -271,34 +345,28 @@
|
|||||||
|
|
||||||
<!-- ── COMPACT BAR ────────────────────────────────────────────────────── -->
|
<!-- ── COMPACT BAR ────────────────────────────────────────────────────── -->
|
||||||
<!--
|
<!--
|
||||||
group: enables group-hover label reveal on each button.
|
Outer div is `group` for group-hover.
|
||||||
On mobile / PWA: touch targets are min 44px via btn sizing.
|
The info strip is absolute (above the bar) so it never shifts the bar layout.
|
||||||
Default: icon-only. Hover: label text appears beside icon.
|
Hover labels on individual buttons use nested group/[name] variants.
|
||||||
|
delay-500 on the info strip prevents it flashing on quick mouse-overs.
|
||||||
-->
|
-->
|
||||||
<div
|
<div class="relative group">
|
||||||
class="
|
|
||||||
ae_sys_bar__strip
|
|
||||||
group
|
|
||||||
flex flex-row items-center gap-1
|
|
||||||
bg-white/80 dark:bg-gray-900/80
|
|
||||||
backdrop-blur-sm
|
|
||||||
border border-gray-200/60 dark:border-gray-700/60
|
|
||||||
rounded-xl
|
|
||||||
px-2 py-1
|
|
||||||
shadow-lg
|
|
||||||
transition-all duration-300
|
|
||||||
"
|
|
||||||
class:border-primary-400={expand}
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- Hover info strip (above/inline — reveals on group-hover when not expanded) -->
|
<!-- Hover info strip — floats above the bar, never shifts button layout -->
|
||||||
{#if !expand && (person_display || access_label)}
|
{#if !expand && (person_display || access_label)}
|
||||||
<span
|
<div
|
||||||
class="
|
class="
|
||||||
hidden group-hover:flex
|
absolute bottom-full right-0 mb-1
|
||||||
items-center gap-1
|
pointer-events-none
|
||||||
|
opacity-0 group-hover:opacity-100
|
||||||
|
transition-opacity duration-200 delay-500
|
||||||
|
flex items-center gap-1.5
|
||||||
|
bg-white/90 dark:bg-gray-900/90
|
||||||
|
border border-gray-200/60 dark:border-gray-700/60
|
||||||
|
backdrop-blur-sm rounded-lg
|
||||||
|
px-2 py-1
|
||||||
text-xs text-gray-500 dark:text-gray-400
|
text-xs text-gray-500 dark:text-gray-400
|
||||||
pr-1 border-r border-gray-200 dark:border-gray-700 mr-1
|
whitespace-nowrap shadow-md
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{#if person_display}
|
{#if person_display}
|
||||||
@@ -310,117 +378,128 @@
|
|||||||
· {access_label}
|
· {access_label}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- AUTH STATUS SHIELD ──────────────────────────────────────────── -->
|
<!-- Bar strip -->
|
||||||
<button
|
<div
|
||||||
type="button"
|
|
||||||
class="
|
class="
|
||||||
btn btn-sm
|
ae_sys_bar__strip
|
||||||
transition-all group/shield
|
flex flex-row items-center gap-1
|
||||||
{$ae_loc?.access_type && $ae_loc?.access_type !== 'anonymous'
|
bg-white/80 dark:bg-gray-900/80
|
||||||
? ($ae_loc?.user_access_type && $ae_loc?.access_type === $ae_loc?.user_access_type
|
backdrop-blur-sm
|
||||||
? 'variant-outline-surface hover:variant-ghost-warning'
|
border border-gray-200/60 dark:border-gray-700/60
|
||||||
: 'variant-outline-warning hover:variant-ghost-warning')
|
rounded-xl
|
||||||
: 'variant-outline-surface hover:variant-ghost-success'}
|
px-2 py-1
|
||||||
|
shadow-lg
|
||||||
|
transition-colors duration-300
|
||||||
"
|
"
|
||||||
onclick={handle_shield_click}
|
class:border-primary-400={expand}
|
||||||
title={
|
|
||||||
$ae_loc?.access_type && $ae_loc?.access_type !== 'anonymous'
|
|
||||||
? ($ae_loc?.user_access_type && $ae_loc?.access_type === $ae_loc?.user_access_type
|
|
||||||
? `Access: ${$ae_loc?.access_type}. Click to use a passcode.`
|
|
||||||
: `Elevated access: ${$ae_loc?.access_type}. Click to clear.`)
|
|
||||||
: 'Anonymous. Click to sign in or enter a passcode.'
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{#if $ae_loc?.access_type && $ae_loc?.access_type !== 'anonymous'}
|
|
||||||
{#if $ae_loc?.user_access_type && $ae_loc?.access_type === $ae_loc?.user_access_type}
|
<!-- AUTH STATUS SHIELD ───────────────────────────────────────── -->
|
||||||
<ShieldEllipsis size="1.1em" class="shrink-0" />
|
<button
|
||||||
|
type="button"
|
||||||
|
class="
|
||||||
|
btn btn-sm transition-all duration-200 group/shield
|
||||||
|
{$ae_loc?.access_type && $ae_loc?.access_type !== 'anonymous'
|
||||||
|
? ($ae_loc?.user_access_type && $ae_loc?.access_type === $ae_loc?.user_access_type
|
||||||
|
? 'variant-outline-surface hover:variant-ghost-warning'
|
||||||
|
: 'variant-outline-warning hover:variant-ghost-warning')
|
||||||
|
: 'variant-outline-surface hover:variant-ghost-success'}
|
||||||
|
"
|
||||||
|
onclick={handle_shield_click}
|
||||||
|
title={
|
||||||
|
$ae_loc?.access_type && $ae_loc?.access_type !== 'anonymous'
|
||||||
|
? ($ae_loc?.user_access_type && $ae_loc?.access_type === $ae_loc?.user_access_type
|
||||||
|
? `Access: ${$ae_loc?.access_type}. Click to use a passcode.`
|
||||||
|
: `Elevated access: ${$ae_loc?.access_type}. Click to clear.`)
|
||||||
|
: 'Anonymous. Click to sign in or enter a passcode.'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{#if $ae_loc?.access_type && $ae_loc?.access_type !== 'anonymous'}
|
||||||
|
{#if $ae_loc?.user_access_type && $ae_loc?.access_type === $ae_loc?.user_access_type}
|
||||||
|
<ShieldEllipsis size="1.1em" class="shrink-0" />
|
||||||
|
{:else}
|
||||||
|
<ShieldMinus size="1.1em" class="shrink-0" />
|
||||||
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<ShieldMinus size="1.1em" class="shrink-0" />
|
<ShieldUser size="1.1em" class="shrink-0" />
|
||||||
|
{/if}
|
||||||
|
<span class="hidden group-hover/shield:inline text-xs ml-0.5 transition-none">
|
||||||
|
{access_label ?? 'Auth?'}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- FONT SIZE CYCLER ─────────────────────────────────────────── -->
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm preset-tonal-surface hover:preset-tonal-primary transition-all duration-200 group/font"
|
||||||
|
onclick={cycle_font_size}
|
||||||
|
title={font_title}
|
||||||
|
>
|
||||||
|
<span class="font-bold leading-none text-sm">{font_label}</span>
|
||||||
|
<span class="hidden group-hover/font:inline text-xs ml-0.5 transition-none">Font</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- DARK / LIGHT TOGGLE ──────────────────────────────────────── -->
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm preset-tonal-surface hover:preset-tonal-secondary transition-all duration-200 group/mode"
|
||||||
|
onclick={toggle_theme_mode}
|
||||||
|
title="Toggle light/dark mode (currently: {$ae_loc?.theme_mode ?? 'unknown'})"
|
||||||
|
>
|
||||||
|
{#if $ae_loc?.theme_mode === 'dark'}
|
||||||
|
<Moon size="1.1em" class="shrink-0" />
|
||||||
|
<span class="hidden group-hover/mode:inline text-xs ml-0.5 transition-none">Dark</span>
|
||||||
|
{:else}
|
||||||
|
<Sun size="1.1em" class="shrink-0" />
|
||||||
|
<span class="hidden group-hover/mode:inline text-xs ml-0.5 transition-none">Light</span>
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- EDIT MODE TOGGLE (authenticated+ only) ───────────────────── -->
|
||||||
|
{#if $ae_loc?.authenticated_access}
|
||||||
|
{#if $ae_loc.edit_mode}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm preset-tonal-warning hover:preset-tonal-success transition-all duration-200 group/edit"
|
||||||
|
onclick={() => { $ae_loc.edit_mode = false; }}
|
||||||
|
title="Edit mode ON — click to turn off"
|
||||||
|
>
|
||||||
|
<span class="fas fa-toggle-on text-sm inline-block"></span>
|
||||||
|
<span class="hidden group-hover/edit:inline text-xs ml-0.5 transition-none">Edit</span>
|
||||||
|
</button>
|
||||||
|
{:else}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm preset-tonal-surface hover:preset-tonal-warning transition-all duration-200 group/edit"
|
||||||
|
onclick={() => { $ae_loc.edit_mode = true; }}
|
||||||
|
title="Edit mode OFF — click to turn on"
|
||||||
|
>
|
||||||
|
<span class="fas fa-toggle-off text-sm inline-block opacity-50"></span>
|
||||||
|
<span class="hidden group-hover/edit:inline text-xs ml-0.5 transition-none">Edit</span>
|
||||||
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
|
||||||
<ShieldUser size="1.1em" class="shrink-0" />
|
|
||||||
{/if}
|
{/if}
|
||||||
<span class="hidden group-hover/shield:inline text-xs ml-0.5">
|
|
||||||
{access_label ?? 'Auth?'}
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- FONT SIZE CYCLER ────────────────────────────────────────────── -->
|
<!-- MENU EXPAND / COLLAPSE ───────────────────────────────────── -->
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-sm preset-tonal-surface hover:preset-tonal-primary transition-all group/font"
|
class="btn btn-sm preset-filled-tertiary-400-600 hover:preset-filled-success transition-all duration-200 group/menu"
|
||||||
onclick={cycle_font_size}
|
onclick={toggle_expand}
|
||||||
title={font_title}
|
title={expand ? 'Close menu' : 'Open menu'}
|
||||||
>
|
>
|
||||||
<span class="font-bold leading-none text-sm">{font_label}</span>
|
{#if expand}
|
||||||
<span class="hidden group-hover/font:inline text-xs ml-0.5">Font</span>
|
<CircleX size="1.1em" class="shrink-0" />
|
||||||
</button>
|
<span class="hidden group-hover/menu:inline text-xs ml-0.5 transition-none">Close</span>
|
||||||
|
{:else}
|
||||||
<!-- DARK / LIGHT TOGGLE ─────────────────────────────────────────── -->
|
<Menu size="1.1em" class="shrink-0" />
|
||||||
<button
|
<span class="hidden group-hover/menu:inline text-xs ml-0.5 transition-none">Menu</span>
|
||||||
type="button"
|
{/if}
|
||||||
class="btn btn-sm preset-tonal-surface hover:preset-tonal-secondary transition-all group/mode"
|
</button>
|
||||||
onclick={toggle_theme_mode}
|
|
||||||
title="Toggle light/dark mode (currently: {$ae_loc?.theme_mode ?? 'unknown'})"
|
|
||||||
>
|
|
||||||
{#if $ae_loc?.theme_mode === 'dark'}
|
|
||||||
<Moon size="1.1em" class="shrink-0" />
|
|
||||||
<span class="hidden group-hover/mode:inline text-xs ml-0.5">Dark</span>
|
|
||||||
{:else}
|
|
||||||
<Sun size="1.1em" class="shrink-0" />
|
|
||||||
<span class="hidden group-hover/mode:inline text-xs ml-0.5">Light</span>
|
|
||||||
{/if}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- EDIT MODE TOGGLE (authenticated+ only) ──────────────────────── -->
|
|
||||||
{#if $ae_loc?.authenticated_access}
|
|
||||||
{#if $ae_loc.edit_mode}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-sm preset-tonal-warning hover:preset-tonal-success transition-all group/edit"
|
|
||||||
onclick={() => { $ae_loc.edit_mode = false; }}
|
|
||||||
title="Edit mode ON — click to turn off"
|
|
||||||
>
|
|
||||||
<span class="fas fa-toggle-on text-sm inline-block"></span>
|
|
||||||
<span class="hidden group-hover/edit:inline text-xs ml-0.5">Edit</span>
|
|
||||||
</button>
|
|
||||||
{:else}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-sm preset-tonal-surface hover:preset-tonal-warning transition-all group/edit"
|
|
||||||
onclick={() => { $ae_loc.edit_mode = true; }}
|
|
||||||
title="Edit mode OFF — click to turn on"
|
|
||||||
>
|
|
||||||
<span class="fas fa-toggle-off text-sm inline-block opacity-50"></span>
|
|
||||||
<span class="hidden group-hover/edit:inline text-xs ml-0.5">Edit</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- MENU EXPAND / COLLAPSE ──────────────────────────────────────── -->
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="
|
|
||||||
btn btn-sm transition-all group/menu
|
|
||||||
{expand
|
|
||||||
? 'preset-filled-tertiary-400-600 hover:preset-filled-success'
|
|
||||||
: 'preset-filled-tertiary-400-600 hover:preset-filled-success'}
|
|
||||||
"
|
|
||||||
onclick={toggle_expand}
|
|
||||||
title={expand ? 'Close menu' : 'Open menu'}
|
|
||||||
>
|
|
||||||
{#if expand}
|
|
||||||
<CircleX size="1.1em" class="shrink-0" />
|
|
||||||
<span class="hidden group-hover/menu:inline text-xs ml-0.5">Close</span>
|
|
||||||
{:else}
|
|
||||||
<Menu size="1.1em" class="shrink-0" />
|
|
||||||
<span class="hidden group-hover/menu:inline text-xs ml-0.5">Menu</span>
|
|
||||||
{/if}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- END: Compact bar -->
|
<!-- END: Compact bar -->
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user