Commit Graph
5 Commits
Author SHA1 Message Date
logan 6d0e46d537 fix(a11y): wire the combobox's roles to each other
Build & publish Arch package / arch-package (push) Successful in 2m5s
CI / check (push) Successful in 2m25s
Search index maintenance / maintain-index (push) Successful in 7s
CI / e2e (push) Successful in 5m19s
a11y.14: role=combobox, role=listbox and role=option were all present
and nothing connected them -- no ids, no aria-controls, no
aria-activedescendant -- so arrowing through nineteen options moved a
visual highlight and announced nothing.

Reproduced on the smart-playlist rule editor against the browser's own
computation rather than a snapshot: getFullAXTree reported no
activedescendant and no controls on any of the five comboboxes on the
page. After, the same node carries both.

aria-selected also meant 'highlighted', which is the one thing it does
not mean: a user arrowing past an option heard it announced as selected
while the value they had chosen was announced as unselected. It is the
chosen value now, and the highlight is what activedescendant points at.

The IDREF tests assert the link rather than the attribute -- an
activedescendant naming an id no element carries is exactly as silent as
no attribute, and reads as fixed.
2026-08-12 23:08:49 -04:00
yonlu ebaa856e0c fix: align combobox height to operator select via grid stretch
- Grid rows use align-items: stretch so all cells share the select's height
- Combobox host, wrapper, and input all set height: 100% to fill the cell
- Remove button uses align-self: center to stay centered instead of stretching
2026-03-21 13:46:26 -04:00
yonlu 288215a97c fix: match combobox input height to select dropdowns 2026-03-21 13:40:07 -04:00
yonlu 6972953649 fix: smart playlist UX polish — layout, defaults, free-form input, case-insensitive matching
Details view:
- Skip evaluation on new playlists (was returning all 25k tracks)
- Go straight to editor on auto-edit instead of awaiting loadTracks

Editor:
- Default sort to Random instead of None, remove None option
- Hide sort direction button when sort is Random
- Fixed-width field (160px) and operator (140px) columns, value fills remaining space
- Preview fills remaining vertical space (flex layout) instead of fixed 200px max-height
- Preview scrolls independently while rules/options stay pinned

Combobox:
- Accept free-form text on blur and Enter — no longer requires selection from dropdown
- Enables typing values like 'indie' that may not be exact DB entries

Backend:
- Case-insensitive text matching: COLLATE NOCASE on is/is_not/is_any_of operators
- Applies to both regular fields and genre subqueries
- LIKE operators were already case-insensitive (SQLite default)
2026-03-21 13:25:21 -04:00
yonlu 477b7ff6a2 feat(M002): smart playlists — rule engine, editor UI, sidebar integration
Recovered from orphaned worktree commits (complete-milestone failed to merge).

Backend:
- Migration 9: is_smart + smart_rules columns on playlists table
- smartplaylist package: parameterized WHERE clause builder, field whitelist, genre subquery
- playlist.Service: Create/Update/Evaluate/Preview/GetRules smart playlist methods
- 65 tests (49 rule engine + 15 service + 1 migration)

Frontend:
- yj-combobox: reusable typeable dropdown with keyboard nav, ARIA, blur-race fix
- smart-playlist-editor: row-based rule builder with live preview
- smart-playlist-details: evaluate, refresh, play, shuffle, edit rules
- Sidebar: filter icon, Smart badge, create button, routing
- Queue snapshot on play/shuffle
2026-03-21 12:53:00 -04:00