diff --git a/packages/ui/src/components/mdx-content/mdx-content.test.tsx b/packages/ui/src/components/mdx-content/mdx-content.test.tsx
new file mode 100644
index 00000000..1f8f20b6
--- /dev/null
+++ b/packages/ui/src/components/mdx-content/mdx-content.test.tsx
@@ -0,0 +1,68 @@
+import { render, screen } from "@testing-library/react";
+import type React from "react";
+import { afterEach, describe, expect, it, vi } from "vitest";
+
+import { MDXContent } from "./mdx-content";
+
+function Note({ children }: { children: React.ReactNode }) {
+ return ;
+}
+
+describe("MDXContent", () => {
+ afterEach(() => {
+ vi.restoreAllMocks();
+ });
+
+ it("renders markdown headings, links, and list items", async () => {
+ const node = await MDXContent({
+ content:
+ "## Getting started\n\nRead the [docs](https://example.com).\n\n- Install\n- Ship",
+ });
+
+ render(node);
+
+ expect(
+ screen.getByRole("heading", { name: "Getting started" }),
+ ).toBeInTheDocument();
+ expect(screen.getByRole("link", { name: "docs" })).toHaveAttribute(
+ "href",
+ "https://example.com",
+ );
+ expect(screen.getByText("Install")).toBeInTheDocument();
+ expect(screen.getByText("Ship")).toBeInTheDocument();
+ });
+
+ it("strips injected component imports before rendering MDX", async () => {
+ const node = await MDXContent({
+ components: { Note },
+ content:
+ 'import { Note } from "./note";\n\nImported component content',
+ });
+
+ render(node);
+
+ expect(screen.getByText("Imported component content")).toBeInTheDocument();
+ expect(document.body).not.toHaveTextContent(
+ 'import { Note } from "./note"',
+ );
+ });
+
+ it("falls back to markdown when MDX evaluation fails", async () => {
+ const consoleError = vi
+ .spyOn(console, "error")
+ .mockImplementation(() => null);
+ const node = await MDXContent({
+ content: "## Fallback content\n\n> = {},
+) {
+ const props = {
+ models,
+ onOpenChange: vi.fn(),
+ onSelectModel: vi.fn(),
+ open: true,
+ selectedModelId: "google/gemini-1.5-pro",
+ ...overrides,
+ };
+
+ render();
+
+ return props;
+}
+
+describe("ModelSelector", () => {
+ it("renders the open dialog with selected model promoted and disabled", () => {
+ renderModelSelector();
+
+ expect(screen.getByText("Select Model")).toBeInTheDocument();
+ expect(screen.getByText("Selected")).toBeInTheDocument();
+ expect(getModelItem("Gemini 1.5 Pro")).toHaveAttribute(
+ "aria-disabled",
+ "true",
+ );
+ expect(screen.getByText("In: $2.50/1M")).toBeInTheDocument();
+ expect(screen.getByText("Out: $10.00/1M")).toBeInTheDocument();
+ });
+
+ it("filters models by search text across provider metadata", () => {
+ renderModelSelector();
+
+ fireEvent.change(
+ screen.getByPlaceholderText("Search models or providers..."),
+ {
+ target: { value: "anthropic" },
+ },
+ );
+
+ expect(screen.getByText("Claude 3.5 Sonnet")).toBeInTheDocument();
+ expect(screen.queryByText("GPT-4o")).not.toBeInTheDocument();
+ expect(screen.queryByText("Gemini 1.5 Pro")).not.toBeInTheDocument();
+ });
+
+ it("selects a non-current model and closes the dialog", () => {
+ const onOpenChange = vi.fn();
+ const onSelectModel = vi.fn();
+ renderModelSelector({ onOpenChange, onSelectModel });
+
+ fireEvent.click(getModelItem("Claude 3.5 Sonnet"));
+
+ expect(onSelectModel).toHaveBeenCalledWith("anthropic/claude-3-5-sonnet");
+ expect(onOpenChange).toHaveBeenCalledWith(false);
+ });
+});
diff --git a/packages/ui/src/components/slideshow/slideshow.test.tsx b/packages/ui/src/components/slideshow/slideshow.test.tsx
new file mode 100644
index 00000000..2db5d6e2
--- /dev/null
+++ b/packages/ui/src/components/slideshow/slideshow.test.tsx
@@ -0,0 +1,104 @@
+import { act, fireEvent, render, screen } from "@testing-library/react";
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
+
+import { Slideshow, type SlideshowProps } from "./slideshow";
+
+const sections = [
+ { id: "intro", title: "Intro" },
+ { id: "setup", title: "Setup" },
+ { id: "finish", title: "Finish" },
+];
+
+function renderSlideshow(overrides: Partial = {}) {
+ const props = {
+ completedSections: new Set(),
+ currentIndex: 0,
+ onComplete: vi.fn(),
+ onExit: vi.fn(),
+ onNavigate: vi.fn(),
+ onToggleSection: vi.fn(),
+ renderContent: (section: { title: string }) => (
+ {section.title} body
+ ),
+ sections,
+ title: "Tutorial",
+ ...overrides,
+ };
+
+ const view = render();
+
+ return { props, view };
+}
+
+function advanceNavigationTimer() {
+ act(() => {
+ vi.advanceTimersByTime(150);
+ });
+}
+
+describe("Slideshow", () => {
+ beforeEach(() => {
+ vi.useFakeTimers();
+ });
+
+ afterEach(() => {
+ vi.useRealTimers();
+ document.body.style.overflow = "";
+ });
+
+ it("renders in a portal and restores body scroll lock on cleanup", () => {
+ const { view } = renderSlideshow();
+
+ expect(screen.getByText("Tutorial")).toBeInTheDocument();
+ expect(screen.getByText("Intro body")).toBeInTheDocument();
+ expect(document.body.style.overflow).toBe("hidden");
+
+ view.unmount();
+
+ expect(document.body.style.overflow).toBe("");
+ });
+
+ it("opens the completion dialog before navigating an incomplete section", () => {
+ const { props } = renderSlideshow();
+
+ fireEvent.click(screen.getByRole("button", { name: /next/i }));
+
+ expect(
+ screen.getByRole("dialog", { name: "Mark section as complete?" }),
+ ).toBeInTheDocument();
+
+ fireEvent.click(screen.getByRole("button", { name: /^done/i }));
+ advanceNavigationTimer();
+
+ expect(props.onToggleSection).toHaveBeenCalledWith("intro");
+ expect(props.onNavigate).toHaveBeenCalledWith(1);
+ });
+
+ it("navigates from the table of contents after the transition delay", () => {
+ const { props } = renderSlideshow();
+
+ fireEvent.click(
+ screen.getByRole("button", { name: "Open table of contents" }),
+ );
+ fireEvent.click(screen.getByRole("button", { name: "Setup" }));
+ advanceNavigationTimer();
+
+ expect(props.onNavigate).toHaveBeenCalledWith(1);
+ expect(
+ screen.getByRole("button", { name: "Open table of contents" }),
+ ).toBeInTheDocument();
+ });
+
+ it("handles keyboard exit and next navigation shortcuts", () => {
+ const { props } = renderSlideshow({
+ completedSections: new Set(["intro"]),
+ });
+
+ fireEvent.keyDown(document, { key: "ArrowRight" });
+ advanceNavigationTimer();
+ expect(props.onNavigate).toHaveBeenCalledWith(1);
+
+ fireEvent.keyDown(document, { key: "Escape" });
+ expect(props.onExit).toHaveBeenCalledTimes(1);
+ });
+});
diff --git a/packages/ui/src/components/social-fab/social-fab.test.tsx b/packages/ui/src/components/social-fab/social-fab.test.tsx
new file mode 100644
index 00000000..2b415185
--- /dev/null
+++ b/packages/ui/src/components/social-fab/social-fab.test.tsx
@@ -0,0 +1,129 @@
+import { act, fireEvent, render, screen } from "@testing-library/react";
+import { afterEach, describe, expect, it, vi } from "vitest";
+
+import { SocialFAB, type SocialFabProps } from "./social-fab";
+
+const originalInnerWidth = window.innerWidth;
+
+const labels = {
+ close: "Close social actions",
+ share: "Share",
+};
+
+const actions = [
+ { id: "share", label: "Share", onClick: vi.fn() },
+ { id: "copy", label: "Copy link", onClick: vi.fn() },
+];
+
+function setViewportWidth(width: number) {
+ Object.defineProperty(window, "innerWidth", {
+ configurable: true,
+ value: width,
+ });
+ act(() => {
+ window.dispatchEvent(new Event("resize"));
+ });
+}
+
+function renderSocialFab(overrides: Partial = {}) {
+ return render(
+ ,
+ );
+}
+
+function getMainButton(name: string): HTMLElement {
+ const buttons = screen.getAllByRole("button", { name });
+ const button = buttons.at(-1);
+ if (!button) throw new Error(`Expected main button named ${name}`);
+ return button;
+}
+
+function getFirstButton(name: string): HTMLElement {
+ const button = screen.getAllByRole("button", { name }).at(0);
+ if (!button) throw new Error(`Expected button named ${name}`);
+ return button;
+}
+
+describe("SocialFAB", () => {
+ afterEach(() => {
+ vi.restoreAllMocks();
+ setViewportWidth(originalInnerWidth);
+ });
+
+ it("renders nothing when hidden", () => {
+ const { container } = renderSocialFab({ hidden: true });
+
+ expect(container.firstChild).toBeNull();
+ });
+
+ it("opens and closes from desktop hover callbacks", () => {
+ const onClose = vi.fn();
+ const onOpen = vi.fn();
+ const { container } = renderSocialFab({ onClose, onOpen });
+ const wrapper = container.querySelector(".fixed");
+ if (!wrapper) throw new Error("Expected fixed FAB wrapper");
+
+ fireEvent.mouseEnter(wrapper);
+ expect(
+ screen.getByRole("button", { name: "Close social actions" }),
+ ).toHaveAttribute("aria-expanded", "true");
+ expect(onOpen).toHaveBeenCalledWith("hover", "desktop");
+
+ fireEvent.mouseLeave(wrapper);
+ expect(getMainButton("Share")).toHaveAttribute("aria-expanded", "false");
+ expect(onClose).toHaveBeenCalledWith("hover_leave");
+ });
+
+ it("uses a mobile backdrop to close expanded actions", () => {
+ setViewportWidth(390);
+ const onClose = vi.fn();
+ const onOpen = vi.fn();
+ renderSocialFab({ onClose, onOpen });
+
+ fireEvent.click(getMainButton("Share"));
+
+ expect(
+ screen.getByRole("button", { name: "Close social actions" }),
+ ).toHaveAttribute("aria-expanded", "true");
+ expect(onOpen).toHaveBeenCalledWith("tap", "mobile");
+
+ const backdrop = document.body.querySelector("[aria-hidden='true']");
+ if (!backdrop) throw new Error("Expected mobile backdrop");
+ fireEvent.click(backdrop);
+
+ expect(getMainButton("Share")).toHaveAttribute("aria-expanded", "false");
+ expect(onClose).toHaveBeenCalledWith("backdrop");
+ });
+
+ it("opens share platforms on desktop hover and launches selected share URL", () => {
+ const open = vi.spyOn(window, "open").mockImplementation(() => null);
+ const onAction = vi.fn();
+ renderSocialFab({
+ onAction,
+ sharePlatforms: [
+ {
+ buildUrl: (pageUrl, pageTitle) =>
+ `https://share.example/?url=${pageUrl}&title=${pageTitle}`,
+ key: "example",
+ label: "Example Network",
+ },
+ ],
+ });
+
+ fireEvent.click(getMainButton("Share"));
+ fireEvent.mouseEnter(getFirstButton("Share"));
+ fireEvent.click(screen.getByRole("button", { name: "Example Network" }));
+
+ expect(onAction).toHaveBeenCalledWith("share");
+ expect(open).toHaveBeenCalledWith(
+ expect.stringContaining("https://share.example/"),
+ "_blank",
+ "noopener,noreferrer",
+ );
+ });
+});