Skip to content

feat(chat): redesign chat UI with modular parts architecture#22

Open
Youhai020616 wants to merge 2 commits intomainfrom
feat/chat-ui-redesign
Open

feat(chat): redesign chat UI with modular parts architecture#22
Youhai020616 wants to merge 2 commits intomainfrom
feat/chat-ui-redesign

Conversation

@Youhai020616
Copy link
Copy Markdown
Owner

Summary

  • Phase A: Refactor monolithic ChatMessage (548→167 lines) into modular parts — UserMessagePart, AssistMessagePart, ReasoningPart, ToolMessagePart, WordByWordFadeIn
  • Phase B: Multi-layer glass input effect, ScrollToBottomButton with framer-motion, Cmd+E thinking toggle shortcut
  • Phase C: Time-based welcome greeting with typewriter animation, expandable error bar, enhanced typing indicator
  • Phase D: Specialized tool renderers (WebSearch/Code/Browser/Default), keyboard shortcuts (Cmd+Shift+K copy, Cmd+Shift+D delete), tool output visualization with Input/Output tabs

Changes

Area Files Description
Message Parts 6 new files in message-parts/ Modular message rendering with custom memo
Tool Renderers 5 new files in tool-renderers/ Specialized visualizations per tool type
WelcomeScreen 1 new file Extracted + animated greeting
ChatMessage rewritten Thin parts dispatcher (167 lines)
ChatInput modified 4-layer glass morphism effect
index.tsx modified ScrollToBottom, ErrorBar, shortcuts, toolResultsMap
i18n en/zh/ja ~30 new translation keys

Test plan

  • Verify chat messages render correctly (user/assistant/tool)
  • Test streaming with word-by-word fade-in animation
  • Test long text truncation (>1000 chars) with expand/collapse
  • Verify ScrollToBottom button appears when scrolled up
  • Test Cmd+E thinking toggle shortcut
  • Test Cmd+Shift+K copy last message
  • Verify tool renderers display for search/code/browser tools
  • Check welcome screen typewriter animation
  • Verify error bar expand/collapse
  • Test in employee chat mode (EmployeeChat → Chat)

🤖 Generated with Claude Code

Refactor monolithic ChatMessage (548→167 lines) into independent part components
inspired by better-chatbot: UserMessagePart, AssistMessagePart, ReasoningPart,
ToolMessagePart, WordByWordFadeIn. Add multi-layer glass input, ScrollToBottom
button, expandable error bar, time-based welcome screen with typewriter animation,
specialized tool renderers (search/code/browser), and keyboard shortcuts
(Cmd+E thinking, Cmd+Shift+K copy, Cmd+Shift+D delete).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 13, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ab1a6979-4783-47a3-9eee-0028c7b67a17

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/chat-ui-redesign
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@augmentcode
Copy link
Copy Markdown

augmentcode bot commented Mar 13, 2026

🤖 Augment PR Summary

Summary: This PR redesigns the Chat UI by splitting message rendering into modular “parts” and adding richer, animated interaction patterns.

Changes:

  • Refactors ChatMessage from a large monolith into a thin dispatcher that composes UserMessagePart, AssistMessagePart, ReasoningPart, and tool components.
  • Adds a new animated WelcomeScreen with time-based greetings, a typewriter effect, and rotating suggestion prompts.
  • Introduces specialized tool renderers (WebSearch / CodeExecutor / Browser / Default) and a toolResultsMap to visualize tool input/output with tabs.
  • Updates the input area with a multi-layer “glass” effect and refreshed send/stop affordances.
  • Adds scroll tracking and a floating “scroll to bottom” button for long conversations.
  • Replaces the static error strip with an animated, expandable error bar.
  • Adds keyboard shortcuts (Cmd/Ctrl+E toggle thinking, Cmd/Ctrl+Shift+K copy last assistant, Cmd/Ctrl+Shift+D delete conversation).
  • Extends i18n strings (en/zh/ja) for new UI labels, error/typing text, message actions, and tool UI.

Technical Notes: Uses framer-motion for entrance/expand/collapse animations and introduces memoized subcomponents for message rendering to reduce re-renders.

🤖 Was this summary useful? React with 👍 or 👎

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 7 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.


useEffect(() => {
// Delay typewriter start to sync with fade-in animation
const delay = setTimeout(runTypewriter, 400);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runTypewriter creates an interval and returns a cleanup, but the effect that calls it only clears the timeout, not the interval. If the component unmounts mid-typewriter (or fullGreeting changes quickly), the interval can keep running and call state setters after unmount.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

const [copied, setCopied] = useState(false);

const code = useMemo(() => extractCode(input), [input]);
const language = useMemo(() => extractLanguage(input, ''), [input]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extractLanguage is called with an empty tool name (extractLanguage(input, '')), so the tool-name-based language inference path never runs. This can make the language badge misleading when the input doesn’t explicitly include a language.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="ghost" size="icon" className="h-7 w-7" onClick={handleEdit}>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Edit action is shown even when onEdit is undefined, so users can enter edit mode and hit Save with no actual persistence/update happening. Consider gating the edit affordance on onEdit being provided (similar to how Delete is gated).

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

const images = extractImages(message);
const tools = extractToolUse(message);
const visibleThinking = showThinking ? thinking : null;
const visibleTools = tools;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tool cards are now rendered regardless of showThinking (visibleTools = tools). If the “thinking” toggle is intended to hide tool call details/status as well (as it previously did), this change may be unintentionally exposing tool inputs when thinking is turned off.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.


// Build a map of toolCallId → tool result content from toolresult messages
// so ToolCard renderers can display the output of each tool invocation.
const toolResultsMap = useMemo(() => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toolResultsMap is built from messages entries with role toolresult, but the chat store’s history load path filters tool-result-role messages out of messages. That means tool outputs may be unavailable for previously loaded conversations (e.g., after refresh) even though ToolCards are rendered.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

<TooltipContent className="flex items-center gap-2">
<span>{showThinking ? t('toolbar.hideThinking') : t('toolbar.showThinking')}</span>
<kbd className="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground">
<span className="text-xs">{navigator.platform.includes('Mac') ? '⌘' : 'Ctrl'}</span>E
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses navigator.platform directly during render; in non-browser contexts (SSR/tests) navigator can be undefined and crash the component. A small guard would make this more robust.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

const [copied, setCopied] = useState(false);

const copyContent = useCallback(() => {
navigator.clipboard.writeText(text);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

navigator.clipboard.writeText(...) returns a Promise; if it rejects (permissions/unavailable clipboard), this can surface as an unhandled promise rejection. Handling/catching failures would avoid noisy runtime errors.

Severity: low

Other Locations
  • src/pages/Chat/message-parts/UserMessagePart.tsx:70

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Base automatically changed from develop to main March 19, 2026 03:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant