diff --git a/docs/features/magic-notes/technical-design.md b/docs/features/magic-notes/technical-design.md index 1f0d26ea..e0c9cbfe 100644 --- a/docs/features/magic-notes/technical-design.md +++ b/docs/features/magic-notes/technical-design.md @@ -54,8 +54,10 @@ and 320px. It shares the AI pane's pointer-capture handlers, separator styling and keyboard semantics (16px arrow steps, Home/End limits). Both widths are stored in `goodbuddy.magic-notes-layout.v1`; missing index width defaults to 168px. Displayed widths clamp together to reserve at least 300px for the stream, -without overwriting saved widths when the window shrinks. The index toggle stays in the detail header immediately -before the title; collapsing hides the entire index and removes its grid column, +without overwriting saved widths when the window shrinks. The page header places +the index toggle immediately after the back button, followed by the AI toggle. +All three use icons and visible localized text; pane toggle labels reflect their +current show/hide action. Collapsing hides the entire index and removes its grid column, border, resize separator and occupied width. AI has a separate right pane with its existing resize separator and header toggle. Both panes scroll independently and persist independent desktop visibility. At container widths of diff --git a/src/renderer/src/MagicNotesWorkspace.test.tsx b/src/renderer/src/MagicNotesWorkspace.test.tsx index fab33df9..ea3eb256 100644 --- a/src/renderer/src/MagicNotesWorkspace.test.tsx +++ b/src/renderer/src/MagicNotesWorkspace.test.tsx @@ -824,10 +824,10 @@ describe('MagicNotesWorkspace detail behavior', () => { await openNote() showAi() const toggle = screen.getByRole('button', { name: '隐藏 AI 评论', expanded: true }) - expect(toggle).toHaveClass('icon-button', 'icon-button--active') + expect(toggle).toHaveClass('secondary-button') expect(toggle).toHaveAttribute('title', '隐藏 AI 评论') expect(toggle).toHaveAttribute('aria-controls', 'magic-notes-ai-pane') - expect(toggle.textContent).toBe('') + expect(toggle).toHaveTextContent('隐藏 AI 评论') const pane = screen.getByRole('complementary', { name: 'AI 评论' }) expect(pane).toHaveAttribute('id', toggle.getAttribute('aria-controls')) expect(within(pane).queryByText('AI 评论', { exact: true })).not.toBeInTheDocument() @@ -841,7 +841,7 @@ describe('MagicNotesWorkspace detail behavior', () => { expect(toggle).toHaveFocus() expect(screen.getByRole('button', { name: '显示 AI 评论', expanded: false })).toBe(toggle) expect(toggle).toHaveAttribute('title', '显示 AI 评论') - expect(toggle).not.toHaveClass('icon-button--active') + expect(toggle).toHaveTextContent('显示 AI 评论') expect(screen.queryByRole('complementary', { name: 'AI 评论' })).not.toBeInTheDocument() back() await openNote() @@ -956,7 +956,7 @@ describe('MagicNotesWorkspace detail behavior', () => { it('keeps entry editing contained and supports deletion confirmation', async () => { const { container } = render() await openNote() - expect(container.querySelector('.magic-note-detail-header button + input')).toBe(screen.getByLabelText('笔记标题')) + expect(container.querySelector('.magic-note-detail-header > :first-child')).toBe(screen.getByLabelText('笔记标题')) expect(screen.getByRole('button', { name: '删除记录' })).toHaveClass('danger-button--quiet') fireEvent.click(screen.getByRole('button', { name: '编辑' })) expect(container.querySelector('.magic-note-entry__editor')).toBeVisible() @@ -1187,8 +1187,14 @@ describe('MagicNotesWorkspace canvas integration', () => { fireEvent.click(screen.getByRole('button', { name: '编辑' })) const editor = screen.getByTestId('magic-note-editor') const toggle = screen.getByRole('button', { name: '收起记录索引' }) - expect(toggle.parentElement).toHaveClass('magic-note-detail-header') - expect(toggle.nextElementSibling).toBe(screen.getByLabelText('笔记标题')) + expect(toggle.parentElement).toHaveClass('page-header__actions') + const back = screen.getByRole('button', { name: '返回总览' }) + expect(back).toHaveTextContent('返回总览') + expect(back.nextElementSibling).toBe(toggle) + expect(toggle).toHaveTextContent('收起记录索引') + const aiToggle = screen.getByRole('button', { name: '隐藏 AI 评论' }) + expect(toggle.nextElementSibling).toBe(aiToggle) + expect(aiToggle).toHaveTextContent('隐藏 AI 评论') expect(toggle).toHaveAttribute('aria-controls', 'magic-notes-index') expect(toggle).toHaveAttribute('aria-expanded', 'true') toggle.focus() @@ -1196,23 +1202,26 @@ describe('MagicNotesWorkspace canvas integration', () => { expect(toggle).toHaveFocus() expect(toggle).toHaveAttribute('aria-expanded', 'false') expect(toggle).toHaveAttribute('title', '展开记录索引') + expect(toggle).toHaveTextContent('展开记录索引') expect(document.querySelector('.magic-notes-index-pane')).toHaveAttribute('hidden') expect(document.querySelector('.magic-notes-layout')).toHaveClass('magic-notes-layout--index-hidden') expect(screen.queryByRole('navigation', { name: '记录' })).not.toBeInTheDocument() expect(screen.getByRole('complementary', { name: 'AI 评论' })).toBeVisible() fireEvent.click(screen.getByRole('button', { name: '隐藏 AI 评论' })) + expect(aiToggle).toHaveTextContent('显示 AI 评论') fireEvent.click(screen.getByRole('button', { name: '展开记录索引' })) expect(screen.getByRole('navigation', { name: '记录' })).toBeVisible() expect(screen.queryByRole('complementary', { name: 'AI 评论' })).not.toBeInTheDocument() expect(screen.getByTestId('magic-note-editor')).toBe(editor) }) - it('opens and closes the narrow index from the detail header and returns Escape focus', async () => { + it('opens and closes the narrow index beside the back button and returns Escape focus', async () => { vi.spyOn(window, 'innerWidth', 'get').mockReturnValue(700) render() await openNote() const toggle = screen.getByRole('button', { name: '展开记录索引' }) - expect(toggle.nextElementSibling).toBe(screen.getByLabelText('笔记标题')) + expect(screen.getByRole('button', { name: '返回总览' }).nextElementSibling).toBe(toggle) + expect(toggle).toHaveTextContent('展开记录索引') expect(document.querySelector('.magic-notes-index-pane')).toHaveAttribute('hidden') fireEvent.click(toggle) expect(toggle).toHaveAttribute('aria-expanded', 'true') diff --git a/src/renderer/src/MagicNotesWorkspace.tsx b/src/renderer/src/MagicNotesWorkspace.tsx index 5a18b94a..7ae9c3df 100644 --- a/src/renderer/src/MagicNotesWorkspace.tsx +++ b/src/renderer/src/MagicNotesWorkspace.tsx @@ -1946,11 +1946,28 @@ export function MagicNotesWorkspace({ )} {detailView && ( + + )} + {detailView && ( )} {!detailView && ( @@ -2496,20 +2514,6 @@ export function MagicNotesWorkspace({ )}
-