memos/web/tests/sidebar-row-grammar.test.tsx
boojack d722608947 fix(sidebar): stop the month calendar growing with the rail
Calendar cells were `aspect-square w-full`, so cell height was a pure
function of rail width. Dragging the rail from 224px to its 400px max
took the calendar block from 231px to 382px — a 65% jump that pushed
Views and Tags out of view, left a 12px numeral floating in a 50px box,
and turned the selected day into a 50x50 slab against a rail whose every
other row is 30px.

Split the cell in two: the button spans its whole column and takes the
pointer, while a chip inside it carries the fill, the ring and the today
dot, and stops growing at `maxSize`. A chip is therefore
`min(column, 30px)` — narrow rails are untouched (224px still yields
25px cells, 170px of grid) and wider ones spend the surplus on hit area
instead of height, holding the grid at 200px from 258px up.

The today dot stops detaching as a side effect: it is positioned against
a chip that no longer grows, rather than against a cell floor that
drifted 19px below the numeral at full width.
2026-08-06 22:59:21 +08:00

53 lines
1.6 KiB
TypeScript

import { render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import SidebarRow, { SIDEBAR_ROW_BOX_CLASSES } from "@/components/AppSidebar/SidebarRow";
import TagTree from "@/components/TagTree";
vi.mock("@/utils/i18n", () => ({ useTranslate: () => (key: string) => key }));
/**
* Tag rows drifted off the rail's row grammar once already (they were 26px/12px against
* everything else's 30px/13px). These lock the shared box: the sizes must come from
* `SIDEBAR_ROW_BOX_CLASSES`, not from values copied into each list.
*/
const boxClasses = SIDEBAR_ROW_BOX_CLASSES.split(" ");
describe("sidebar row grammar", () => {
it("gives a nav row the shared row box", () => {
render(<SidebarRow icon={() => null} label="Tasks" />);
expect(screen.getByRole("button", { name: "Tasks" })).toHaveClass(...boxClasses);
});
it("gives tag tree rows the same box as a nav row", () => {
render(
<TagTree
tagAmounts={[
["a", 2],
["a/b", 1],
]}
onTagClick={vi.fn()}
/>,
);
for (const item of screen.getAllByRole("treeitem")) {
expect(item).toHaveClass(...boxClasses);
}
});
it("indents nested tags by the same step the memo outline uses", () => {
render(
<TagTree
tagAmounts={[
["a", 2],
["a/b", 1],
]}
onTagClick={vi.fn()}
/>,
);
const [root, child] = screen.getAllByRole("treeitem");
expect(root).toHaveStyle({ paddingInlineStart: "8px" });
expect(child).toHaveStyle({ paddingInlineStart: "20px" });
});
});