refactor(webui): unify shared shape system

This commit is contained in:
Xubin Ren
2026-08-14 19:55:25 +09:00
parent 7c04af86f9
commit 60993597de
56 changed files with 305 additions and 219 deletions
+1 -1
View File
@@ -493,7 +493,7 @@ describe("ChatList", () => {
expect(tabSurface).toContainElement(paneList);
const activePane = within(tabGroup).getByRole("button", { name: "Research pane" });
expect(activePane).toHaveAttribute("aria-current", "true");
expect(activePane.closest("[data-sidebar-pane]")).toHaveClass("rounded-[0.65rem]");
expect(activePane.closest("[data-sidebar-pane]")).toHaveClass("rounded-control");
expect(activePane.querySelector("[data-sidebar-selection-track]"))
.toHaveAttribute("data-active", "true");
expect(screen.getByRole("button", {
+1 -1
View File
@@ -54,7 +54,7 @@ describe("CodeBlock", () => {
expect(screen.getByTestId("plain-code-fallback")).toHaveClass("py-4", "pl-5", "pr-14");
const container = screen.getByTestId("plain-code-fallback").closest(".not-prose");
expect(container).toHaveClass("relative", "rounded-[18px]", "bg-secondary/70");
expect(container).toHaveClass("relative", "rounded-floating", "bg-secondary/70");
expect(container).not.toHaveClass("border");
expect(container).toHaveAttribute("data-language", "ts");
+3 -3
View File
@@ -108,7 +108,7 @@ describe("MessageBubble", () => {
const pill = screen.getByText("hello");
expect(row).toHaveClass("ml-auto", "flex");
expect(pill).toHaveClass("ml-auto", "w-fit", "rounded-[18px]");
expect(pill).toHaveClass("ml-auto", "w-fit", "rounded-floating");
expect(screen.getByRole("button", { name: "Copy" })).toBeInTheDocument();
expect(screen.queryByRole("button", { name: "Fork" })).not.toBeInTheDocument();
});
@@ -286,7 +286,7 @@ describe("MessageBubble", () => {
expect(command.getAttribute("style")).toContain("var(--inline-token-highlight)");
expect(command.className).not.toMatch(/(?:^|\s)(?:bg-|border|ring|rounded)/);
expect(command.parentElement).toHaveTextContent("/model gpt-5");
expect(command.parentElement).toHaveClass("rounded-[18px]", "bg-secondary/70");
expect(command.parentElement).toHaveClass("rounded-floating", "bg-secondary/70");
});
it("keeps unknown and invalid slash commands as plain message text", () => {
@@ -934,7 +934,7 @@ describe("MessageBubble", () => {
const { container } = render(<MessageBubble message={message} />);
const imageButton = screen.getByRole("button", { name: /view image/i });
expect(imageButton).toHaveClass("w-[min(100%,34rem)]", "rounded-[20px]");
expect(imageButton).toHaveClass("w-[min(100%,34rem)]", "rounded-panel");
expect(imageButton).toHaveClass(
"border",
"border-border/60",
+1 -1
View File
@@ -165,7 +165,7 @@ describe("Settings models", () => {
expect(editor).toHaveClass(
"slide-in-from-top-1",
"lg:max-w-6xl",
"rounded-[18px]",
"rounded-floating",
);
expect(within(editor).getByDisplayValue("Primary")).toBeInTheDocument();
const deleteButton = within(editor).getByRole("button", { name: "Delete" });
+1 -1
View File
@@ -554,7 +554,7 @@ describe("ThreadComposer", () => {
expect(input.className).toContain("min-h-[50px]");
expect(input.className).toContain("text-[16px]");
expect(input.parentElement?.parentElement?.className).toContain("max-w-[49.5rem]");
expect(input.parentElement?.parentElement?.className).toContain("rounded-[22px]");
expect(input.parentElement?.parentElement?.className).toContain("rounded-panel");
expect(input.parentElement?.parentElement?.className).not.toContain("shadow-");
expect(screen.getByRole("button", { name: "Attach files" }).className).toContain("bg-card");
expect(screen.getByRole("button", { name: "Send message" }).className).toContain("bg-foreground");
+83
View File
@@ -0,0 +1,83 @@
import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import {
AlertDialog,
AlertDialogContent,
AlertDialogDescription,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogTitle,
} from "@/components/ui/dialog";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
describe("UI shape system", () => {
it("gives standard controls one shared radius", () => {
render(
<>
<Button>Continue</Button>
<Input aria-label="Name" />
<Textarea aria-label="Description" />
</>,
);
expect(screen.getByRole("button", { name: "Continue" })).toHaveClass("rounded-control");
expect(screen.getByRole("textbox", { name: "Name" })).toHaveClass("rounded-control");
expect(screen.getByRole("textbox", { name: "Description" })).toHaveClass(
"rounded-control",
);
});
it("gives dialogs and alert dialogs one shared modal radius", () => {
const dialog = render(
<Dialog open>
<DialogContent showCloseButton={false}>
<DialogTitle>Edit name</DialogTitle>
<DialogDescription>Choose a new name.</DialogDescription>
</DialogContent>
</Dialog>,
);
expect(screen.getByRole("dialog", { name: "Edit name" })).toHaveClass("rounded-modal");
dialog.unmount();
render(
<AlertDialog open>
<AlertDialogContent>
<AlertDialogTitle>Delete item?</AlertDialogTitle>
<AlertDialogDescription>This cannot be undone.</AlertDialogDescription>
</AlertDialogContent>
</AlertDialog>,
);
expect(screen.getByRole("alertdialog", { name: "Delete item?" })).toHaveClass(
"rounded-modal",
);
});
it("keeps floating surfaces and their items on the shared radius scale", () => {
render(
<DropdownMenu open>
<DropdownMenuTrigger>Open menu</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Rename</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>,
);
expect(screen.getByRole("menu")).toHaveClass("rounded-floating");
expect(screen.getByRole("menuitem", { name: "Rename" })).toHaveClass(
"rounded-control",
);
});
});