Table filters: emptying a header filter folds it shut around the box being typed in, and focus is lost #626
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#626
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo at
95348908d, reading the column header template, then typing into and clearing a header filter on Companies in headless Chromium.Checked again on 2026-10-01 against
mainat0a5cad587: still present.Each column filter is a
<details>that the server rendersopenonly while the column has a value (header.filtered). The text and number boxes arehx-preserve, so after the table swap htmx moves the old, focused box into the freshly rendered header. When the person has just emptied the box, that header is rendered closed, so the box they are typing in ends up inside a closed disclosure: it disappears, focus falls to the document body, and the next keystrokes go nowhere. Nothing inapp.jsreopens it.templates/cotton/table/head.html:110(<details class="col-filter" data-col-filter {% if header.filtered %}open{% endif %}>);core/tables.py:152-161(filteredisbool(self.value or self.value_from or self.value_to));templates/cotton/table/filter.html:37-40,:62and:71(hx-preserveon the live boxes). The choice and date controls are not preserved, so htmx tries to refocus their replacement by id, which sits inside the closed disclosure and cannot take focus.ac(the table narrows; the disclosure stays open because the column is now filtered), then delete both letters to try another word. 300 ms later the table swaps: the Name disclosure is closed, the box is no longer visible anddocument.activeElementis<body>(observed). Typingxnext changes nothing: the box is still empty and no request is sent. Choosing Any in a choice filter or clearing a date has the same result.openalso when the request is an htmx request whoseHX-Triggeris one of that header's input ids (header.input_id,-min,-max,-from,-to); scripts-off rendering is unchanged. Alternatively, inapp.js, note the open[data-col-filter]that containsdocument.activeElementonhtmx:beforeSwapand reopen it onhtmx:afterSwap, before htmx restores focus.Done when
tests/e2e/) opens a header filter, types a value, deletes it, and asserts that the disclosure is still open and the box still has focus; a second case does the same with Any in a choice filter.tests/test_tables.pyasserts that an htmx request triggered byfilter-namewith an empty value renders the Name disclosureopen.