mirror of
https://github.com/multica-ai/multica.git
synced 2026-08-02 01:45:52 +02:00
fix(issues): anchor full-width table rows
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -3,7 +3,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { renderWithI18n } from "../../test/i18n";
|
||||
import { QuickCreateFooter } from "./table-view";
|
||||
import { IssueTableGroupRow, QuickCreateFooter } from "./table-view";
|
||||
|
||||
const { createIssue } = vi.hoisted(() => ({
|
||||
createIssue: vi.fn(),
|
||||
@@ -38,6 +38,7 @@ describe("QuickCreateFooter", () => {
|
||||
|
||||
const input = screen.getByPlaceholderText("Add an issue…");
|
||||
const submit = screen.getByRole("button", { name: "Add" });
|
||||
expect(input.closest("form")).toHaveClass("sticky", "left-1.5");
|
||||
expect(submit).toBeDisabled();
|
||||
|
||||
await user.type(input, " Clickable quick create ");
|
||||
@@ -56,4 +57,32 @@ describe("QuickCreateFooter", () => {
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps full-width row controls anchored during horizontal scrolling", async () => {
|
||||
const user = userEvent.setup();
|
||||
const onToggle = vi.fn();
|
||||
renderWithI18n(
|
||||
<table>
|
||||
<tbody>
|
||||
<IssueTableGroupRow
|
||||
group={{
|
||||
kind: "group",
|
||||
key: "status:backlog",
|
||||
label: "Backlog",
|
||||
count: 13,
|
||||
collapsed: false,
|
||||
}}
|
||||
colSpan={3}
|
||||
onToggle={onToggle}
|
||||
/>
|
||||
</tbody>
|
||||
</table>,
|
||||
);
|
||||
|
||||
const group = screen.getByRole("button", { name: /Backlog\s*13/ });
|
||||
expect(group).toHaveClass("sticky", "left-4", "w-fit");
|
||||
|
||||
await user.click(group);
|
||||
expect(onToggle).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -572,7 +572,7 @@ export function QuickCreateFooter({
|
||||
<TableRow className="hover:bg-muted/30">
|
||||
<TableCell colSpan={colSpan} className="p-1.5">
|
||||
<form
|
||||
className="flex max-w-2xl items-center gap-2"
|
||||
className="sticky left-1.5 flex max-w-2xl items-center gap-2"
|
||||
onSubmit={(event) => {
|
||||
event.preventDefault();
|
||||
submit();
|
||||
@@ -607,6 +607,42 @@ export function QuickCreateFooter({
|
||||
);
|
||||
}
|
||||
|
||||
type IssueTableGroupRowProps = {
|
||||
group: Extract<IssueTableDisplayRow, { kind: "group" }>;
|
||||
colSpan: number;
|
||||
onToggle: () => void;
|
||||
};
|
||||
|
||||
export function IssueTableGroupRow({
|
||||
group,
|
||||
colSpan,
|
||||
onToggle,
|
||||
}: IssueTableGroupRowProps) {
|
||||
return (
|
||||
<TableRow
|
||||
className="bg-muted/40 hover:bg-muted/60"
|
||||
onClick={onToggle}
|
||||
>
|
||||
<TableCell colSpan={colSpan} className="h-9 px-4 py-1.5">
|
||||
<button
|
||||
type="button"
|
||||
className="sticky left-4 flex w-fit items-center gap-2 text-xs font-medium"
|
||||
>
|
||||
{group.collapsed ? (
|
||||
<ChevronRight className="size-3.5" />
|
||||
) : (
|
||||
<ChevronDown className="size-3.5" />
|
||||
)}
|
||||
{group.label}
|
||||
<span className="font-normal tabular-nums text-muted-foreground">
|
||||
{group.count}
|
||||
</span>
|
||||
</button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
|
||||
function propertyDisplayValue(
|
||||
property: IssueProperty,
|
||||
value: IssuePropertyValue | undefined,
|
||||
@@ -1115,7 +1151,10 @@ export function TableView({
|
||||
return (
|
||||
<TableCell
|
||||
key={column.id}
|
||||
className="overflow-hidden px-4 py-1.5 text-xs text-muted-foreground"
|
||||
className={cn(
|
||||
"overflow-hidden px-4 py-1.5 text-xs text-muted-foreground",
|
||||
column.getIsPinned() && "bg-background",
|
||||
)}
|
||||
style={getCellStyle(column, { withBorder: true, hasExplicitSize: true })}
|
||||
>
|
||||
{key === "title"
|
||||
@@ -1286,30 +1325,11 @@ export function TableView({
|
||||
renderRow={(row) => {
|
||||
if (row.original.kind !== "group") return null;
|
||||
return (
|
||||
<TableRow
|
||||
className="bg-muted/40 hover:bg-muted/60"
|
||||
onClick={() => toggleTableGroupCollapsed(row.original.key)}
|
||||
>
|
||||
<TableCell
|
||||
colSpan={table.getVisibleLeafColumns().length}
|
||||
className="h-9 px-4 py-1.5"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center gap-2 text-xs font-medium"
|
||||
>
|
||||
{row.original.collapsed ? (
|
||||
<ChevronRight className="size-3.5" />
|
||||
) : (
|
||||
<ChevronDown className="size-3.5" />
|
||||
)}
|
||||
{row.original.label}
|
||||
<span className="font-normal tabular-nums text-muted-foreground">
|
||||
{row.original.count}
|
||||
</span>
|
||||
</button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<IssueTableGroupRow
|
||||
group={row.original}
|
||||
colSpan={table.getVisibleLeafColumns().length}
|
||||
onToggle={() => toggleTableGroupCollapsed(row.original.key)}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
className="min-h-0 flex-1"
|
||||
|
||||
Reference in New Issue
Block a user