feat(sys-menu): replace sys_menu with new e_app_sys_bar component
New compact bar + expandable panel design: - Compact strip (bottom-right): auth shield, font cycler, dark/light toggle, edit mode toggle (authenticated+), menu expand — icon-only by default, labels reveal on hover - Hover info strip shows person name + access level when logged in - Expanded panel: sign in/out, access/passcode, appearance (theme), admin (config + URL builder + debug trigger) — all gated same as before - Debug overlay trigger moved into admin section (edit mode only) - All business logic preserved via existing sub-components (unchanged) - e_app_sys_menu.svelte retained but no longer mounted (import commented out) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
427
src/lib/app_components/e_app_sys_bar.svelte
Normal file
427
src/lib/app_components/e_app_sys_bar.svelte
Normal file
@@ -0,0 +1,427 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
/**
|
||||||
|
* e_app_sys_bar.svelte
|
||||||
|
* Global system bar — replaces e_app_sys_menu.svelte.
|
||||||
|
*
|
||||||
|
* Visual states:
|
||||||
|
* Idle: compact icon strip (bottom-right corner)
|
||||||
|
* Hover: info strip appears above bar; button labels revealed
|
||||||
|
* Expanded: full panel slides up above the bar
|
||||||
|
*
|
||||||
|
* Sub-components are reused unchanged — all business logic lives there.
|
||||||
|
* This file only orchestrates layout, visibility, and the compact quick-actions.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
Bug,
|
||||||
|
CircleX,
|
||||||
|
Menu,
|
||||||
|
Moon,
|
||||||
|
Sun,
|
||||||
|
ShieldEllipsis,
|
||||||
|
ShieldMinus,
|
||||||
|
ShieldUser,
|
||||||
|
User,
|
||||||
|
} from '@lucide/svelte';
|
||||||
|
|
||||||
|
import { ae_loc, ae_sess, ae_api } from '$lib/stores/ae_stores';
|
||||||
|
|
||||||
|
import Element_access_type from '$lib/app_components/e_app_access_type.svelte';
|
||||||
|
import Element_app_cfg from '$lib/app_components/e_app_cfg.svelte';
|
||||||
|
import Element_sign_in_out from '$lib/app_components/e_app_sign_in_out.svelte';
|
||||||
|
import Element_theme from '$lib/app_components/e_app_theme.svelte';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
log_lvl?: number;
|
||||||
|
data: any;
|
||||||
|
hide?: null | boolean;
|
||||||
|
expand?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
log_lvl = $bindable(0),
|
||||||
|
data = null,
|
||||||
|
hide = $bindable(false),
|
||||||
|
expand = $bindable(false)
|
||||||
|
}: Props = $props();
|
||||||
|
|
||||||
|
// Passed down to Element_access_type — triggers handle_clear_access() there.
|
||||||
|
// See e_app_access_type.svelte for the full clear logic (reverts to user_access_type).
|
||||||
|
let trigger_clear_access: null | boolean = $state(null);
|
||||||
|
|
||||||
|
// ── Accessibility: font size cycler ─────────────────────────────────────
|
||||||
|
function cycle_font_size() {
|
||||||
|
const mode = $ae_loc.font_size_mode;
|
||||||
|
if (!mode || mode === 'default') {
|
||||||
|
$ae_loc.font_size_mode = 'larger';
|
||||||
|
} else if (mode === 'larger') {
|
||||||
|
$ae_loc.font_size_mode = 'smaller';
|
||||||
|
} else {
|
||||||
|
$ae_loc.font_size_mode = 'default';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Accessibility: dark / light toggle ──────────────────────────────────
|
||||||
|
function toggle_theme_mode() {
|
||||||
|
if ($ae_loc.theme_mode === 'light') {
|
||||||
|
$ae_loc.theme_mode = 'dark';
|
||||||
|
} else {
|
||||||
|
$ae_loc.theme_mode = 'light';
|
||||||
|
}
|
||||||
|
// DOM sync (class) is handled reactively in +layout.svelte effect #3
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Menu expand / collapse ───────────────────────────────────────────────
|
||||||
|
function toggle_expand() {
|
||||||
|
if (!expand) {
|
||||||
|
expand = true;
|
||||||
|
$ae_sess.sys_menu.expand = true;
|
||||||
|
$ae_loc.app_cfg.show_element__access_type = true;
|
||||||
|
|
||||||
|
if ($ae_loc?.access_type === 'anonymous') {
|
||||||
|
$ae_sess.sys_menu.focus_passcode_input = true;
|
||||||
|
} else {
|
||||||
|
$ae_loc.sys_menu.expand_user = false;
|
||||||
|
$ae_sess.show__sign_in_out__fields = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
expand = false;
|
||||||
|
$ae_sess.sys_menu.expand = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Auth shield: click behaviour depends on current auth state ───────────
|
||||||
|
// Mirrors the three-state shield logic from e_app_sys_menu.svelte.
|
||||||
|
function handle_shield_click() {
|
||||||
|
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) {
|
||||||
|
// At user's own level — offer passcode upgrade
|
||||||
|
if (!expand) {
|
||||||
|
expand = true;
|
||||||
|
$ae_sess.sys_menu.expand = true;
|
||||||
|
$ae_loc.sys_menu.hide_access_type = false;
|
||||||
|
$ae_loc.sys_menu.expand_access_type = true;
|
||||||
|
} else {
|
||||||
|
$ae_loc.sys_menu.hide_access_type = false;
|
||||||
|
$ae_loc.sys_menu.expand_access_type = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Elevated via passcode — offer to clear back to user level
|
||||||
|
trigger_clear_access = true;
|
||||||
|
if (expand) {
|
||||||
|
$ae_loc.sys_menu.hide_access_type = false;
|
||||||
|
expand = false;
|
||||||
|
$ae_loc.app_cfg.show_element__access_type = true;
|
||||||
|
$ae_sess.app_cfg.show_element__passcode_input = true;
|
||||||
|
} else {
|
||||||
|
$ae_loc.sys_menu.hide_access_type = false;
|
||||||
|
$ae_loc.sys_menu.expand_access_type = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Anonymous — open menu and focus passcode
|
||||||
|
expand = true;
|
||||||
|
$ae_sess.sys_menu.expand = true;
|
||||||
|
$ae_loc.sys_menu.hide_access_type = false;
|
||||||
|
$ae_loc.sys_menu.expand_access_type = true;
|
||||||
|
$ae_sess.app_cfg.show_element__passcode_input = true;
|
||||||
|
$ae_sess.sys_menu.focus_passcode_input = true;
|
||||||
|
const to_focus = document.getElementById('access_passcode_input');
|
||||||
|
to_focus?.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Derived display helpers ──────────────────────────────────────────────
|
||||||
|
let font_label = $derived.by(() => {
|
||||||
|
if ($ae_loc.font_size_mode === 'larger') return 'A+';
|
||||||
|
if ($ae_loc.font_size_mode === 'smaller') return 'A−';
|
||||||
|
return 'A';
|
||||||
|
});
|
||||||
|
|
||||||
|
let font_title = $derived.by(() => {
|
||||||
|
if ($ae_loc.font_size_mode === 'larger') return 'Font: Larger — click for Smaller';
|
||||||
|
if ($ae_loc.font_size_mode === 'smaller') return 'Font: Smaller — click for Normal';
|
||||||
|
return 'Font: Normal — click for Larger';
|
||||||
|
});
|
||||||
|
|
||||||
|
let person_display = $derived(
|
||||||
|
$ae_loc?.person?.informal_name ?? $ae_loc?.person?.given_name ?? null
|
||||||
|
);
|
||||||
|
|
||||||
|
let access_label = $derived.by(() => {
|
||||||
|
const t = $ae_loc?.access_type;
|
||||||
|
if (!t || t === 'anonymous') return null;
|
||||||
|
const map: Record<string, string> = {
|
||||||
|
super: 'Super', manager: 'Manager', administrator: 'Admin',
|
||||||
|
trusted: 'Trusted', public: 'Public', authenticated: 'Auth\'d'
|
||||||
|
};
|
||||||
|
return map[t] ?? t;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- ══════════════════════════════════════════════════════════════════════════
|
||||||
|
OUTER WRAPPER — fixed bottom-right, hidden on print, hidden in iframe
|
||||||
|
(unless trusted_access — mirrors existing +layout.svelte condition)
|
||||||
|
══════════════════════════════════════════════════════════════════════════ -->
|
||||||
|
<div
|
||||||
|
class="
|
||||||
|
ae_sys_bar
|
||||||
|
print:hidden
|
||||||
|
fixed bottom-4 right-2
|
||||||
|
z-50
|
||||||
|
flex flex-col items-end gap-1
|
||||||
|
"
|
||||||
|
class:hidden={hide}
|
||||||
|
>
|
||||||
|
|
||||||
|
<!-- ── EXPANDED PANEL ──────────────────────────────────────────────────── -->
|
||||||
|
{#if expand}
|
||||||
|
<div
|
||||||
|
class="
|
||||||
|
ae_sys_panel
|
||||||
|
flex flex-col items-end gap-2
|
||||||
|
w-72 max-w-[92vw]
|
||||||
|
max-h-[80vh] overflow-y-auto
|
||||||
|
bg-white dark:bg-gray-900
|
||||||
|
border border-gray-200 dark:border-gray-700
|
||||||
|
rounded-xl shadow-2xl
|
||||||
|
px-2 py-3
|
||||||
|
text-sm
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<!-- Close row -->
|
||||||
|
<div class="flex items-center justify-between w-full px-1">
|
||||||
|
<!-- Person + access summary in panel header -->
|
||||||
|
<div class="flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
{#if $ae_loc?.person_id}
|
||||||
|
<User size="0.9em" class="shrink-0" />
|
||||||
|
<span>{person_display ?? '—'}</span>
|
||||||
|
{/if}
|
||||||
|
{#if access_label}
|
||||||
|
<span class="font-semibold text-primary-600 dark:text-primary-400">
|
||||||
|
· {access_label}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-icon btn-sm preset-tonal-surface hover:preset-filled-error transition-all"
|
||||||
|
onclick={toggle_expand}
|
||||||
|
title="Close menu"
|
||||||
|
>
|
||||||
|
<CircleX size="1.1em" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ── 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">
|
||||||
|
<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
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm preset-outlined-error-400-600 hover:preset-tonal-error transition-all group/dbg"
|
||||||
|
onclick={() => { $ae_loc.debug_menu.expand = !$ae_loc.debug_menu.expand; }}
|
||||||
|
title="Toggle debug overlay"
|
||||||
|
>
|
||||||
|
<Bug size="1em" class="shrink-0" />
|
||||||
|
<span class="hidden group-hover/dbg:inline text-xs ml-0.5">Debug</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<!-- END: Expanded panel -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ── COMPACT BAR ────────────────────────────────────────────────────── -->
|
||||||
|
<!--
|
||||||
|
group: enables group-hover label reveal on each button.
|
||||||
|
On mobile / PWA: touch targets are min 44px via btn sizing.
|
||||||
|
Default: icon-only. Hover: label text appears beside icon.
|
||||||
|
-->
|
||||||
|
<div
|
||||||
|
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) -->
|
||||||
|
{#if !expand && (person_display || access_label)}
|
||||||
|
<span
|
||||||
|
class="
|
||||||
|
hidden group-hover:flex
|
||||||
|
items-center gap-1
|
||||||
|
text-xs text-gray-500 dark:text-gray-400
|
||||||
|
pr-1 border-r border-gray-200 dark:border-gray-700 mr-1
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{#if person_display}
|
||||||
|
<User size="0.8em" class="shrink-0" />
|
||||||
|
<span>{person_display}</span>
|
||||||
|
{/if}
|
||||||
|
{#if access_label}
|
||||||
|
<span class="font-semibold text-primary-600 dark:text-primary-400">
|
||||||
|
· {access_label}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<!-- AUTH STATUS SHIELD ──────────────────────────────────────────── -->
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="
|
||||||
|
btn btn-sm
|
||||||
|
transition-all 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}
|
||||||
|
<ShieldUser size="1.1em" class="shrink-0" />
|
||||||
|
{/if}
|
||||||
|
<span class="hidden group-hover/shield:inline text-xs ml-0.5">
|
||||||
|
{access_label ?? 'Auth?'}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- FONT SIZE CYCLER ────────────────────────────────────────────── -->
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm preset-tonal-surface hover:preset-tonal-primary transition-all 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">Font</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- DARK / LIGHT TOGGLE ─────────────────────────────────────────── -->
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm preset-tonal-surface hover:preset-tonal-secondary transition-all 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">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>
|
||||||
|
<!-- END: Compact bar -->
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -42,7 +42,8 @@
|
|||||||
|
|
||||||
// import MyClipboard from '$lib/app_components/e_app_clipboard.svelte';
|
// import MyClipboard from '$lib/app_components/e_app_clipboard.svelte';
|
||||||
import E_app_debug_menu from '$lib/app_components/e_app_debug_menu.svelte';
|
import E_app_debug_menu from '$lib/app_components/e_app_debug_menu.svelte';
|
||||||
import E_app_sys_menu from '$lib/app_components/e_app_sys_menu.svelte';
|
import E_app_sys_bar from '$lib/app_components/e_app_sys_bar.svelte';
|
||||||
|
// import E_app_sys_menu from '$lib/app_components/e_app_sys_menu.svelte'; // replaced by E_app_sys_bar
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
data: any;
|
data: any;
|
||||||
@@ -329,7 +330,7 @@
|
|||||||
{#if browser && (!$ae_loc?.iframe || $ae_loc?.trusted_access)}
|
{#if browser && (!$ae_loc?.iframe || $ae_loc?.trusted_access)}
|
||||||
<!-- print:hidden wrapper: sys/debug menus are fixed overlays — must not appear on printed pages -->
|
<!-- print:hidden wrapper: sys/debug menus are fixed overlays — must not appear on printed pages -->
|
||||||
<div class="print:hidden">
|
<div class="print:hidden">
|
||||||
<E_app_sys_menu {data} bind:hide={$ae_loc.sys_menu.hide} bind:expand={$ae_sess.sys_menu.expand} />
|
<E_app_sys_bar {data} bind:hide={$ae_loc.sys_menu.hide} bind:expand={$ae_sess.sys_menu.expand} />
|
||||||
|
|
||||||
<!-- You must be in Edit Mode to initially see the Debug expand button. Once expanded, you can toggle the Edit Mode while still seeing the expanded Debug content. -->
|
<!-- You must be in Edit Mode to initially see the Debug expand button. Once expanded, you can toggle the Edit Mode while still seeing the expanded Debug content. -->
|
||||||
{#if $ae_loc.edit_mode || $ae_loc.debug_menu.expand}
|
{#if $ae_loc.edit_mode || $ae_loc.debug_menu.expand}
|
||||||
|
|||||||
Reference in New Issue
Block a user