feat(design): the channel menu's Tags and Priority submenus (C1, E28 S3e3b)
Tags A-Z as in-place checks (the menu stays open for the next); Priority as the fixed steps 10 5 3 2 1 0, an off-scale current value ticked in its place. A pick re-sorts the list at once, moving only that row (placeByPriority, the server's order), and the table / card pager and the focus follow it (DataTable and useCardPager take a reveal seq, listNav.focusNavItem lands on the row's own "…", a virtualized card revealed first). ActionMenu rows take check: many | one. The menu reads the row fresh from the cache and keys its target by id.
This commit is contained in:
@@ -136,3 +136,27 @@ describe("DataTable · keyboardNav", () => {
|
||||
expect(document.activeElement).toBe(document.body);
|
||||
});
|
||||
});
|
||||
|
||||
describe("DataTable · reveal", () => {
|
||||
const many: Row[] = Array.from({ length: 25 }, (_, i) => ({ id: `r${i}` }));
|
||||
const cols: Column<Row>[] = [
|
||||
{ key: "name", header: "Name", cardPrimary: true, render: (r) => r.id },
|
||||
];
|
||||
const shown = () => [...document.querySelectorAll("tbody tr")].map((tr) => tr.textContent);
|
||||
|
||||
it("turns to the page that now holds a moved row on each new seq", () => {
|
||||
viewport(true);
|
||||
const view = (list: Row[], reveal: { key: string; seq: number } | null) => (
|
||||
<DataTable rows={list} columns={cols} rowKey={(r) => r.id} reveal={reveal} />
|
||||
);
|
||||
const { rerender } = render(view(many, { key: "r22", seq: 0 }));
|
||||
// The mount's seq is not a request: the first page stays.
|
||||
expect(shown()[0]).toBe("r0");
|
||||
rerender(view(many, { key: "r22", seq: 1 }));
|
||||
expect(shown()).toContain("r22");
|
||||
expect(shown()[0]).toBe("r20");
|
||||
// r22 bubbled up to the top: the next seq follows it back to page one.
|
||||
rerender(view([many[22]!, ...many.filter((r) => r.id !== "r22")], { key: "r22", seq: 2 }));
|
||||
expect(shown()[0]).toBe("r22");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user