Classic theme after the 2004 Mac app; header and dialog buttons as icons

- A Classic theme beside Dark and Light: brushed-metal toolbar and
  status bar, a pale blue-grey source list, Aqua blue for whatever is
  selected, red unread badges, a striped table with blue titles, a blue
  bar behind the item's title, and Lucida Grande. The theme button steps
  through all three and remembers the choice.
- The feed and OPML headers' buttons (scan, download latest, mark all
  read, settings, unsubscribe) and the Settings, feed settings and
  Download latest dialogs' buttons (save, download, cancel) are icons,
  with the words in title and aria-label.
- Tests: the theme button reaches Classic and it survives a reload; the
  header buttons are found by action.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016HdTEWQNrzyFULijigkmMn
This commit is contained in:
2026-09-11 15:00:30 +00:00
parent 8a309eb652
commit ae47e31a97
3 changed files with 116 additions and 24 deletions

View File

@@ -29,6 +29,18 @@ test('the theme toggle actually changes the theme', async ({ page }) => {
.not.toBe(before);
});
test('the theme button steps through dark, light and classic, and remembers', async ({ page }) => {
const theme = () => page.evaluate(() => document.documentElement.dataset.theme);
for (let i = 0; i < 3 && (await theme()) !== 'classic'; i++) await page.locator('#theme').click();
expect(await theme()).toBe('classic');
await expect(page.locator('#theme')).toHaveAttribute('title', /Classic.*Click for Dark/);
await page.reload();
await expect.poll(theme).toBe('classic');
// The 2004 Mac app set its type in Lucida Grande.
expect(await page.evaluate(() => getComputedStyle(document.body).fontFamily)).toContain('Lucida Grande');
});
test('settings opens and saves the global schedule', async ({ page }) => {
await page.locator('#prefs').click();
await expect(page.locator('#modal.on')).toBeVisible();
@@ -136,7 +148,7 @@ test('the filter tabs change what is listed', async ({ page }) => {
test('a feed URL is editable and has a copy button', async ({ page }) => {
await page.getByText('Test Show').click();
await page.locator('.btn', { hasText: 'Settings' }).first().click();
await page.locator('#content .acts [data-a="settings"]').click();
await expect(page.locator('#surl')).toHaveValue(/show\.xml/);
await expect(page.locator('#scopy')).toBeVisible();
@@ -239,7 +251,7 @@ test('marking an OPML subscription read covers the feeds inside it', async ({ pa
await expect(folder.locator('.badge')).not.toHaveText('0');
await folder.click();
await page.locator('#content .acts button', { hasText: 'Mark all read' }).click();
await page.locator('#content .acts [data-a="read"]').click();
await expect(folder.locator('.badge')).toHaveText('0');
});