From 8cf8c4139cf97d8f6c644bda1987bed031407164 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Sun, 1 Nov 2026 20:49:59 +0100 Subject: [PATCH] feat(playlists): select rows with a box, Shift for a range, x and Esc A box first in every row and one over the column for the rows shown, the selected row tinted. A filter keeps what it hides selected; another list starts over; a row that left the list drops out. Watch later has none. A box no longer counts as a typing target: a click on one left the focus there and the page's keys went dead. --- docs/DESIGN.md | 6 + frontend/src/components/ui/NativeControls.tsx | 24 ++- frontend/src/components/ui/NavGrid.tsx | 7 +- frontend/src/components/ui/README.md | 14 +- frontend/src/components/ui/RowSelectBox.tsx | 36 ++++ frontend/src/components/ui/tableHeader.tsx | 4 +- frontend/src/i18n/locales/en/keys.json | 6 +- frontend/src/i18n/locales/en/playlists.json | 2 + frontend/src/i18n/locales/hu/keys.json | 6 +- frontend/src/i18n/locales/hu/playlists.json | 2 + frontend/src/lib/keymap.test.ts | 23 +++ frontend/src/lib/keymap.ts | 22 ++- frontend/src/lib/listNav.select.dom.test.tsx | 136 +++++++++++++++ frontend/src/lib/listNav.ts | 34 ++++ frontend/src/lib/tableColumns.ts | 2 + frontend/src/lib/useRowSelection.dom.test.ts | 159 ++++++++++++++++++ frontend/src/lib/useRowSelection.ts | 75 +++++++++ .../modules/playlists/Playlists.dom.test.tsx | 97 ++++++++++- frontend/src/modules/playlists/Playlists.tsx | 43 ++++- .../src/modules/playlists/playlistColumns.tsx | 41 +++++ 20 files changed, 710 insertions(+), 29 deletions(-) create mode 100644 frontend/src/components/ui/RowSelectBox.tsx create mode 100644 frontend/src/lib/listNav.select.dom.test.tsx create mode 100644 frontend/src/lib/useRowSelection.dom.test.ts create mode 100644 frontend/src/lib/useRowSelection.ts diff --git a/docs/DESIGN.md b/docs/DESIGN.md index c173a62e..14e0cfb2 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -536,6 +536,11 @@ of a full-width panel and nothing on the right. shows them as four buttons with the item's place beside the selected view; a side panel in edit mode gives each group an Up / Down pair (`ui/OrderButtons`, `compact`). A move that would go nowhere is shown off, not hidden. A grip also picks up from the keyboard (space, the arrows, space). +- **Selecting rows:** a list whose rows take bulk actions shows a box first in every row, always, and one + over the column for the rows shown. Shift+click selects a range, `x` toggles the row under the keyboard, + Esc clears. A selected row wears the accent tint as well as its tick. An action covers the selected rows + shown; a row a filter hides stays selected and comes back ticked; another list starts over. The row's own + menu still acts on that row alone. - **Motion:** 150–300ms micro-interactions, transform/opacity only; `prefers-reduced-motion` is respected. [WCAG 2.3.3] @@ -834,3 +839,4 @@ of a full-width panel and nothing on the right. | 2026-11-01 | Channel header on a tablet (owner E2) | Below `xl` the action row drops its two words: "Prio" (the stepper's tooltip names it) and "Subscribed" (a ✓ glyph; its name in the aria-label, Unsubscribe in the tooltip); the tags keep the row's rest, folding into "+N" | The tag lane on a full line of its own below ~12rem; the tags under the channel name | On an iPad (820 px, 44 px targets) the lane got 29 px, a sliver; now 130 px, and every tag shows at 1180 | | 2026-11-01 | Clear watch progress (owner E a) | A video menu's Reset reads "Clear watch progress" in English (HU "Megtekintés visszaállítása" stays); "Reset view" is only a page's view reset (sort, filters, grouping) | "Reset view" for both; the playlist page's view reset renamed instead | On a playlist page the two stood one right-click apart under one name, and one of them erases the video's progress with no undo | | 2026-11-01 | Clear watch progress clears only that (owner A) | The row shows only on a video with a resume point and clears that alone: a hidden video stays hidden, a watched one watched. Un-hiding and un-watching have rows of their own | +| 2026-11-01 | Selecting a list's rows (owner D2 a) | An always visible box first in the row and one over the column for the rows shown; Shift+click a range, `x` the row under the keyboard, Esc clears; the selected row wears `accent/12` with its tick. Rows a filter hides stay selected, an action covers those shown; Watch later offers no selecting. | diff --git a/frontend/src/components/ui/NativeControls.tsx b/frontend/src/components/ui/NativeControls.tsx index bc2db63b..07e234c3 100644 --- a/frontend/src/components/ui/NativeControls.tsx +++ b/frontend/src/components/ui/NativeControls.tsx @@ -1,5 +1,5 @@ import clsx from "clsx"; -import type { InputHTMLAttributes, ReactNode, Ref } from "react"; +import type { InputHTMLAttributes, ReactNode, RefObject } from "react"; // A6 (docs/DESIGN.md): checkbox, slider and colour well are the BROWSER's controls, tinted // with the chosen colour (the accent; the media amber on the player chrome) — keyboard, screen @@ -10,18 +10,30 @@ import type { InputHTMLAttributes, ReactNode, Ref } from "react"; type Native = Omit, "type" | "onChange">; -/** The bare checkbox: inside your own `