Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ claudius/
│ │ │ ├── ChatWindow.tsx # Chat UI container
│ │ │ ├── ChatInput.tsx # Message input form
│ │ │ ├── ChatToggleButton.tsx # Floating action button
│ │ │ └── MessageBubble.tsx # Individual message display
│ │ │ └── ChatMessage.tsx # Individual message display
│ │ ├── hooks/
│ │ │ └── useChat.ts # Chat state management
│ │ ├── index.ts # Public exports
Expand Down Expand Up @@ -99,7 +99,7 @@ pnpm test # Run tests
| `ChatWindow` | Chat UI container with message list and input |
| `ChatInput` | Message input form with submit handling |
| `ChatToggleButton` | Floating button to open/close chat |
| `MessageBubble` | Renders individual messages with URL linking |
| `ChatMessage` | Renders individual messages with URL linking |
| `ChatSources` | Slide-out sidebar displaying grouped source links |
| `SourceIcon` | Icon button with badge count to trigger source sidebar |

Expand Down
85 changes: 85 additions & 0 deletions docs/plans/2026-03-27-chatmessage-rename.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# ChatMessage Rename Implementation Plan

> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

**Goal:** Rename `MessageBubble` to `ChatMessage` for naming consistency with other `Chat*` components.

**Architecture:** Pure rename/refactor. No logic changes. Rename the component, file, test file, and update all imports.

**Tech Stack:** React, TypeScript, Vitest

---

### Task 1: Rename component file

**Files:**
- Rename: `widget/src/components/MessageBubble.tsx` -> `widget/src/components/ChatMessage.tsx`

**Step 1: Create ChatMessage.tsx with renamed exports**

Copy `MessageBubble.tsx` to `ChatMessage.tsx`. Rename:
- Interface: `MessageBubbleProps` -> `ChatMessageProps`
- Component: `MessageBubble` -> `ChatMessage`
- `memo` display name: `MessageBubble` -> `ChatMessage`

**Step 2: Delete old MessageBubble.tsx**

**Step 3: Run tests to verify they fail (imports broken)**

Run: `cd widget && pnpm test -- --run`
Expected: FAIL - cannot find `MessageBubble`

### Task 2: Update test file

**Files:**
- Rename: `widget/src/components/__tests__/MessageBubble.test.tsx` -> `widget/src/components/__tests__/ChatMessage.test.tsx`

**Step 1: Create ChatMessage.test.tsx**

Copy test file, update:
- Import: `from "../MessageBubble"` -> `from "../ChatMessage"`
- References: `MessageBubble` -> `ChatMessage`
- Describe block: `"MessageBubble"` -> `"ChatMessage"`

**Step 2: Delete old MessageBubble.test.tsx**

### Task 3: Update ChatWindow import

**Files:**
- Modify: `widget/src/components/ChatWindow.tsx`

**Step 1: Update import and JSX usage**

Change:
```tsx
import { MessageBubble } from "./MessageBubble";
```
to:
```tsx
import { ChatMessage } from "./ChatMessage";
```

Change JSX `<MessageBubble` to `<ChatMessage` (and closing tag).

### Task 4: Update CLAUDE.md references

**Files:**
- Modify: `CLAUDE.md`

**Step 1: Update component table and file listing**

Replace `MessageBubble` with `ChatMessage` in the project structure and component table.

### Task 5: Run tests and verify

**Step 1: Run all widget tests**

Run: `cd widget && pnpm test -- --run`
Expected: All tests PASS

**Step 2: Commit**

```bash
git add -A
git commit -m "refactor: rename MessageBubble to ChatMessage for naming consistency"
```
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { memo, type ReactNode } from "react";
import { SourceIcon } from "./SourceIcon";
import type { Source } from "../api/types";

interface MessageBubbleProps {
interface ChatMessageProps {
role: "user" | "assistant";
content: string;
sources?: Source[];
Expand Down Expand Up @@ -87,13 +87,13 @@ function renderFormattedContent(content: string): ReactNode[] {
));
}

