Implemented Story 11: Text Alignment and Syntax Highlighting - Removed center-alignment from chat container (text-align: center) - Added left-alignment to markdown body and code blocks - Integrated react-syntax-highlighter with react-markdown - Added syntax highlighting for code blocks using oneDark theme - Supports JavaScript, TypeScript, Rust, Python, JSON, Markdown, Shell, and more - Inline code maintains simple styling without full highlighting - All code blocks are now left-aligned for better readability Fixed: Agent over-aggressive file writing behavior - Refined system prompt to distinguish between: * 'show/example/how does' → respond with code in chat * 'create/add/implement/fix' → use write_file tool - Removed aggressive AGENT DIRECTIVE prefix from user messages - Softened reminder message to reflect nuanced behavior - Agent can now both teach (show examples) and implement (write files) Updated Specs - Added Text Alignment and Readability section to UI_UX.md - Added Syntax Highlighting section with implementation details - Updated SDSW workflow: acceptance criteria marked complete only after user acceptance Dependencies - Added react-syntax-highlighter and @types/react-syntax-highlighter
160 lines
7.6 KiB
Markdown
160 lines
7.6 KiB
Markdown
# Functional Spec: UI/UX Responsiveness
|
|
|
|
## Problem
|
|
Currently, the `chat` command in Rust is an async function that performs a long-running, blocking loop (waiting for LLM, executing tools). While Tauri executes this on a separate thread from the UI, the frontend awaits the *entire* result before re-rendering. This makes the app feel "frozen" because there is no feedback during the 10-60 seconds of generation.
|
|
|
|
## Solution: Event-Driven Feedback
|
|
Instead of waiting for the final array of messages, the Backend should emit **Events** to the Frontend in real-time.
|
|
|
|
### 1. Events
|
|
* `chat:token`: Emitted when a text token is generated (Streaming text).
|
|
* `chat:tool-start`: Emitted when a tool call begins (e.g., `{ tool: "git status" }`).
|
|
* `chat:tool-end`: Emitted when a tool call finishes (e.g., `{ output: "..." }`).
|
|
|
|
### 2. Implementation Strategy (MVP)
|
|
For this story, we won't fully implement token streaming (as `reqwest` blocking/async mixed with stream parsing is complex). We will focus on **State Updates**:
|
|
|
|
* **Refactor `chat` command:**
|
|
* Instead of returning `Vec<Message>` at the very end, it accepts a `AppHandle`.
|
|
* Inside the loop, after every step (LLM response, Tool Execution), emit an event `chat:update` containing the *current partial history*.
|
|
* The Frontend listens to `chat:update` and re-renders immediately.
|
|
|
|
### 3. Visuals
|
|
* **Loading State:** The "Send" button should show a spinner or "Stop" button.
|
|
* **Auto-Scroll:** The chat view should stick to the bottom as new events arrive.
|
|
|
|
## Tool Output Display
|
|
|
|
### Problem
|
|
Tool outputs (like file contents, search results, or command output) can be very long, making the chat history difficult to read. Users need to see the Agent's reasoning and responses without being overwhelmed by verbose tool output.
|
|
|
|
### Solution: Collapsible Tool Outputs
|
|
Tool outputs should be rendered in a collapsible component that is **closed by default**.
|
|
|
|
### Requirements
|
|
|
|
1. **Default State:** Tool outputs are collapsed/closed when first rendered
|
|
2. **Summary Line:** Shows essential information without expanding:
|
|
- Tool name (e.g., `read_file`, `exec_shell`)
|
|
- Key arguments (e.g., file path, command name)
|
|
- Format: "▶ tool_name(key_arg)"
|
|
- Example: "▶ read_file(src/main.rs)"
|
|
- Example: "▶ exec_shell(cargo check)"
|
|
3. **Expandable:** User can click the summary to toggle expansion
|
|
4. **Output Display:** When expanded, shows the complete tool output in a readable format:
|
|
- Use `<pre>` or monospace font for code/terminal output
|
|
- Preserve whitespace and line breaks
|
|
- Limit height with scrolling for very long outputs (e.g., max-height: 300px)
|
|
5. **Visual Indicator:** Clear arrow or icon showing collapsed/expanded state
|
|
6. **Styling:** Consistent with the dark theme, distinguishable from assistant messages
|
|
|
|
### Implementation Notes
|
|
* Use native `<details>` and `<summary>` HTML elements for accessibility
|
|
* Or implement custom collapsible component with proper ARIA attributes
|
|
* Tool outputs should be visually distinct (border, background color, or badge)
|
|
* Multiple tool calls in sequence should each be independently collapsible
|
|
|
|
## Scroll Bar Styling
|
|
|
|
### Problem
|
|
Visible scroll bars create visual clutter and make the interface feel less polished. Standard browser scroll bars can be distracting and break the clean aesthetic of the dark theme.
|
|
|
|
### Solution: Hidden Scroll Bars with Maintained Functionality
|
|
Scroll bars should be hidden while maintaining full scroll functionality.
|
|
|
|
### Requirements
|
|
|
|
1. **Visual:** Scroll bars should not be visible to the user
|
|
2. **Functionality:** Scrolling must still work perfectly:
|
|
- Mouse wheel scrolling
|
|
- Trackpad scrolling
|
|
- Keyboard navigation (arrow keys, page up/down)
|
|
- Auto-scroll to bottom for new messages
|
|
3. **Cross-browser:** Solution must work on Chrome, Firefox, and Safari
|
|
4. **Areas affected:**
|
|
- Main chat message area (vertical scroll)
|
|
- Tool output content (both vertical and horizontal)
|
|
- Any other scrollable containers
|
|
|
|
### Implementation Notes
|
|
* Use CSS `scrollbar-width: none` for Firefox
|
|
* Use `::-webkit-scrollbar { display: none; }` for Chrome/Safari/Edge
|
|
* Maintain `overflow: auto` or `overflow-y: scroll` to preserve scroll functionality
|
|
* Ensure `overflow-x: hidden` where horizontal scroll is not needed
|
|
* Test with very long messages and large tool outputs to ensure no layout breaking
|
|
|
|
## Text Alignment and Readability
|
|
|
|
### Problem
|
|
Center-aligned text in a chat interface is unconventional and reduces readability, especially for code blocks and long-form content. Standard chat UIs align messages differently based on the sender.
|
|
|
|
### Solution: Context-Appropriate Text Alignment
|
|
Messages should follow standard chat UI conventions with proper alignment based on message type.
|
|
|
|
### Requirements
|
|
|
|
1. **User Messages:** Right-aligned (standard pattern showing messages sent by the user)
|
|
2. **Assistant Messages:** Left-aligned (standard pattern showing messages received)
|
|
3. **Tool Outputs:** Left-aligned (part of the system/assistant response flow)
|
|
4. **Code Blocks:** Always left-aligned regardless of message type (for readability)
|
|
5. **Container:** Remove any center-alignment from the chat container
|
|
6. **Max-Width:** Maintain current max-width constraint (e.g., 768px) for optimal readability
|
|
7. **Spacing:** Maintain proper padding and visual hierarchy between messages
|
|
|
|
### Implementation Notes
|
|
* Check for `textAlign: "center"` in inline styles and remove
|
|
* Check for `text-align: center` in CSS and remove from chat-related classes
|
|
* Ensure flexbox alignment is set appropriately:
|
|
* User messages: `alignItems: "flex-end"`
|
|
* Assistant/Tool messages: `alignItems: "flex-start"`
|
|
* Code blocks should have `text-align: left` explicitly set
|
|
|
|
## Syntax Highlighting
|
|
|
|
### Problem
|
|
Code blocks in assistant responses currently lack syntax highlighting, making them harder to read and understand. Developers expect colored syntax highlighting similar to their code editors.
|
|
|
|
### Solution: Syntax Highlighting for Code Blocks
|
|
Integrate syntax highlighting into markdown code blocks rendered by the assistant.
|
|
|
|
### Requirements
|
|
|
|
1. **Languages Supported:** At minimum:
|
|
- JavaScript/TypeScript
|
|
- Rust
|
|
- Python
|
|
- JSON
|
|
- Markdown
|
|
- Shell/Bash
|
|
- HTML/CSS
|
|
- SQL
|
|
2. **Theme:** Use a dark theme that complements the existing dark UI (e.g., `oneDark`, `vsDark`, `dracula`)
|
|
3. **Integration:** Work seamlessly with `react-markdown` component
|
|
4. **Performance:** Should not significantly impact rendering performance
|
|
5. **Fallback:** Plain monospace text for unrecognized languages
|
|
6. **Inline Code:** Inline code (single backticks) should maintain simple styling without full syntax highlighting
|
|
|
|
### Implementation Notes
|
|
* Use `react-syntax-highlighter` library with `react-markdown`
|
|
* Or use `rehype-highlight` plugin for `react-markdown`
|
|
* Configure with a dark theme preset (e.g., `oneDark` from `react-syntax-highlighter/dist/esm/styles/prism`)
|
|
* Apply to code blocks via `react-markdown` components prop:
|
|
```tsx
|
|
<Markdown
|
|
components={{
|
|
code: ({node, inline, className, children, ...props}) => {
|
|
const match = /language-(\w+)/.exec(className || '');
|
|
return !inline && match ? (
|
|
<SyntaxHighlighter style={oneDark} language={match[1]} {...props}>
|
|
{String(children).replace(/\n$/, '')}
|
|
</SyntaxHighlighter>
|
|
) : (
|
|
<code className={className} {...props}>{children}</code>
|
|
);
|
|
}
|
|
}}
|
|
/>
|
|
```
|
|
* Ensure syntax highlighted code blocks are left-aligned
|
|
* Test with various code samples to ensure proper rendering
|