From 243ac3fc90961c843e2ab32148c3b344f6149641 Mon Sep 17 00:00:00 2001 From: harikiran-lab <79027849+harikiran-lab@users.noreply.github.com> Date: Wed, 21 Oct 2026 00:22:17 -0500 Subject: [PATCH] Keep note controls visible and fix reminder overlay layers --- CHANGELOG.md | 6 + scripts/backdrop-click.test.js | 2 +- scripts/overlay-layer.test.js | 32 ++++ scripts/read-only.test.js | 5 +- scripts/toolbar-fit.test.js | 26 +++ src/App.svelte | 2 +- src/components/notes/NoteEditor.svelte | 225 ++++++++++++----------- src/components/notes/Popover.svelte | 6 +- src/components/notes/TipTapEditor.svelte | 8 +- src/components/ui/Sheet.svelte | 2 + src/components/ui/TimePicker.svelte | 2 + src/i18n/en.json | 4 + src/lib/overlay-layer.js | 24 +++ src/lib/toolbar-fit.js | 9 + src/routes/Shopping.svelte | 2 +- src/styles/base.css | 13 +- 16 files changed, 241 insertions(+), 127 deletions(-) create mode 100644 scripts/overlay-layer.test.js create mode 100644 scripts/toolbar-fit.test.js create mode 100644 src/lib/overlay-layer.js create mode 100644 src/lib/toolbar-fit.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ec9822..799d557 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +### Fixed + +- Keep Read Only note controls visible while disabling content changes, fit reader actions to the available width, and expose available actions in maximized desktop note windows. +- Open nested reminder calendars and time pickers above their parent form, and dismiss only the top overlay on Escape. +- Use consistent rounded page headers and the theme button foreground for banner contrast. + --- ## [1.2.0-dev01] - 2026-10-20 (pre-release) diff --git a/scripts/backdrop-click.test.js b/scripts/backdrop-click.test.js index fae5cf3..0b51a43 100644 --- a/scripts/backdrop-click.test.js +++ b/scripts/backdrop-click.test.js @@ -75,7 +75,7 @@ test('it follows the latest close action and lets go when removed', () => { test('the note editor and every popup close only on a deliberate backdrop click', () => { const editor = read('../src/components/notes/NoteEditor.svelte'); - assert.match(editor, /class="editor-backdrop" class:inline use:backdropClick=\{\(\) => \{ if \(!inline\) close\(\); \}\}/); + assert.match(editor, /class="editor-backdrop" class:inline[^\n]*use:backdropClick=\{\(\) => \{ if \(!inline\) close\(\); \}\}/); assert.doesNotMatch(editor, /class="editor-backdrop"[^\n]*on:click/); const pop = read('../src/components/notes/Popover.svelte'); assert.match(pop, /class="pop-backdrop" class:narrow use:backdropClick=\{closeOutside\} use:closeOnBack=\{close\}/); diff --git a/scripts/overlay-layer.test.js b/scripts/overlay-layer.test.js new file mode 100644 index 0000000..323b220 --- /dev/null +++ b/scripts/overlay-layer.test.js @@ -0,0 +1,32 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import { overlayLayer, isTopOverlay } from '../src/lib/overlay-layer.js'; + +globalThis.getComputedStyle = node => ({ zIndex: node.baseline }); +const node = baseline => ({ baseline, style: { zIndex: '' } }); + +test('a calendar with a lower CSS z-index opens above its reminder popover', () => { + const popover = node('300'), calendar = node('200'); + const parent = overlayLayer(popover), child = overlayLayer(calendar); + assert.ok(Number(calendar.style.zIndex) > Number(popover.style.zIndex)); + assert.equal(isTopOverlay(popover), false); + assert.equal(isTopOverlay(calendar), true); + child.destroy(); + assert.equal(isTopOverlay(popover), true); + assert.equal(calendar.style.zIndex, ''); + parent.destroy(); + assert.equal(isTopOverlay(popover), false); +}); +test('higher baseline layers and nested layers retain their ordering', () => { + const reminder = node('300'), time = node('9999'), child = node('200'); + const a = overlayLayer(reminder), b = overlayLayer(time), c = overlayLayer(child); + assert.equal(time.style.zIndex, '9999'); + assert.equal(child.style.zIndex, '10000'); + a.destroy(); // Account/navigation teardown can remove a parent first. + assert.equal(isTopOverlay(child), true); + c.destroy(); assert.equal(isTopOverlay(time), true); + b.destroy(); + const reopened = node('200'), d = overlayLayer(reopened); + assert.equal(reopened.style.zIndex, '200'); + d.destroy(); +}); diff --git a/scripts/read-only.test.js b/scripts/read-only.test.js index 29fff0e..7635dc2 100644 --- a/scripts/read-only.test.js +++ b/scripts/read-only.test.js @@ -269,7 +269,10 @@ test('the note opens for reading: content guarded, ticking and color kept, Edit // Turned on, what's typed is saved first. assert.match(ed, /if \(next\) await flushAll\(\);\s*readOnlyNote = next;/); assert.match(ed, /checkable=\{!baseLocked\}/); - assert.equal((ed.match(/\{#if !baseLocked( && !tightBar)?\}\s* - {#if isOwner} - - {/if} - {#if $sharingAvailable && !tightBar} - - {/if} - {#if !contentLocked && !tightBar} - - - - {#if canRecord} - - {/if} - {/if} - {#if !baseLocked && !tightBar} - - {/if} - {#if !tightBar} - - {/if} + {/each} + {#if readerOverflow.length} + {/if} {/if} + {#if !inline && !narrow} + + {/if}
@@ -1301,7 +1305,7 @@ on:open={openFile} on:remove={removeImage} /> {#key editorKey} {#if kind === 'text'} - formats = e.detail} slashActions={contentLocked ? [] : ['checklist', 'image', 'file', 'drawing', ...(canRecord ? ['voice'] : []), ...(isOwner ? ['reminder'] : [])]} on:slash={(e) => onSlash(e.detail)} @@ -1359,7 +1363,7 @@
{#if !inline || readOnly} -