export const MessageBubble = memo(function MessageBubble({
export const ChatMessage = memo(function ChatMessage({
role,
content,
sources,
onSourceClick,
isSourceActive,
}: MessageBubbleProps) {
}: ChatMessageProps) {
const isUser = role === "user";

return (
Expand Down
15 changes: 4 additions & 11 deletions widget/src/components/ChatWindow.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
import { useEffect, useRef, useState } from "react";
import { MessageBubble } from "./MessageBubble";
import { ChatMessage } from "./ChatMessage";
import { ChatInput } from "./ChatInput";
import { ChatSources } from "./ChatSources";
import { useSwipeToDismiss } from "../hooks/useSwipeToDismiss";
import type { WidgetPosition } from "./ChatWidget";
import type { ClaudiusTranslations } from "../i18n";
import type { Source } from "../api/types";

interface ChatMessage {
id: string;
role: "user" | "assistant";
content: string;
sources?: Source[];
}
import type { ChatMessage as ChatMessageData, Source } from "../api/types";

interface ChatWindowProps {
messages: ChatMessage[];
messages: ChatMessageData[];
isLoading: boolean;
error: string | null;
onSend: (message: string) => void;
Expand Down Expand Up @@ -165,7 +158,7 @@ export function ChatWindow({
)}

{messages.map((msg) => (
<MessageBubble
<ChatMessage
key={msg.id}
role={msg.role}
content={msg.content}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { describe, it, expect, vi } from "vitest";
import { MessageBubble } from "../MessageBubble";
import { ChatMessage } from "../ChatMessage";
import type { Source } from "../../api/types";

const mockSources: Source[] = [
{ url: "https://pmds.info/blog/test", title: "Test Post", type: "blog" },
{ url: "https://pmds.info/services", title: "Services", type: "page" },
];

describe("MessageBubble", () => {
describe("ChatMessage", () => {
it("renders user message with correct styling", () => {
render(<MessageBubble role="user" content="Hello!" />);
render(<ChatMessage role="user" content="Hello!" />);
const bubble = screen.getByText("Hello!");
expect(bubble).toBeInTheDocument();
// ml-auto is on the outer wrapper div (parent of the bubble div)
Expand All @@ -20,7 +20,7 @@ describe("MessageBubble", () => {
});

it("renders assistant message with correct styling", () => {
render(<MessageBubble role="assistant" content="How can I help?" />);
render(<ChatMessage role="assistant" content="How can I help?" />);
const bubble = screen.getByText("How can I help?");
expect(bubble).toBeInTheDocument();
// mr-auto is on the outer wrapper div (parent of the bubble div)
Expand All @@ -30,7 +30,7 @@ describe("MessageBubble", () => {

it("renders links as clickable anchors", () => {
render(
<MessageBubble
<ChatMessage
role="assistant"
content="Visit https://pmds.info/contact to get started!"
/>
Expand All @@ -43,7 +43,7 @@ describe("MessageBubble", () => {

it("renders source icon for assistant messages with sources", () => {
render(
<MessageBubble
<ChatMessage
role="assistant"
content="Here are resources."
sources={mockSources}
Expand All @@ -57,7 +57,7 @@ describe("MessageBubble", () => {

it("does not render source icon for user messages", () => {
render(
<MessageBubble
<ChatMessage
role="user"
content="Hello"
sources={mockSources}
Expand All @@ -70,7 +70,7 @@ describe("MessageBubble", () => {

it("does not render source icon when no sources", () => {
render(
<MessageBubble role="assistant" content="No sources here." />
<ChatMessage role="assistant" content="No sources here." />
);
expect(screen.queryByRole("button", { name: /view sources/i })).not.toBeInTheDocument();
});
Expand All @@ -79,7 +79,7 @@ describe("MessageBubble", () => {
const user = userEvent.setup();
const onSourceClick = vi.fn();
render(
<MessageBubble
<ChatMessage
role="assistant"
content="Resources."
sources={mockSources}
Expand Down
Loading