feat(design): the three 375 rows (E28 S3f3)

- Download row: answers to its own width (container query); below 40rem
  it stacks: picture beside a two-line title, the meta line across the
  row (one line, never wraps: zoomed on the iPad its pieces broke apart),
  then the source link and the actions on one wrapping line. The paste
  field takes a line of its own when the buttons would squeeze it.
- YT playlist row: below 42rem the length rides on the picture and the
  title runs two lines over the channel.
- Channels tag row: the suggestions take a line of their own below
  40rem (the chip lane was 0 px and the row's menu off the screen).
- Pager: on a phone the arrows drop their words (names kept), and the
  size label stays one line.
- Lint: a class split where the interpolation is the variant itself
  (${NARROW}:w-24) is refused too; it had shipped with no CSS.
This commit is contained in:
2026-09-27 04:15:08 +02:00
parent d510c8a534
commit a58a398427
11 changed files with 275 additions and 77 deletions
@@ -110,3 +110,28 @@ describe("Pager · the page box follows the page without an effect", () => {
expect(box).toHaveProperty("value", "3");
});
});
// E28 S3f3: on a phone the row ran 18px past a 375 screen. The arrows keep their names (a screen
// reader still hears Previous / Next) and only the visible words step aside below `sm`; the size label
// stays one line rather than a word per line.
describe("Pager · on a phone", () => {
it("hides only the visible words of Previous / Next, never their names", () => {
render(
<Pager
page={1}
size={10}
total={120}
pageSizeOptions={[10, 25]}
onPageChange={() => {}}
onSizeChange={() => {}}
sizeLabel="Rows per page"
/>,
);
for (const name of ["datatable.pager.prev", "datatable.pager.next"]) {
const btn = screen.getByRole("button", { name });
const word = [...btn.querySelectorAll("span")].find((s) => s.textContent === name)!;
expect(word.className.split(/\s+/)).toContain("max-sm:sr-only");
}
expect(screen.getByText("Rows per page").className).toContain("whitespace-nowrap");
});
});