refactor(webui): reuse sidebar selection highlight
This commit is contained in:
@@ -349,6 +349,22 @@ describe("App layout", () => {
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it("highlights the blank new-topic destination immediately", async () => {
|
||||
render(<App />);
|
||||
|
||||
await waitFor(() => expect(connectSpy).toHaveBeenCalled());
|
||||
const sidebar = screen.getByRole("navigation", { name: "Sidebar navigation" });
|
||||
const newTopicButton = within(sidebar).getByRole("button", { name: "New topic" });
|
||||
|
||||
expect(newTopicButton).toHaveAttribute("aria-current", "page");
|
||||
expect(newTopicButton).not.toHaveClass("bg-sidebar-accent");
|
||||
expect(newTopicButton).toHaveClass("transition-[width,padding,color]");
|
||||
expect(within(sidebar).getByTestId("actions-selection-highlight")).toHaveAttribute(
|
||||
"data-active-id",
|
||||
"new-chat",
|
||||
);
|
||||
});
|
||||
|
||||
it("restores the Settings route after a restart fallback hash", async () => {
|
||||
localStorage.setItem("nanobot-webui.restartStartedAt", String(Date.now()));
|
||||
localStorage.setItem("nanobot-webui.restartRoute", "#/settings?section=channels");
|
||||
@@ -2128,16 +2144,41 @@ describe("App layout", () => {
|
||||
expect(window.location.hash).toBe("#/settings");
|
||||
|
||||
const settingsNav = screen.getByRole("navigation", { name: "Settings sections" });
|
||||
fireEvent.click(within(settingsNav).getByRole("button", { name: "Models" }));
|
||||
const overviewButton = within(settingsNav).getByRole("button", {
|
||||
name: "Overview",
|
||||
exact: true,
|
||||
});
|
||||
const modelsButton = within(settingsNav).getByRole("button", {
|
||||
name: "Models",
|
||||
exact: true,
|
||||
});
|
||||
const settingsHighlight = within(settingsNav).getByTestId(
|
||||
"settings-selection-highlight",
|
||||
);
|
||||
|
||||
expect(overviewButton).toHaveAttribute("aria-current", "page");
|
||||
expect(overviewButton).not.toHaveClass("bg-sidebar-accent");
|
||||
expect(overviewButton).toHaveClass("transition-[color]");
|
||||
expect(settingsHighlight).toHaveAttribute("data-active-id", "overview");
|
||||
|
||||
fireEvent.click(modelsButton);
|
||||
|
||||
expect(await screen.findByText("Model presets")).toBeInTheDocument();
|
||||
expect(screen.queryByRole("heading", { name: "Models" })).not.toBeInTheDocument();
|
||||
expect(window.location.hash).toBe("#/settings?section=models");
|
||||
expect(modelsButton).toHaveAttribute("aria-current", "page");
|
||||
expect(settingsHighlight).toHaveAttribute("data-active-id", "models");
|
||||
|
||||
fireEvent.click(within(settingsNav).getByRole("button", { name: "Voice" }));
|
||||
const voiceButton = within(settingsNav).getByRole("button", {
|
||||
name: "Voice",
|
||||
exact: true,
|
||||
});
|
||||
fireEvent.click(voiceButton);
|
||||
|
||||
expect(await screen.findByRole("heading", { name: "Voice input" })).toBeInTheDocument();
|
||||
expect(window.location.hash).toBe("#/settings?section=voice");
|
||||
expect(voiceButton).toHaveAttribute("aria-current", "page");
|
||||
expect(settingsHighlight).toHaveAttribute("data-active-id", "voice");
|
||||
});
|
||||
|
||||
it("transitions between Apps and Skills without replacing the sidebar", async () => {
|
||||
@@ -2163,6 +2204,11 @@ describe("App layout", () => {
|
||||
"aria-current",
|
||||
"page",
|
||||
);
|
||||
expect(within(sidebar).getByTestId("actions-selection-highlight")).toHaveAttribute(
|
||||
"data-active-id",
|
||||
"utility:apps",
|
||||
);
|
||||
expect(within(sidebar).queryAllByRole("button", { current: "page" })).toHaveLength(1);
|
||||
expect(screen.getByTestId("settings-section-transition")).toHaveAttribute(
|
||||
"data-settings-section",
|
||||
"apps",
|
||||
@@ -2190,6 +2236,10 @@ describe("App layout", () => {
|
||||
"aria-current",
|
||||
"page",
|
||||
);
|
||||
expect(within(sidebar).getByTestId("actions-selection-highlight")).toHaveAttribute(
|
||||
"data-active-id",
|
||||
"utility:skills",
|
||||
);
|
||||
expect(document.title).toBe("Skills · nanobot");
|
||||
});
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ describe("ChatList", () => {
|
||||
expect(within(chatsSection).queryByText("Project chat")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("floats a borderless highlight in, then slides it between selected topics", () => {
|
||||
it("positions one background highlight, then slides it between selected topics", () => {
|
||||
let revealFrame: FrameRequestCallback | null = null;
|
||||
vi.spyOn(window, "requestAnimationFrame").mockImplementation((callback) => {
|
||||
revealFrame = callback;
|
||||
@@ -259,14 +259,15 @@ describe("ChatList", () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
const highlight = screen.getByTestId("active-chat-highlight");
|
||||
const surface = screen.getByTestId("active-chat-highlight-surface");
|
||||
expect(surface).toHaveClass(
|
||||
const highlight = screen.getByTestId("sessions-selection-highlight");
|
||||
expect(highlight).toHaveClass(
|
||||
"bg-sidebar-foreground/[0.055]",
|
||||
"transition-[opacity,transform]",
|
||||
"transition-[transform,width,height]",
|
||||
"motion-reduce:transition-none",
|
||||
);
|
||||
expect(surface).toHaveStyle("opacity: 0; transform: scale(0.97)");
|
||||
expect(highlight).toHaveStyle("opacity: 0");
|
||||
expect(screen.queryByTestId("sessions-selection-highlight-surface"))
|
||||
.not.toBeInTheDocument();
|
||||
|
||||
rerender(
|
||||
<ChatList
|
||||
@@ -277,6 +278,8 @@ describe("ChatList", () => {
|
||||
|
||||
const activeButton = screen.getByTitle("Active topic");
|
||||
expect(activeButton).toHaveAttribute("aria-current", "page");
|
||||
expect(activeButton.parentElement).toHaveClass("transition-[color]");
|
||||
expect(activeButton.parentElement).not.toHaveClass("transition-colors");
|
||||
expect(activeButton.parentElement).not.toHaveClass(
|
||||
"bg-sidebar-accent",
|
||||
"shadow-[inset_0_0_0_1px_hsl(var(--sidebar-border)/0.55)]",
|
||||
@@ -286,9 +289,8 @@ describe("ChatList", () => {
|
||||
"motion-reduce:transition-none",
|
||||
);
|
||||
expect(highlight).toHaveStyle(
|
||||
"width: 284px; height: 32px; transform: translate3d(8px, 12px, 0); transition-property: none",
|
||||
"width: 284px; height: 32px; transform: translate3d(8px, 12px, 0); opacity: 1; transition-property: none",
|
||||
);
|
||||
expect(surface).toHaveStyle("opacity: 1; transform: scale(1)");
|
||||
|
||||
revealFrame?.(0);
|
||||
expect(highlight.style.transitionProperty).toBe("");
|
||||
|
||||
Reference in New Issue
Block a user