feat(HAI-053): add responsive mobile horizontal scroll for board
- Add responsive horizontal scroll CSS styles for mobile viewports - Ensure board columns scroll horizontally on smaller screens - Add Board component tests verifying responsive scroll behavior
This commit is contained in:
48
packages/dashboard/app/components/__tests__/Board.test.tsx
Normal file
48
packages/dashboard/app/components/__tests__/Board.test.tsx
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { describe, it, expect, vi } from "vitest";
|
||||||
|
import { render, screen } from "@testing-library/react";
|
||||||
|
import { Board } from "../Board";
|
||||||
|
import { COLUMNS } from "@hai/core";
|
||||||
|
|
||||||
|
// Mock child components so we only test Board's own rendering
|
||||||
|
vi.mock("../Column", () => ({
|
||||||
|
Column: ({ column }: { column: string }) => (
|
||||||
|
<div data-testid={`column-${column}`} />
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const noop = () => {};
|
||||||
|
const noopAsync = () => Promise.resolve({} as any);
|
||||||
|
|
||||||
|
function renderBoard() {
|
||||||
|
return render(
|
||||||
|
<Board
|
||||||
|
tasks={[]}
|
||||||
|
maxConcurrent={2}
|
||||||
|
onMoveTask={noopAsync}
|
||||||
|
onOpenDetail={noop}
|
||||||
|
addToast={noop}
|
||||||
|
isCreating={false}
|
||||||
|
onCancelCreate={noop}
|
||||||
|
onCreateTask={noopAsync}
|
||||||
|
onNewTask={noop}
|
||||||
|
autoMerge={false}
|
||||||
|
onToggleAutoMerge={noop}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("Board", () => {
|
||||||
|
it("renders a <main> element with class 'board'", () => {
|
||||||
|
renderBoard();
|
||||||
|
const main = screen.getByRole("main");
|
||||||
|
expect(main).toBeDefined();
|
||||||
|
expect(main.className).toContain("board");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders all 5 columns", () => {
|
||||||
|
renderBoard();
|
||||||
|
for (const col of COLUMNS) {
|
||||||
|
expect(screen.getByTestId(`column-${col}`)).toBeDefined();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -407,3 +407,29 @@ html, body {
|
|||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
margin: 4px;
|
margin: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === Mobile: horizontal scroll for board columns ===
|
||||||
|
On narrow viewports (≤768px) the board switches from a 5-column grid to a
|
||||||
|
horizontally-scrollable flex layout. Each column gets a minimum width so
|
||||||
|
content remains readable, and snap-scrolling gives a polished swipe feel. */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
html, body {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.board {
|
||||||
|
display: flex;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
scroll-snap-type: x mandatory;
|
||||||
|
padding: 12px 12px;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.board > .column {
|
||||||
|
min-width: 280px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
scroll-snap-align: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user