fix: keep the notes list accessible in narrow workspaces

Default the notes list to 200px with a 160px minimum and hide it automatically only below 600px. Keep the detail toolbar toggle available to open a drawer, with dismissal and note-switching support. Restore reading positions after rich text content effects populate the record.

Include the existing document-table and file-tree scroll anchoring styles in this file-level commit. Validation: 143 related tests, Electron layout regression, typecheck and changed-file lint passed; repository lint is blocked by unrelated App.tsx changes.

Release note: The notes list takes less space and remains accessible through a drawer in narrow windows. Existing saved list widths are preserved.
This commit is contained in:
mesalogo
2026-10-03 16:02:27 +08:00
parent 10065da8ac
commit a620c22676
6 changed files with 169 additions and 34 deletions
+28 -8
View File
@@ -94,7 +94,7 @@ it('resizes record columns with native Electron input and preserves desktop widt
const toolbarBox = await rect('.magic-note-detail-toolbar'), streamBox = await rect('.magic-notes-stream-pane');
const streamClient = await js('document.querySelector(".magic-notes-stream-pane").clientWidth');
assert(Math.abs(toolbarBox.x - streamBox.x) <= 1 && Math.abs(toolbarBox.width - streamClient) <= 1, 'Toolbar spans the stream: ' + JSON.stringify({ toolbarBox, streamBox, streamClient }));
assert.equal((await rect('.magic-notes-overview')).width, 280);
assert.equal((await rect('.magic-notes-overview')).width, 200);
assert(await js('document.querySelector(".magic-notes-overview").checkVisibility()'));
await js('document.querySelector(".magic-notes-card-grid").scrollTop = 300; document.querySelector(".magic-notes-stream-pane").scrollTop = 420');
await wait('document.querySelector(".magic-notes-stream-pane").scrollTop === 420');
@@ -108,7 +108,7 @@ it('resizes record columns with native Electron input and preserves desktop widt
assert.equal(await js('document.querySelector("#magic-note-select-layout-note").getAttribute("aria-current")'), 'true');
await drag('.magic-notes-notes-resize-handle', 40);
const notesWidth = (await rect('.magic-notes-overview')).width;
assert(notesWidth >= 320 && notesWidth <= 325);
assert(notesWidth >= 240 && notesWidth <= 245);
await key('.magic-notes-notes-resize-handle', 'Left');
assert.equal((await rect('.magic-notes-overview')).width, notesWidth - 16);
await click('button[aria-controls="magic-library-panel-notes"]');
@@ -117,7 +117,7 @@ it('resizes record columns with native Electron input and preserves desktop widt
assert.equal((await rect('.magic-notes-overview')).width, notesWidth - 16);
assert.equal(await js('document.querySelector(".magic-notes-card-grid").scrollTop'), 300);
await key('.magic-notes-notes-resize-handle', 'Home');
assert.equal((await rect('.magic-notes-overview')).width, 240);
assert.equal((await rect('.magic-notes-overview')).width, 160);
await js('document.querySelector(".magic-notes-stream-pane").scrollTop = 0');
const editor = '.magic-note-composer .magic-note-editor__content .ql-editor';
const saveButton = '.magic-note-composer > footer > .primary-button';
@@ -184,10 +184,10 @@ it('resizes record columns with native Electron input and preserves desktop widt
const withoutAi = (await rect(index)).width; assert(withoutAi < 250 && withoutAi > 230);
await click('button[aria-controls="magic-notes-ai-pane"]'); assert.equal((await rect(index)).width, withoutAi);
await win.loadURL(${JSON.stringify(server.resolvedUrls!.local[0] + 'layout.html')}); await open(); assert.equal((await rect(index)).width, withoutAi);
assert.equal((await rect('.magic-notes-overview')).width, 240);
assert.equal((await rect('.magic-notes-overview')).width, 160);
await js('document.querySelector(".magic-notes-card-grid").scrollTop = 300');
win.setContentSize(1000, 720); await settle(); await settle();
assert.equal((await rect('.magic-notes-overview')).width, 240);
win.setContentSize(960, 720); await settle(); await settle();
assert.equal((await rect('.magic-notes-overview')).width, 160);
assert.equal((await rect(index)).width, 0, 'Record drawer follows detail width, not the outer page');
const assertSideBySide = async () => {
const s = await rect(stream), ai = await rect('.magic-notes-ai-pane'), list = await rect('.magic-notes-overview');
@@ -198,12 +198,14 @@ it('resizes record columns with native Electron input and preserves desktop widt
await assertSideBySide();
win.setContentSize(930, 720); await settle(); await settle();
await assertSideBySide();
win.setContentSize(1000, 720); await settle(); await settle();
win.setContentSize(960, 720); await settle(); await settle();
assert(await js('document.documentElement.scrollWidth <= innerWidth'));
win.setContentSize(820, 720); await settle(); await settle();
assert((await rect(stream)).width >= 299);
const constrained = { index: (await rect(index)).width, editor: (await rect(stream)).width, ai: (await rect('.magic-notes-ai-pane')).width };
win.setContentSize(720, 640); await settle(); await settle();
assert.equal((await rect('.magic-notes-overview')).width, 160);
await click('#magic-notes-list-toggle');
assert.equal((await rect('.magic-notes-overview')).width, 0);
await click('#magic-notes-back');
assert(await js('document.querySelector(".magic-notes-overview").checkVisibility()'));
@@ -224,10 +226,28 @@ it('resizes record columns with native Electron input and preserves desktop widt
assert(Math.abs(narrowFooter.x + narrowFooter.width - footerPaddingRight - narrowSave.x - narrowSave.width) <= 1, 'Narrow Save button stays right-aligned within footer padding');
await screenshot('magic-notes-narrow');
win.setContentSize(560, 640); await settle(); await settle();
assert(await js('document.querySelector("#magic-notes-list-toggle").checkVisibility()'));
const detailBeforeDrawer = await rect('.magic-notes-detail-container');
await click('#magic-notes-list-toggle');
assert(await js('document.querySelector(".magic-notes-workspace--drawer") !== null'));
assert.equal((await rect('.magic-notes-overview')).width, 160);
assert.deepEqual(await rect('.magic-notes-detail-container'), detailBeforeDrawer);
assert(await js('document.querySelector(".magic-notes-overview").scrollWidth <= document.querySelector(".magic-notes-overview").clientWidth'));
await key('#magic-library-panel-notes input', 'Escape');
assert.equal((await rect('.magic-notes-overview')).width, 0);
assert(await js('document.activeElement.id === "magic-notes-list-toggle"'));
await click('#magic-notes-list-toggle');
await click('#magic-note-select-other-note-3');
await wait('document.querySelector(".magic-note-detail-title").value === "Other note 3"');
assert.equal((await rect('.magic-notes-overview')).width, 0);
await click('#magic-notes-list-toggle');
await click('#magic-note-select-layout-note');
await wait('document.querySelector(".magic-note-detail-title").value === "Layout note"');
assert((await rect('.magic-notes-ai-pane')).y >= (await rect(stream)).y + (await rect(stream)).height, 'AI pane stacks below the stream on very narrow widths');
assert.equal(await js('getComputedStyle(document.querySelector(".magic-notes-ai-resize-handle")).display'), 'none');
win.setContentSize(1280, 800); await settle(); await settle();
assert.equal((await rect('.magic-notes-overview')).width, 240);
await click('#magic-notes-list-toggle');
assert.equal((await rect('.magic-notes-overview')).width, 160);
assert.equal((await rect(index)).width, withoutAi);
await key('.magic-note-record', 'Tab');
await js('document.querySelector(".magic-note-record").focus()');