mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 21:39:39 +02:00
fix(mana/web): EncryptionIntroBanner sits inside the bottom-stack
The one-time encryption intro banner used its own position: fixed at
bottom: 1.5rem with z-index: 60, mounted at the root layout level.
That put it in a stacking context the QuickInputBar covered up — the
search bar visually sat ON TOP of the banner instead of below it,
making the privacy claim half-readable and the dismiss X impossible
to click.
Same fix the guest nudge got in c8ed58b7d: move into the bottom-stack
flex container in (app)/+layout.svelte and let the parent handle
positioning. The banner is now the FIRST child of the stack so it
renders above the guest nudge / QuickInputBar / TagStrip / PillNav
and stays in flow as the stack reflows when nav collapses.
- Removed `<EncryptionIntroBanner />` from root +layout.svelte (it
doesn't belong above the (app) gate anyway since it self-checks
isVaultUnlocked() which is always false outside auth context)
- Mounted inside `.bottom-stack` as the first `.bottom-stack-notification`
child in (app)/+layout.svelte
- Stripped position: fixed / bottom / left / transform / max-width /
z-index from the banner CSS — now an in-flow flex item with
width: 100% (the wrapper centres + caps width via the existing
bottom-stack-notification rules)
- Slide-up animation rewritten to use translateY only since the
parent no longer transforms the banner
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
09f81d77de
commit
2a437a5861
3 changed files with 27 additions and 13 deletions
|
|
@ -16,9 +16,17 @@
|
||||||
"you understand and accept what's happening" social contract
|
"you understand and accept what's happening" social contract
|
||||||
that encryption-at-rest requires.
|
that encryption-at-rest requires.
|
||||||
|
|
||||||
The component is mounted once at the root layout. It self-checks
|
The component is mounted inside the bottom-stack of (app)/+layout.svelte
|
||||||
the vault state on mount and via a small interval, so it can fire
|
(NOT the root layout) so it shares the stack's reflow with the
|
||||||
even if the unlock happens asynchronously after the layout renders.
|
QuickInputBar / TagStrip / PillNav and can't end up rendered
|
||||||
|
behind them. Earlier the banner used its own `position: fixed`
|
||||||
|
with z-index 60, which the QuickInputBar's higher stacking context
|
||||||
|
covered up — fix was to make positioning the parent's job.
|
||||||
|
|
||||||
|
It self-checks the vault state on mount and via a small interval,
|
||||||
|
so it can fire even if the unlock happens asynchronously after the
|
||||||
|
layout renders. Guests never see it because isVaultUnlocked()
|
||||||
|
returns false until a real master key is loaded.
|
||||||
|
|
||||||
NOTE: The flag uses a constant string instead of a STORAGE_KEYS
|
NOTE: The flag uses a constant string instead of a STORAGE_KEYS
|
||||||
import because the central storage-keys file was removed in a
|
import because the central storage-keys file was removed in a
|
||||||
|
|
@ -112,13 +120,14 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
/* Positioning is the parent's job (.bottom-stack-notification in
|
||||||
|
(app)/+layout.svelte). The banner used to be position: fixed
|
||||||
|
with its own bottom + transform centring; that put it in a
|
||||||
|
stacking context the QuickInputBar covered. Now it's a normal
|
||||||
|
in-flow flex item and the bottom-stack handles where it goes. */
|
||||||
.banner {
|
.banner {
|
||||||
position: fixed;
|
|
||||||
bottom: 1.5rem;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
max-width: 32rem;
|
max-width: 32rem;
|
||||||
width: calc(100% - 2rem);
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 0.875rem;
|
gap: 0.875rem;
|
||||||
|
|
@ -128,18 +137,17 @@
|
||||||
border-left: 4px solid rgb(34, 197, 94);
|
border-left: 4px solid rgb(34, 197, 94);
|
||||||
border-radius: 0.75rem;
|
border-radius: 0.75rem;
|
||||||
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.18);
|
box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.18);
|
||||||
z-index: 60;
|
|
||||||
animation: slide-up 250ms ease-out;
|
animation: slide-up 250ms ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes slide-up {
|
@keyframes slide-up {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: translate(-50%, 1rem);
|
transform: translateY(0.75rem);
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translate(-50%, 0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
import { todoReminderSource } from '$lib/modules/todo/reminder-source';
|
import { todoReminderSource } from '$lib/modules/todo/reminder-source';
|
||||||
import KeyboardShortcutsModal from '$lib/components/KeyboardShortcutsModal.svelte';
|
import KeyboardShortcutsModal from '$lib/components/KeyboardShortcutsModal.svelte';
|
||||||
import SessionWarning from '$lib/components/SessionWarning.svelte';
|
import SessionWarning from '$lib/components/SessionWarning.svelte';
|
||||||
|
import EncryptionIntroBanner from '$lib/components/EncryptionIntroBanner.svelte';
|
||||||
import { locale, _ } from 'svelte-i18n';
|
import { locale, _ } from 'svelte-i18n';
|
||||||
import {
|
import {
|
||||||
PillNavigation,
|
PillNavigation,
|
||||||
|
|
@ -445,6 +446,13 @@
|
||||||
<div class="min-h-screen bg-background">
|
<div class="min-h-screen bg-background">
|
||||||
<!-- Bottom Stack: all fixed-bottom elements in one flex container -->
|
<!-- Bottom Stack: all fixed-bottom elements in one flex container -->
|
||||||
<div class="bottom-stack" style:--bottom-chrome-height="{bottomChromeHeight}px">
|
<div class="bottom-stack" style:--bottom-chrome-height="{bottomChromeHeight}px">
|
||||||
|
<!-- One-time encryption intro — sits at the top of the stack so
|
||||||
|
it can't be obscured by the QuickInputBar / TagStrip / PillNav.
|
||||||
|
Self-gates on isVaultUnlocked() so guests never see it. -->
|
||||||
|
<div class="bottom-stack-notification">
|
||||||
|
<EncryptionIntroBanner />
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Guest nudge — sits above the input bar, fades with the stack -->
|
<!-- Guest nudge — sits above the input bar, fades with the stack -->
|
||||||
{#if guestMode && guestMode.notifications.length > 0}
|
{#if guestMode && guestMode.notifications.length > 0}
|
||||||
<div class="bottom-stack-notification">
|
<div class="bottom-stack-notification">
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
import { installDataLayerListeners } from '$lib/data/data-layer-listeners';
|
import { installDataLayerListeners } from '$lib/data/data-layer-listeners';
|
||||||
import { getVaultClient, hasAnyEncryption } from '$lib/data/crypto';
|
import { getVaultClient, hasAnyEncryption } from '$lib/data/crypto';
|
||||||
import SuggestionToast from '$lib/components/SuggestionToast.svelte';
|
import SuggestionToast from '$lib/components/SuggestionToast.svelte';
|
||||||
import EncryptionIntroBanner from '$lib/components/EncryptionIntroBanner.svelte';
|
|
||||||
import RecoveryCodeUnlockModal from '$lib/components/RecoveryCodeUnlockModal.svelte';
|
import RecoveryCodeUnlockModal from '$lib/components/RecoveryCodeUnlockModal.svelte';
|
||||||
import SyncConflictToast from '$lib/components/SyncConflictToast.svelte';
|
import SyncConflictToast from '$lib/components/SyncConflictToast.svelte';
|
||||||
import OfflineIndicator from '$lib/components/OfflineIndicator.svelte';
|
import OfflineIndicator from '$lib/components/OfflineIndicator.svelte';
|
||||||
|
|
@ -111,7 +110,6 @@
|
||||||
<SyncConflictToast />
|
<SyncConflictToast />
|
||||||
<OfflineIndicator />
|
<OfflineIndicator />
|
||||||
<PwaUpdatePrompt />
|
<PwaUpdatePrompt />
|
||||||
<EncryptionIntroBanner />
|
|
||||||
<AuthRequiredModal />
|
<AuthRequiredModal />
|
||||||
|
|
||||||
{#if needsRecoveryCode}
|
{#if needsRecoveryCode}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue