Skip to content

web UI: style filters and favorites screens - #57

Merged
TSVRN9 merged 2 commits into
mainfrom
ux/filters-favorites
Aug 19, 2026
Merged

TSVRN9 merged 2 commits into
mainfrom
ux/filters-favorites

Conversation

@TSVRN9

@TSVRN9 TSVRN9 commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Closes #40

What changed

Restyled web/src/routes/filters/+page.svelte and web/src/routes/favorites/+page.svelte using only the landed component classes/tokens from web/src/app.css (.page-title, .section-title, .label-rule, .card, .empty-state, .btn/.btn-primary/.btn-ghost/.btn-sm, .badge) plus Tailwind utilities built from the existing @theme tokens. No app.css edits, no new colors.

  • Filters: page-title header, section-title'd "Avoid allergens"/"Require diet tags" sections, .empty-state for the no-data case, .btn-primary Save, .badge for the "Saved" status. Each allergen/diet-tag checkbox is wrapped in a chip-style <label> that fills maroon (bg-maroon-600 text-paper-50) when checked vs. an outlined border-ink-900/25 chip when not — the issue calls out that filters need "clear on/off states," so this is a real visual, not just decoration on the same 1px checkbox.
  • Favorites: page-title header, section-title'd "Dishes"/"Dining Halls", .card rows matching the treatment already established on / and /halls/[slug] (same list-row pattern), .empty-state for empty lists, .btn-ghost btn-sm Remove (per app.css's own stated intent: "low-stakes/destructive-lite").

Native checkbox/button roles and accessible names are unchanged: getByRole("checkbox", { name: "Milk" }), the favorite star's glyph-only text-content contract on the hall/home pages, and the Remove button's accessible name all still resolve exactly as before.

Both are device-only per CLAUDE.md's data-residency table — FoodPreferences in localStorage, Favorites in IndexedDB via IndexedDbFavoritesStorage. No Supabase calls added, no auth gate.

Red/green evidence (strict TDD)

Extended web/e2e/filters.spec.ts and web/e2e/favorites.spec.ts write-first with new assertions for the new visual behavior, using toHaveCSS (not class-name matching, so the test verifies an actual rendered difference, not a string in an attribute).

Red — ran PORT=4303 npx playwright test filters.spec.ts favorites.spec.ts against the unstyled pages, before any .svelte changes:

1) favorites.spec.ts › favoriting a dish ... Error: expect(received).not.toBe(expected)
   Expected: not "rgba(0, 0, 0, 0)"
   > 62 | 	expect(rowBg).not.toBe("rgba(0, 0, 0, 0)");

2) filters.spec.ts › setting an allergen filter ... Error: expect(locator).not.toHaveCSS(expected) failed
   Locator:  getByRole('checkbox', { name: 'Milk' }).locator('..')
   Expected: not "rgba(0, 0, 0, 0)"
   Received: "rgba(0, 0, 0, 0)"
   > 84 | 	await expect(milkLabel).not.toHaveCSS("background-color", milkBgBeforeCheck);

2 failed

Green — after restyling both pages, same command:

Running 2 tests using 2 workers
  2 passed (8.6s)

Verification

  • PORT=4303 npx playwright test (full suite, all 17 specs, including sibling-owned shell.spec.ts, halls-menu.spec.ts, rank.spec.ts, vertical-slice.spec.ts): 17 passed, confirming this restyle didn't regress shell.spec.ts's proveHydrated() (which also depends on the favorite star's text-content contract) or any concurrently-landing sibling work.
  • pnpm --filter web check: 0 errors, 0 warnings (396 files).
  • pnpm --filter web build (after cp web/.env.example web/.env): succeeds; only the expected pre-existing adapter-auto "could not detect a supported production environment" notice, not an error.
  • Eyeballed both routes live against the dev server (PORT=4303 vite dev, screenshotted via Playwright's own chromium since no system Chrome was available in this sandbox): confirmed the maroon page-title/label-rule header, chip-style checkboxes with a visibly filled checked state, and the dashed .empty-state panel on /favorites all render as intended.

Acceptance criteria (from #40)

  • Filters and favorites screens fully restyled using web UI: install Tailwind CSS + design tokens + styled shared layout #35's tokens
  • npx playwright test passes unchanged — extended, not modified in place; all pre-existing assertions (checkbox accessible names, Saved status text, star button text-content contract, Remove button name) still pass as written
  • pnpm --filter web check clean, CI passes (checked locally; CI to confirm)

Scope

Touched only: web/src/routes/filters/+page.svelte, web/src/routes/favorites/+page.svelte, web/e2e/filters.spec.ts, web/e2e/favorites.spec.ts. No app.css, no +layout.svelte, no other route dirs, no other e2e specs, no halls/ files.

Not merging — leaving for review per dispatch instructions.

Restyle /filters and /favorites with #35's design tokens: page-title +
label-rule headers, section-title for subsections, .card rows on favorites
(matching the halls/home list treatment), .empty-state for empty lists,
.btn-primary Save and .btn-ghost Remove, and chip-style checkboxes on
/filters that fill maroon when checked for a clear on/off state.

Extends filters.spec.ts and favorites.spec.ts (write-first, confirmed red
against the unstyled pages, green after) to assert the new visual behavior
directly via toHaveCSS rather than class names: a checked allergen chip's
background actually changes, favorite rows get a card surface distinct from
the page background, and the empty state renders with a dashed border.

Native checkbox/button roles and accessible names are unchanged, so the
existing assertions (getByRole("checkbox", { name: "Milk" }), the favorite
star's text-content contract, Remove's accessible name) keep passing as-is.
Filters and favorites remain device-only (localStorage/IndexedDB) — no
Supabase calls, no auth gate.
@TSVRN9
TSVRN9 merged commit c944b7a into main Aug 19, 2026
7 checks passed
@TSVRN9
TSVRN9 deleted the ux/filters-favorites branch August 19, 2026 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

web UI: style filters and favorites screens

1 participant