Redesign project header and study navigation
Build and Push Docker Image / build-and-push (push) Failing after 20s

- Header: navigation buttons grouped; Study Guide, Podcast, and
  Pronunciation Guide move into a Tools menu (disabled until a chunk
  exists), set apart from Export and Share by a divider.
- Only one header dropdown is open at a time, and it closes on an
  outside click or Escape.
- Study page: drop the duplicate Prev/Next and counter at the top; the
  fixed bottom bar is the single chunk navigation and now shows a
  readable "Chunk N of M".
- Mobile empty-state hint points to Back to Chunks.
- Tests: Tools menu, one-dropdown-at-a-time, Escape/outside click.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Opus 5.5 committed 2026-09-22 15:37:29 -04:00
1 parent 33e3f2bdc6
commit 5287b471d0
3 files changed
+152 -111

No files matched your search

+32
View File
@@ -702,3 +702,35 @@ describe('Chunk builder', () => {
expect(await screen.findByRole('button', { name: 'Titus 2' })).toHaveClass('bg-slate-900');
});
});
// ---------------------------------------------------------------------------
// Header redesign: Tools menu + one-dropdown-at-a-time
// ---------------------------------------------------------------------------
describe('Header menus', () => {
test('Tools is disabled until a chunk exists, then opens the Pronunciation Guide', async () => {
const user = await loadChapter();
expect(screen.getByRole('button', { name: /tools/i })).toBeDisabled();
addChunk('Paul, a servant', 'Paul, a servant');
await screen.findByText('1 created');
await user.click(screen.getByRole('button', { name: /tools/i }));
await user.click(screen.getByRole('button', { name: /pronunciation guide/i }));
expect(await screen.findByRole('heading', { name: /pronunciation guide/i })).toBeInTheDocument();
});
test('opening one dropdown closes the other; Escape and outside clicks close it', async () => {
const user = await loadChapter();
await user.click(screen.getByRole('button', { name: /export/i }));
expect(screen.getByRole('button', { name: /export markdown/i })).toBeInTheDocument();
await user.click(screen.getByRole('button', { name: /share/i }));
expect(screen.queryByRole('button', { name: /export markdown/i })).not.toBeInTheDocument();
expect(screen.getByText(/read-only share link/i)).toBeInTheDocument();
await user.keyboard('{Escape}');
expect(screen.queryByText(/read-only share link/i)).not.toBeInTheDocument();
await user.click(screen.getByRole('button', { name: /export/i }));
await user.click(screen.getByText(/scripture & chunks/i));
expect(screen.queryByRole('button', { name: /export markdown/i })).not.toBeInTheDocument();
});
});