FILES: select-all checkbox in the list header (tri-state, accent) #366

Closed
opened 2026-09-28 17:28:44 +00:00 by kayg · 3 comments
Owner

Request (owner, 2026-09-28)

"can we add a checkbox here to select all files? tapping on it should select all files and of course the tap should use the accent colour?" The screenshot shows the Files list column header, left of "Name", above the first folder row.

Spec (Claude defaults; standard file-manager behaviour)

  • A select-all checkbox in the list header cell, aligned with the row checkboxes (same column, size, and optical centre on the "Name" cap height).
  • Three states: none selected (empty); some selected (indeterminate dash); all selected (checked). Clicking it when empty or indeterminate selects every item in the current folder, including rows the virtual list has not rendered yet (select by folder listing, not by DOM rows). Clicking it when all are selected clears the selection.
  • It enters selection mode (the selection bar appears with the count, #340), and the count updates.
  • Checked and indeterminate states and the press feedback use the accent colour role token, like the row checkboxes. No literal colours.
  • Accessibility: a real checkbox (aria-checked="mixed" for some), with the label "Select all N items in ". Keyboard: Space toggles it, and ⌘/Ctrl+A in the list does the same. Screen readers announce the new count.
  • Touch: at least a 44 px target; long-press behaviour stays as is.
  • The same header control goes in Recent and Trash lists (one shared component; reuse the row checkbox).
  • Deep link: none needed (a transient state).

Screenshots at 390/820/1440, light and dark, in each state; zoom crops of the header alignment.

## Request (owner, 2026-09-28) "can we add a checkbox here to select all files? tapping on it should select all files and of course the tap should use the accent colour?" The screenshot shows the Files list column header, left of "Name", above the first folder row. ## Spec (Claude defaults; standard file-manager behaviour) - A select-all checkbox in the list header cell, aligned with the row checkboxes (same column, size, and optical centre on the "Name" cap height). - Three states: none selected (empty); some selected (indeterminate dash); all selected (checked). Clicking it when empty or indeterminate selects **every item in the current folder**, including rows the virtual list has not rendered yet (select by folder listing, not by DOM rows). Clicking it when all are selected clears the selection. - It enters selection mode (the selection bar appears with the count, #340), and the count updates. - Checked and indeterminate states and the press feedback use the accent colour role token, like the row checkboxes. No literal colours. - Accessibility: a real checkbox (`aria-checked="mixed"` for some), with the label "Select all N items in <folder>". Keyboard: Space toggles it, and ⌘/Ctrl+A in the list does the same. Screen readers announce the new count. - Touch: at least a 44 px target; long-press behaviour stays as is. - The same header control goes in Recent and Trash lists (one shared component; reuse the row checkbox). - Deep link: none needed (a transient state). Screenshots at 390/820/1440, light and dark, in each state; zoom crops of the header alignment.
Author
Owner

Starting #366 on job/selection-pills, with dev already merged at base 3b300558692d17108cd8e9282a1f30601f96e70d. FileCollection virtualizes rendered rows but receives the full collection; I am adding the shared list-header checkbox and wiring its tri-state and keyboard behavior to the existing full-list selection state in Files, Recent and Trash.

Starting #366 on `job/selection-pills`, with `dev` already merged at base `3b300558692d17108cd8e9282a1f30601f96e70d`. `FileCollection` virtualizes rendered rows but receives the full collection; I am adding the shared list-header checkbox and wiring its tri-state and keyboard behavior to the existing full-list selection state in Files, Recent and Trash.
Author
Owner

Tri-state Files header evidence

Production browser captures from the local calternal server and production web build. Files, Recent, and Trash show none, mixed, and all selected at 390, 820, and 1440 CSS px in light and dark themes. Alignment crops focus on the header checkbox and Name label at 390 and 1440 CSS px.

Full header screenshots (54)

Header alignment crops (36)

# Tri-state Files header evidence Production browser captures from the local calternal server and production web build. Files, Recent, and Trash show none, mixed, and all selected at 390, 820, and 1440 CSS px in light and dark themes. Alignment crops focus on the header checkbox and Name label at 390 and 1440 CSS px. ## Full header screenshots (54) - [files-header-none-phone-light.png](https://git.kayg.org/attachments/c5735ed5-f861-4e44-9942-fdab83acf4cd) - [files-header-none-phone-dark.png](https://git.kayg.org/attachments/0f6e69af-1920-40d5-8af3-d1b5c03914ad) - [files-header-none-tablet-light.png](https://git.kayg.org/attachments/2e8ce5b2-2ca0-46c1-a498-1bf23f460c8e) - [files-header-none-tablet-dark.png](https://git.kayg.org/attachments/e4edd063-23bd-449e-a208-b3ab654627ab) - [files-header-none-desktop-light.png](https://git.kayg.org/attachments/0fc1b8b0-0154-4dfb-8afb-7713b40f3660) - [files-header-none-desktop-dark.png](https://git.kayg.org/attachments/e2871f67-d27c-4b06-8fe4-4ab84441eb32) - [files-header-some-phone-light.png](https://git.kayg.org/attachments/a0c05e7d-31a3-4fe7-838b-bf7a540d5acc) - [files-header-some-phone-dark.png](https://git.kayg.org/attachments/c2aed08b-372c-4a92-81cb-d937366dbeef) - [files-header-some-tablet-light.png](https://git.kayg.org/attachments/a46253ce-566b-4556-a667-b3a238fe90cd) - [files-header-some-tablet-dark.png](https://git.kayg.org/attachments/acbbdf33-9d45-432d-801c-9effe1d4358f) - [files-header-some-desktop-light.png](https://git.kayg.org/attachments/af25cb18-dba9-46cd-bd9d-1d701e5c04fa) - [files-header-some-desktop-dark.png](https://git.kayg.org/attachments/9ec2af83-dfcb-4204-a968-5d93db4dc512) - [files-header-all-phone-light.png](https://git.kayg.org/attachments/496892fb-63d8-4271-9591-09564708d8c1) - [files-header-all-phone-dark.png](https://git.kayg.org/attachments/833c8f45-b667-4637-8c64-045df5b5b0c3) - [files-header-all-tablet-light.png](https://git.kayg.org/attachments/abe8eaf7-49e5-401e-a93c-60c468d1a140) - [files-header-all-tablet-dark.png](https://git.kayg.org/attachments/4b3973bd-9802-4fd7-a17a-a23efc137f49) - [files-header-all-desktop-light.png](https://git.kayg.org/attachments/b09a04e1-0927-40a2-ad1a-4108ec4eb063) - [files-header-all-desktop-dark.png](https://git.kayg.org/attachments/353052cf-e67b-442b-8b20-283ea11d863a) - [recent-header-none-phone-light.png](https://git.kayg.org/attachments/0de65ed1-af32-43e9-88b5-af647fcb0391) - [recent-header-none-phone-dark.png](https://git.kayg.org/attachments/e428c58e-d356-4a98-9591-03cd42a1f7ae) - [recent-header-none-tablet-light.png](https://git.kayg.org/attachments/1edee497-5732-43ff-92be-cd0944c3b2c0) - [recent-header-none-tablet-dark.png](https://git.kayg.org/attachments/f0e454f2-38c8-44bc-b22d-09ad8266b04f) - [recent-header-none-desktop-light.png](https://git.kayg.org/attachments/e546ded1-bdfc-4863-8531-a332c26d7167) - [recent-header-none-desktop-dark.png](https://git.kayg.org/attachments/86e8f90c-ef34-427a-a003-5870087f42d8) - [recent-header-some-phone-light.png](https://git.kayg.org/attachments/fd574ba8-4566-44ca-a916-0eea1417e242) - [recent-header-some-phone-dark.png](https://git.kayg.org/attachments/20dae233-e6cf-48e3-b805-fa7194ffd4b4) - [recent-header-some-tablet-light.png](https://git.kayg.org/attachments/cce40a09-3492-4b17-96ff-14d534b7520b) - [recent-header-some-tablet-dark.png](https://git.kayg.org/attachments/84c6293c-4433-4740-97a3-7c38f628c820) - [recent-header-some-desktop-light.png](https://git.kayg.org/attachments/b98a9763-979c-48e3-9a03-89fa4592d109) - [recent-header-some-desktop-dark.png](https://git.kayg.org/attachments/4ab94aac-bd74-420f-a077-7a94cf70589c) - [recent-header-all-phone-light.png](https://git.kayg.org/attachments/21f96d3b-6f93-4adf-ac37-bc6b4d61c01b) - [recent-header-all-phone-dark.png](https://git.kayg.org/attachments/bf2abbfc-cd91-4685-89a4-29083af90150) - [recent-header-all-tablet-light.png](https://git.kayg.org/attachments/b20a93db-ddbb-4494-a32a-de186d5f82c6) - [recent-header-all-tablet-dark.png](https://git.kayg.org/attachments/171ea1ca-d8d4-4a7d-bda3-e0856daa7602) - [recent-header-all-desktop-light.png](https://git.kayg.org/attachments/d76bf791-55c8-4400-8be4-2897df98e25a) - [recent-header-all-desktop-dark.png](https://git.kayg.org/attachments/d3938f0e-0559-4def-98d8-2df82cd672cb) - [trash-header-none-phone-light.png](https://git.kayg.org/attachments/cab5e27c-6748-4ff2-b5e4-439a4e25f015) - [trash-header-none-phone-dark.png](https://git.kayg.org/attachments/581a94d1-a727-4d8a-9000-d0d4de246edf) - [trash-header-none-tablet-light.png](https://git.kayg.org/attachments/a3b68039-9487-4c09-9ec0-3fed256a4c1d) - [trash-header-none-tablet-dark.png](https://git.kayg.org/attachments/d6697aeb-01dc-4819-ba6c-85a1f05d2f37) - [trash-header-none-desktop-light.png](https://git.kayg.org/attachments/b105e590-41b5-4bad-965e-385c5d700b24) - [trash-header-none-desktop-dark.png](https://git.kayg.org/attachments/337d8bd5-9799-4c6b-b530-88b8874cdd18) - [trash-header-some-phone-light.png](https://git.kayg.org/attachments/8a50cc35-d570-4369-b9d9-827bb7893410) - [trash-header-some-phone-dark.png](https://git.kayg.org/attachments/30383259-1d17-42c0-998f-1a56e6e01ce6) - [trash-header-some-tablet-light.png](https://git.kayg.org/attachments/6e07854a-6b36-4426-ae29-2585c592eb5e) - [trash-header-some-tablet-dark.png](https://git.kayg.org/attachments/2cc5b4fe-8e52-4766-9c95-0fa9ca2236c6) - [trash-header-some-desktop-light.png](https://git.kayg.org/attachments/5f943b48-55f5-43c7-9f79-885cdefcab77) - [trash-header-some-desktop-dark.png](https://git.kayg.org/attachments/36e21781-e854-4520-ac58-e2232e39ce22) - [trash-header-all-phone-light.png](https://git.kayg.org/attachments/cd172cb0-6595-40af-b0e2-4f1321443de4) - [trash-header-all-phone-dark.png](https://git.kayg.org/attachments/ca828d1f-232f-47ea-854e-38e90b994e17) - [trash-header-all-tablet-light.png](https://git.kayg.org/attachments/b3e54caa-473d-4a1a-a080-5ab85163544a) - [trash-header-all-tablet-dark.png](https://git.kayg.org/attachments/8a0731b3-c021-4a84-9399-c389e7f3e441) - [trash-header-all-desktop-light.png](https://git.kayg.org/attachments/9934731a-5e13-46a8-9913-d29fd5a5377b) - [trash-header-all-desktop-dark.png](https://git.kayg.org/attachments/4514a507-6a66-4f47-b0eb-9711787edaa1) ## Header alignment crops (36) - [files-header-none-alignment-phone-light.png](https://git.kayg.org/attachments/724d816f-cbc7-4a52-a4d8-7192b64cf206) - [files-header-none-alignment-phone-dark.png](https://git.kayg.org/attachments/48d605d3-6e18-4587-8c06-214e975aef57) - [files-header-none-alignment-desktop-light.png](https://git.kayg.org/attachments/b0d85b84-bed2-4f3b-8c04-d7f6d6c845d2) - [files-header-none-alignment-desktop-dark.png](https://git.kayg.org/attachments/a1a89c7b-ba1e-4215-9207-a344071b168b) - [files-header-some-alignment-phone-light.png](https://git.kayg.org/attachments/634d3b7c-24c6-46a2-ae7a-421f1ffeef6b) - [files-header-some-alignment-phone-dark.png](https://git.kayg.org/attachments/aed31e83-4ba4-4104-b736-e650139bf30e) - [files-header-some-alignment-desktop-light.png](https://git.kayg.org/attachments/1f7e98e2-d50f-4865-8443-ba0ec7b574c0) - [files-header-some-alignment-desktop-dark.png](https://git.kayg.org/attachments/9535e67a-81d9-4e6f-b467-33b5df3e238a) - [files-header-all-alignment-phone-light.png](https://git.kayg.org/attachments/f8748c0e-e1f5-4acf-a504-1322ea302522) - [files-header-all-alignment-phone-dark.png](https://git.kayg.org/attachments/cf9dae51-14ee-489b-bc5d-9110c166e8ce) - [files-header-all-alignment-desktop-light.png](https://git.kayg.org/attachments/4ccea954-0ed0-4625-9794-b2687b1ff985) - [files-header-all-alignment-desktop-dark.png](https://git.kayg.org/attachments/e69db204-9f9a-4875-9bc5-5b4599ac676b) - [recent-header-none-alignment-phone-light.png](https://git.kayg.org/attachments/d34b0b97-4a3f-4bff-a575-601dd7f3fa33) - [recent-header-none-alignment-phone-dark.png](https://git.kayg.org/attachments/da748ccf-094d-4f6d-b043-6c78d98db1fa) - [recent-header-none-alignment-desktop-light.png](https://git.kayg.org/attachments/0cd375f4-04fd-45a6-b3d4-9aab337f1b7b) - [recent-header-none-alignment-desktop-dark.png](https://git.kayg.org/attachments/62385f2d-d52b-4605-b55b-20bbaf10a6c1) - [recent-header-some-alignment-phone-light.png](https://git.kayg.org/attachments/59f69366-2d47-4963-93b0-1560a2ca8d3e) - [recent-header-some-alignment-phone-dark.png](https://git.kayg.org/attachments/eb0d0c3c-c753-43da-868c-940d3f6b5cb1) - [recent-header-some-alignment-desktop-light.png](https://git.kayg.org/attachments/42ca10fd-c04a-45e4-ba18-a02c8a9d70bc) - [recent-header-some-alignment-desktop-dark.png](https://git.kayg.org/attachments/ec2467b9-a256-4075-bf87-e7dd14e632d1) - [recent-header-all-alignment-phone-light.png](https://git.kayg.org/attachments/17d433ca-4ab1-462e-ad9f-a2a27337bd77) - [recent-header-all-alignment-phone-dark.png](https://git.kayg.org/attachments/9c7a9c6a-cc7f-4f47-8760-298fbc5922fa) - [recent-header-all-alignment-desktop-light.png](https://git.kayg.org/attachments/584060c5-231a-4765-9247-adcc4025b55a) - [recent-header-all-alignment-desktop-dark.png](https://git.kayg.org/attachments/5c7807fa-91b1-41b2-b273-ce27d3dc34ad) - [trash-header-none-alignment-phone-light.png](https://git.kayg.org/attachments/287d5ba1-c72c-477d-9b0b-383404d5c42d) - [trash-header-none-alignment-phone-dark.png](https://git.kayg.org/attachments/cac1a7b7-d534-4df1-8e12-e386cabfdd72) - [trash-header-none-alignment-desktop-light.png](https://git.kayg.org/attachments/4b4e42ef-3644-4ca0-bf8e-c987ee6b1546) - [trash-header-none-alignment-desktop-dark.png](https://git.kayg.org/attachments/49315642-a532-4508-9ac1-e7f6f31300a1) - [trash-header-some-alignment-phone-light.png](https://git.kayg.org/attachments/12de3062-3052-4746-b613-b3f4edf793b4) - [trash-header-some-alignment-phone-dark.png](https://git.kayg.org/attachments/ffe62683-8c0d-4869-873b-e28db63a2791) - [trash-header-some-alignment-desktop-light.png](https://git.kayg.org/attachments/33d6cb82-791c-461c-b3c6-94e789e35a31) - [trash-header-some-alignment-desktop-dark.png](https://git.kayg.org/attachments/c7508789-6caa-4f0d-a8d0-425ed5225e15) - [trash-header-all-alignment-phone-light.png](https://git.kayg.org/attachments/aef1700b-c766-448f-aa11-06667e1b2f5d) - [trash-header-all-alignment-phone-dark.png](https://git.kayg.org/attachments/dbc2dfe0-34f2-437d-a80f-7a9eb1224282) - [trash-header-all-alignment-desktop-light.png](https://git.kayg.org/attachments/5d1852ed-5448-4680-b874-89f120eb1a11) - [trash-header-all-alignment-desktop-dark.png](https://git.kayg.org/attachments/0d975490-52c2-4f45-9a74-124dc3604bcf)
Author
Owner

Merged into dev by Claude after visual review (a9a16e90) and deployed to calternal.cloud. Closing.

Merged into dev by Claude after visual review (a9a16e90) and deployed to calternal.cloud. Closing.
kayg closed this issue 2026-09-28 22:31:14 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#366
No description provided.