docs(06-chat-ui-redesign): create phase 6 plans
This commit is contained in:
1 parent
3d57acbc7d
commit
3364dba5aa
4 files changed
+722
No files matched your search
@@ -93,6 +93,24 @@ Plans:
|
||||
- [x] `05-03-PLAN.md` - Add validation UI and recovery experience.
|
||||
**UI hint**: yes
|
||||
|
||||
### Phase 6: Chat UI Redesign (Manus AI System Design)
|
||||
**Goal**: Redesign the chat UI to follow Manus AI system design with correct color tokens, component decomposition, and UX patterns.
|
||||
**Depends on**: Phase 5
|
||||
**Requirements**: UI-01, UI-02, UI-03
|
||||
**Success Criteria** (what must be TRUE):
|
||||
1. Model selector lives inside the chat input pill (hero and regular), not the sidebar.
|
||||
2. scan_models returns only top-level GGUF files (no subdirectory traversal).
|
||||
3. Thinking indicator is a single pulsing blue dot + "Thinking" text.
|
||||
4. Send button uses PaperPlaneRight icon only.
|
||||
5. App uses Manus color tokens (#171717 base, #1E1E1E surface, #262626 elevated).
|
||||
6. Settings page aligns to Manus design tokens.
|
||||
**Plans**: 3 plans
|
||||
Plans:
|
||||
- [ ] `06-01-PLAN.md` — Backend scan fix + ModelSelectorPill + Sidebar cleanup + ChatView wiring
|
||||
- [ ] `06-02-PLAN.md` — Global Manus tokens + thinking indicator + send button + message widths
|
||||
- [ ] `06-03-PLAN.md` — Settings page Manus token alignment
|
||||
**UI hint**: yes
|
||||
|
||||
## Progress
|
||||
|
||||
| Phase | Plans Complete | Status | Completed |
|
||||
@@ -102,3 +120,4 @@ Plans:
|
||||
| 3. Unified Runtime Workspace | 3/3 | Complete | 2026-03-29 |
|
||||
| 4. Hugging Face Download Engine | 3/3 | Complete | 2026-03-31 |
|
||||
| 5. Model Source Validation | 3/3 | Planned | - |
|
||||
| 6. Chat UI Redesign | 0/3 | Planned | - |
|
||||
@@ -0,0 +1,208 @@
|
||||
---
|
||||
phase: 06-chat-ui-redesign
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- tauri-app/src-tauri/src/model_files.rs
|
||||
- tauri-app/src/components/ModelSelectorPill.tsx
|
||||
- tauri-app/src/components/Sidebar.tsx
|
||||
- tauri-app/src/App.tsx
|
||||
- tauri-app/src/components/ChatView.tsx
|
||||
autonomous: true
|
||||
requirements: [UI-01]
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "scan_models returns only GGUF files at the root of the models directory (no subdirectory traversal)"
|
||||
- "Model selector dropdown appears inside the chat input area (both hero and regular input)"
|
||||
- "Model selector is absent from the Sidebar"
|
||||
- "Selecting a model in the input pill updates the active model"
|
||||
artifacts:
|
||||
- path: "tauri-app/src-tauri/src/model_files.rs"
|
||||
provides: "scan_model_dir_top_level function replaces recursive scan"
|
||||
contains: "scan_model_dir_top_level"
|
||||
- path: "tauri-app/src/components/ModelSelectorPill.tsx"
|
||||
provides: "Reusable model selector dropdown pill for input area"
|
||||
exports: ["ModelSelectorPill", "ModelSelectorPillProps"]
|
||||
- path: "tauri-app/src/components/Sidebar.tsx"
|
||||
provides: "Sidebar without model-section block"
|
||||
key_links:
|
||||
- from: "tauri-app/src/App.tsx"
|
||||
to: "tauri-app/src/components/ChatView.tsx"
|
||||
via: "new props: models, localModels, selectedModel, onModelChange, onModelSwap, isSwapping, status"
|
||||
pattern: "models=\\{models\\}"
|
||||
- from: "tauri-app/src/components/ChatView.tsx"
|
||||
to: "tauri-app/src/components/ModelSelectorPill.tsx"
|
||||
via: "import and render inside .input-box"
|
||||
pattern: "<ModelSelectorPill"
|
||||
- from: "tauri-app/src-tauri/src/model_files.rs"
|
||||
to: "scan_model_dir_top_level"
|
||||
via: "scan_models Tauri command calls top-level scanner"
|
||||
pattern: "scan_model_dir_top_level"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Fix the Rust model scan to return only top-level GGUF files, create a ModelSelectorPill component, move the model selector out of the Sidebar and into the ChatView input area.
|
||||
|
||||
Purpose: The model selector must live in the chat input bubble (Manus AI pattern), not the sidebar. The scan bug returns unintended nested models from HuggingFace cache dirs.
|
||||
Output: `scan_model_dir_top_level` Rust function, `ModelSelectorPill.tsx` component, Sidebar cleaned of model-section, ChatView wired with model selector in both input boxes.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.config/opencode/get-shit-done/workflows/execute-plan.md
|
||||
@$HOME/.config/opencode/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/phases/06-chat-ui-redesign/06-RESEARCH.md
|
||||
|
||||
@tauri-app/src-tauri/src/model_files.rs
|
||||
@tauri-app/src/components/Sidebar.tsx
|
||||
@tauri-app/src/components/ChatView.tsx
|
||||
@tauri-app/src/App.tsx
|
||||
</context>
|
||||
|
||||
<interfaces>
|
||||
<!-- Key contracts the executor needs. Extracted from codebase. -->
|
||||
|
||||
From tauri-app/src/components/Sidebar.tsx (lines 13-22) — props that move to ChatView:
|
||||
```typescript
|
||||
interface SidebarProps {
|
||||
models: ModelInfo[]; // <- these 6 props move to ChatView
|
||||
localModels: RuntimeModelFile[];
|
||||
selectedModel: string;
|
||||
onModelChange: (v: string) => void;
|
||||
onModelSwap?: (path: string) => void;
|
||||
isSwapping?: boolean;
|
||||
status: RuntimeStatus;
|
||||
// ... non-model props stay in Sidebar
|
||||
}
|
||||
```
|
||||
|
||||
From tauri-app/src/components/ChatView.tsx (lines 18-28) — current ChatView Props:
|
||||
```typescript
|
||||
interface Props {
|
||||
db: DB;
|
||||
chatId: number | null;
|
||||
server: string;
|
||||
apiKey: string;
|
||||
model: string;
|
||||
onChatCreated: (id: number) => void;
|
||||
onChatUpdated: () => void;
|
||||
onOpenSidebar?: () => void;
|
||||
onDegradationDetected?: () => void;
|
||||
}
|
||||
// New props to add: models, localModels, selectedModel, onModelChange, onModelSwap, isSwapping, status
|
||||
```
|
||||
|
||||
From tauri-app/src/components/Sidebar.tsx (lines 56-71) — deduplication logic to extract:
|
||||
```typescript
|
||||
// Merge API models + local scanned models, dedupe by id, filter isInChatSelector
|
||||
const allModels: ModelOption[] = [
|
||||
...models
|
||||
.filter((m) => m.id !== "" && m.id !== "local")
|
||||
.map((m) => ({ id: m.id, label: getDisplayName(m.id) })),
|
||||
...localModels.map((m) => ({ id: m.path, label: getDisplayName(m.path) })),
|
||||
].filter((m, i, arr) => arr.findIndex((x) => x.id === m.id) === i);
|
||||
const selectedLabel = getDisplayName(selectedModel) || "No model";
|
||||
```
|
||||
|
||||
New ModelSelectorPill interface (to create):
|
||||
```typescript
|
||||
interface ModelSelectorPillProps {
|
||||
models: ModelInfo[];
|
||||
localModels: RuntimeModelFile[];
|
||||
selectedModel: string;
|
||||
onModelChange: (id: string) => void;
|
||||
onModelSwap?: (path: string) => void;
|
||||
isSwapping?: boolean;
|
||||
status: RuntimeStatus;
|
||||
}
|
||||
```
|
||||
|
||||
Rust scan_models Tauri command signature (model_files.rs):
|
||||
```rust
|
||||
#[tauri::command]
|
||||
pub fn scan_models(dir: String) -> Result<Vec<ModelFile>, String>
|
||||
// Currently calls scan_model_dir() -> scan_model_dir_recursive()
|
||||
// Must change to call scan_model_dir_top_level()
|
||||
```
|
||||
</interfaces>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Fix Rust model scan to top-level only + update test</name>
|
||||
<files>tauri-app/src-tauri/src/model_files.rs</files>
|
||||
<action>
|
||||
Add a new `scan_model_dir_top_level(path: &Path) -> Result<Vec<ModelFile>, String>` function that reads only the immediate children of `path` (depth=1) — no recursion. Only collects entries where `p.is_file()` and extension is `"gguf"` (case-insensitive). Sort by name. Keep `scan_model_dir_recursive` in place (used by existing tests and potentially future use) — do NOT delete it.
|
||||
|
||||
Update `scan_model_dir()` to call `scan_model_dir_top_level` instead of `scan_model_dir_recursive` — OR bypass `scan_model_dir()` entirely and have the `scan_models` Tauri command call `scan_model_dir_top_level` directly.
|
||||
|
||||
Update the `scan_model_dir_finds_gguf_in_subdirectories` test (line 196): rename it to `scan_model_dir_returns_only_top_level_gguf` and update the assertion so nested models are NOT in the result — only `["top-level.gguf"]`. Add a new test `scan_model_dir_recursive_still_finds_nested` that exercises `scan_model_dir_recursive` directly to ensure the recursive function still works.
|
||||
|
||||
Verify: `cargo test -p commands` (or `cargo test` in `tauri-app/src-tauri/`) passes with no failures.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd tauri-app/src-tauri && cargo test scan_model 2>&1 | tail -10</automated>
|
||||
</verify>
|
||||
<done>All `scan_model*` tests pass. `scan_models` Tauri command uses top-level scan. Nested GGUFs are NOT returned by default.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Create ModelSelectorPill + wire into ChatView + clean Sidebar</name>
|
||||
<files>
|
||||
tauri-app/src/components/ModelSelectorPill.tsx,
|
||||
tauri-app/src/components/Sidebar.tsx,
|
||||
tauri-app/src/components/ChatView.tsx,
|
||||
tauri-app/src/App.tsx
|
||||
</files>
|
||||
<action>
|
||||
**Step A — Create `ModelSelectorPill.tsx`:**
|
||||
Create `tauri-app/src/components/ModelSelectorPill.tsx`. Extract the deduplication logic from `Sidebar.tsx` lines 56-71 into this component (or call a shared util). The component renders a compact pill button showing the selected model's display name (`getDisplayName`). Clicking opens a dropdown listbox (reuse the same HTML pattern as `Sidebar.tsx` lines 136-168: `model-dropdown-menu` with `model-dropdown-item` entries). Use `getDisplayName` from `lib/modelAlias`. Emit `onModelChange(id)` when item selected; if item is a local model path, also call `onModelSwap(path)`. Show a spinner/disabled state when `isSwapping` is true. Style: `bg-[#262626] text-[#9CA3AF] rounded-md px-2 py-1 text-sm flex items-center gap-1.5` for the pill trigger. Dropdown: absolute positioned, `bg-[#1E1E1E] border border-[#333333]`. Props: `ModelSelectorPillProps` as defined in the interface block above.
|
||||
|
||||
**Step B — Clean Sidebar.tsx:**
|
||||
In `Sidebar.tsx`, delete the `model-section` div block (lines ~131-170) and remove from `SidebarProps`: `models`, `localModels`, `selectedModel`, `onModelChange`, `onModelSwap`, `isSwapping`. Remove the `status` prop if it was only used for model selector logic. Remove the deduplication logic (lines 56-69) and the `handleModelSelect` handler. Remove `ModelInfo` import if no longer used.
|
||||
|
||||
**Step C — Update App.tsx:**
|
||||
In `App.tsx`, stop passing the 6 model props to `<Sidebar>`. Add them as new props to `<ChatView>`: `models={models}`, `localModels={localModels}`, `selectedModel={selectedModel}`, `onModelChange={setSelectedModel}`, `onModelSwap={handleModelSwap}`, `isSwapping={isSwapping}`, `status={status}`.
|
||||
|
||||
**Step D — Update ChatView.tsx:**
|
||||
Add the 6 model props to ChatView's `Props` interface. Import `ModelSelectorPill`. Render `<ModelSelectorPill ...props />` inside the input area in TWO places:
|
||||
1. Hero input block (around line 657) — inside `.input-box`, before the textarea, on its own row or inline left.
|
||||
2. Regular input block (around line 860-875) — same position inside `.input-box`.
|
||||
|
||||
Do NOT change any existing chat logic, message handling, or streaming logic.
|
||||
|
||||
Pitfall to avoid: Do NOT use `useModelSelector` hook — just pass props directly. Do NOT create a context. Keep it simple prop-drilling.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd tauri-app && npm run build 2>&1 | tail -20</automated>
|
||||
</verify>
|
||||
<done>TypeScript build passes. ModelSelectorPill renders in both hero and regular input areas. Sidebar has no model-section. App.tsx routes model props to ChatView.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
- `cargo test scan_model` passes — top-level scan verified by updated test
|
||||
- `npm run build` passes — no TypeScript errors
|
||||
- Sidebar.tsx no longer contains `model-section`
|
||||
- ChatView.tsx imports and renders `ModelSelectorPill` in both input contexts
|
||||
- App.tsx passes model props to ChatView (not Sidebar)
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Top-level model scan: `scan_models("./models")` returns only `.gguf` files directly in the folder — NOT files from subdirectories
|
||||
- Model selector visible in chat input pill (hero screen and regular screen)
|
||||
- No model selector in the sidebar
|
||||
- TypeScript and Rust compile without errors
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/06-chat-ui-redesign/06-01-SUMMARY.md`
|
||||
</output>
|
||||
@@ -0,0 +1,281 @@
|
||||
---
|
||||
phase: 06-chat-ui-redesign
|
||||
plan: 02
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: [06-01]
|
||||
files_modified:
|
||||
- tauri-app/src/index.css
|
||||
- tauri-app/tailwind.config.js
|
||||
- tauri-app/src/components/ChatView.tsx
|
||||
- tauri-app/src/components/ChatView.css
|
||||
autonomous: true
|
||||
requirements: [UI-02]
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "App uses Manus color tokens (#171717 base, #1E1E1E surface, #262626 elevated)"
|
||||
- "Thinking indicator is a single pulsing blue dot (#3B82F6) with 'Thinking' text — not three bouncing dots"
|
||||
- "Send button uses PaperPlaneRight icon only (no 'Send' text label)"
|
||||
- "Message and input area share a consistent reading-column width"
|
||||
artifacts:
|
||||
- path: "tauri-app/src/index.css"
|
||||
provides: "Updated :root CSS vars aligned to Manus tokens + Manus named vars"
|
||||
contains: "--manus-base"
|
||||
- path: "tauri-app/tailwind.config.js"
|
||||
provides: "Manus named color tokens registered for Tailwind use"
|
||||
contains: "manus-base"
|
||||
- path: "tauri-app/src/components/ChatView.css"
|
||||
provides: "thinking-manus CSS class, updated thinking animation"
|
||||
contains: "thinking-manus"
|
||||
key_links:
|
||||
- from: "tauri-app/src/index.css"
|
||||
to: "all components"
|
||||
via: "CSS custom properties cascade"
|
||||
pattern: "--manus-base.*#171717"
|
||||
- from: "tauri-app/src/components/ChatView.tsx"
|
||||
to: "tauri-app/src/components/ChatView.css"
|
||||
via: "className thinking-manus replaces thinking"
|
||||
pattern: "thinking-manus"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Apply Manus color tokens globally, replace the three-dot thinking indicator with a pulsing blue dot + "Thinking" text, swap the send button icon to PaperPlaneRight, and align message/input reading-column widths.
|
||||
|
||||
Purpose: Visual alignment with Manus AI system design — correct tokens, correct indicators, correct iconography.
|
||||
Output: Updated CSS vars, Tailwind config, ChatView.tsx (send button + thinking JSX), ChatView.css (thinking animation + width rules).
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.config/opencode/get-shit-done/workflows/execute-plan.md
|
||||
@$HOME/.config/opencode/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/phases/06-chat-ui-redesign/06-RESEARCH.md
|
||||
@.planning/phases/06-chat-ui-redesign/06-01-SUMMARY.md
|
||||
|
||||
@tauri-app/src/index.css
|
||||
@tauri-app/tailwind.config.js
|
||||
@tauri-app/src/components/ChatView.tsx
|
||||
@tauri-app/src/components/ChatView.css
|
||||
</context>
|
||||
|
||||
<interfaces>
|
||||
<!-- Key patterns from current codebase. -->
|
||||
|
||||
Current index.css :root vars to update (tauri-app/src/index.css lines 4-14):
|
||||
```css
|
||||
:root {
|
||||
--bg: #0d1115; /* → #171717 (Manus base) */
|
||||
--bg2: #12171d; /* → #1E1E1E (Manus surface) */
|
||||
--bg3: #171d24; /* → #262626 (Manus elevated)*/
|
||||
--bg4: #1e252d; /* → #333333 (Manus hover) */
|
||||
--bg5: #27303a; /* → #333333 or keep as-is */
|
||||
--text: #f2f4f7; /* → #F3F4F6 (Manus tx) */
|
||||
--text2: #a0a9b4; /* → #9CA3AF (Manus tx2) */
|
||||
--text3: #6f7782; /* → #52525B (Manus tx3) */
|
||||
}
|
||||
```
|
||||
|
||||
Current tailwind.config.js (full contents):
|
||||
```js
|
||||
export default {
|
||||
content: ["./index.html", "./src/**/*.{ts,tsx}"],
|
||||
corePlugins: { preflight: false },
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
"c-bg": "var(--bg)", "c-bg2": "var(--bg2)", "c-bg3": "var(--bg3)",
|
||||
"c-bg4": "var(--bg4)", "c-bg5": "var(--bg5)",
|
||||
"c-bdr": "var(--border)", "c-bdr2": "var(--border2)",
|
||||
"c-tx": "var(--text)", "c-tx2": "var(--text2)", "c-tx3": "var(--text3)",
|
||||
"c-ac": "var(--accent)", "c-ac2": "var(--accent2)",
|
||||
"c-danger": "var(--danger)", "c-success": "var(--success)", "c-warn": "var(--warning)",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Current thinking indicator JSX (ChatView.tsx lines 763-769):
|
||||
```tsx
|
||||
{generating && !streamReasoning && !streamContent && !streamThinkingOpen && (
|
||||
<div className="msg-wrapper assistant">
|
||||
<div className="thinking">
|
||||
<span /><span /><span />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
Current send button (ChatView.tsx line 871 — non-hero):
|
||||
```tsx
|
||||
<button className="send-btn" ...><ArrowUp size={18} weight="duotone" /> Send</button>
|
||||
```
|
||||
Current send button (ChatView.tsx line 657 — hero):
|
||||
```tsx
|
||||
<button className="send-btn" ...><ArrowUp size={18} weight="duotone" /></button>
|
||||
```
|
||||
|
||||
Current message width CSS (ChatView.css):
|
||||
```css
|
||||
.messages-container { max-width: 1200px; }
|
||||
.msg-wrapper.user { max-width: 800px; }
|
||||
.msg-wrapper.assistant { max-width: 100%; } /* <- too wide */
|
||||
.input-row { max-width: 800px; }
|
||||
```
|
||||
</interfaces>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Apply Manus color tokens to index.css and tailwind.config.js</name>
|
||||
<files>tauri-app/src/index.css, tauri-app/tailwind.config.js</files>
|
||||
<action>
|
||||
**index.css — update :root vars to Manus values:**
|
||||
Change the existing CSS vars to the Manus design tokens. Also ADD new named Manus vars for direct use (do not remove old vars — components still reference them):
|
||||
```css
|
||||
:root {
|
||||
/* Updated to Manus design tokens */
|
||||
--bg: #171717; /* was #0d1115 — Manus bg-base */
|
||||
--bg2: #1E1E1E; /* was #12171d — Manus bg-surface */
|
||||
--bg3: #262626; /* was #171d24 — Manus bg-elevated */
|
||||
--bg4: #333333; /* was #1e252d — Manus bg-hover */
|
||||
--bg5: #3D3D3D; /* was #27303a — slightly lighter */
|
||||
--text: #F3F4F6; /* was #f2f4f7 — Manus text-primary */
|
||||
--text2: #9CA3AF; /* was #a0a9b4 — Manus text-secondary */
|
||||
--text3: #52525B; /* was #6f7782 — Manus text-muted */
|
||||
/* Keep all other existing vars (--border, --accent, etc.) unchanged */
|
||||
|
||||
/* NEW: Manus design tokens as named vars (for new components) */
|
||||
--manus-base: #171717;
|
||||
--manus-surface: #1E1E1E;
|
||||
--manus-elevated: #262626;
|
||||
--manus-hover: #333333;
|
||||
--manus-tx: #F3F4F6;
|
||||
--manus-tx2: #9CA3AF;
|
||||
--manus-tx3: #52525B;
|
||||
--manus-blue: #3B82F6;
|
||||
}
|
||||
```
|
||||
|
||||
**tailwind.config.js — add Manus named color tokens:**
|
||||
Add the following entries to the `colors` extension (append after existing entries):
|
||||
```js
|
||||
"manus-base": "var(--manus-base)",
|
||||
"manus-surface": "var(--manus-surface)",
|
||||
"manus-elevated": "var(--manus-elevated)",
|
||||
"manus-hover": "var(--manus-hover)",
|
||||
"manus-tx": "var(--manus-tx)",
|
||||
"manus-tx2": "var(--manus-tx2)",
|
||||
"manus-tx3": "var(--manus-tx3)",
|
||||
"manus-blue": "var(--manus-blue)",
|
||||
```
|
||||
|
||||
Pitfall: CSS specificity — existing hardcoded hex values in `.css` files (e.g., `background: #252525` in ChatView.css) will NOT automatically update when CSS vars change. Do NOT touch those yet (they are handled in Task 2).
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd tauri-app && npm run build 2>&1 | grep -E "error|warning" | head -10</automated>
|
||||
</verify>
|
||||
<done>index.css :root has updated vars + new --manus-* vars. tailwind.config.js has manus-* color tokens. Build passes.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Replace thinking indicator, send button icon, and align message widths</name>
|
||||
<files>tauri-app/src/components/ChatView.tsx, tauri-app/src/components/ChatView.css</files>
|
||||
<action>
|
||||
**ChatView.tsx — three changes:**
|
||||
|
||||
1. **Import:** Add `PaperPlaneRight` to the phosphor import line (line 10):
|
||||
```tsx
|
||||
import { ArrowUp, PaperPlaneRight, Image, Microphone, Paperclip, ChatCircleText } from "@phosphor-icons/react";
|
||||
```
|
||||
(Keep `ArrowUp` import only if used elsewhere; otherwise remove it.)
|
||||
|
||||
2. **Thinking indicator (lines ~763-769):** Replace the three-span bounce with Manus-style:
|
||||
```tsx
|
||||
{generating && !streamReasoning && !streamContent && !streamThinkingOpen && (
|
||||
<div className="msg-wrapper assistant">
|
||||
<div className="thinking-manus">
|
||||
<span className="thinking-dot" aria-hidden="true" />
|
||||
<span className="thinking-label">Thinking</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
3. **Send button icon:** Find ALL occurrences of `<ArrowUp` inside send button JSX (hero ~line 657, regular ~line 871) and replace with `<PaperPlaneRight size={18} weight="fill" />`. Remove the "Send" text label from the non-hero button to make it icon-only. Keep the `.send-btn` class unchanged.
|
||||
|
||||
**ChatView.css — four changes:**
|
||||
|
||||
1. **Remove/replace old `.thinking span` block** (lines ~770-802). Replace with Manus thinking styles:
|
||||
```css
|
||||
.thinking-manus {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
.thinking-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #3B82F6;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
animation: thinking-pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
.thinking-label {
|
||||
font-size: 0.875rem;
|
||||
color: #9CA3AF;
|
||||
font-weight: 400;
|
||||
}
|
||||
@keyframes thinking-pulse {
|
||||
0%, 100% { opacity: 1; transform: scale(1); }
|
||||
50% { opacity: 0.35; transform: scale(0.7); }
|
||||
}
|
||||
```
|
||||
Remove the old `@keyframes thinking-bounce` block too.
|
||||
|
||||
2. **Message + input reading column alignment:**
|
||||
Update the width rules so messages and input align:
|
||||
```css
|
||||
/* Consistent reading column: 800px for user, aligned input */
|
||||
.msg-wrapper.assistant { max-width: 800px; margin-left: 0; } /* was 100% */
|
||||
.msg-wrapper.user { max-width: 800px; } /* unchanged */
|
||||
.input-row { max-width: 800px; } /* unchanged */
|
||||
```
|
||||
Keep `.messages-container { max-width: 1200px; }` as the scroll container — only the message wrapper width matters.
|
||||
|
||||
3. **Update any hardcoded background on `.chat-view` or `.initial-screen`:**
|
||||
Find and replace `background: #252525` (or similar hardcoded colors on the hero/initial screen container) with `background: var(--bg)` so it picks up the updated `#171717` token. Only change the hero background — do not mass-replace all hex values.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd tauri-app && npm run build 2>&1 | tail -10</automated>
|
||||
</verify>
|
||||
<done>TypeScript build passes. ChatView renders PaperPlaneRight send button. thinking-manus class replaces thinking. Message widths set to max 800px for both user and assistant.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
- `npm run build` passes with no TypeScript errors
|
||||
- index.css has `--manus-base: #171717` and updated `--bg: #171717`
|
||||
- tailwind.config.js has `manus-base` through `manus-blue` color tokens
|
||||
- ChatView.tsx imports `PaperPlaneRight`, renders it in both send buttons
|
||||
- ChatView.css has `.thinking-manus` with pulse animation (no more `.thinking span` bounce)
|
||||
- `.msg-wrapper.assistant` max-width is 800px (not 100%)
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- App background is neutral dark (#171717), not navy-black
|
||||
- Thinking state shows "● Thinking" (pulsing blue dot + text), not three bouncing dots
|
||||
- Send button is a paper plane icon, no text label
|
||||
- User and assistant messages share same max reading width (800px)
|
||||
- Build passes clean
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/06-chat-ui-redesign/06-02-SUMMARY.md`
|
||||
</output>
|
||||
@@ -0,0 +1,214 @@
|
||||
---
|
||||
phase: 06-chat-ui-redesign
|
||||
plan: 03
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: [06-01]
|
||||
files_modified:
|
||||
- tauri-app/src/features/settings/SettingsPage.tsx
|
||||
- tauri-app/src/features/settings/SettingsPage.css
|
||||
autonomous: true
|
||||
requirements: [UI-03]
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "Settings page left nav panel uses Manus surface color (#1E1E1E) and correct border color (#262626)"
|
||||
- "Settings cards/sections use Manus elevated color (#262626) background"
|
||||
- "Section titles use Manus primary text (#F3F4F6), descriptions use secondary text (#9CA3AF)"
|
||||
- "Two-panel layout is preserved and fully functional"
|
||||
artifacts:
|
||||
- path: "tauri-app/src/features/settings/SettingsPage.css"
|
||||
provides: "Updated sp-nav, sp-card, sp-section CSS with Manus tokens"
|
||||
contains: "var(--manus-surface)"
|
||||
- path: "tauri-app/src/features/settings/SettingsPage.tsx"
|
||||
provides: "SettingsPage with Manus Tailwind token classes applied"
|
||||
key_links:
|
||||
- from: "tauri-app/src/features/settings/SettingsPage.css"
|
||||
to: "tauri-app/src/index.css"
|
||||
via: "var(--manus-surface), var(--manus-elevated), var(--manus-tx), var(--manus-tx2)"
|
||||
pattern: "var\\(--manus-"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Apply Manus design tokens to the Settings page: update the left-nav panel, card/section backgrounds, and text colors while preserving the existing two-panel layout.
|
||||
|
||||
Purpose: Visual consistency — Settings must match the chat UI's Manus dark theme.
|
||||
Output: Updated SettingsPage.css (sp-nav, sp-card, sp-section selectors) and SettingsPage.tsx (Tailwind token classes on inline-styled elements). The --manus-* CSS vars (created in plan 06-02) are the token source.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.config/opencode/get-shit-done/workflows/execute-plan.md
|
||||
@$HOME/.config/opencode/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/phases/06-chat-ui-redesign/06-RESEARCH.md
|
||||
@.planning/phases/06-chat-ui-redesign/06-01-SUMMARY.md
|
||||
|
||||
@tauri-app/src/features/settings/SettingsPage.tsx
|
||||
@tauri-app/src/features/settings/SettingsPage.css
|
||||
@tauri-app/src/index.css
|
||||
</context>
|
||||
|
||||
<interfaces>
|
||||
<!-- Key CSS classes used in SettingsPage. Executor targets these. -->
|
||||
|
||||
SettingsPage BEM class mapping to update (from SettingsPage.css):
|
||||
```
|
||||
.sp-nav → left panel container → bg: var(--manus-surface) border: var(--manus-elevated)
|
||||
.sp-nav-item → nav list items → text: var(--manus-tx2) hover bg: var(--manus-elevated)
|
||||
.sp-nav-item.active → active nav item → text: var(--manus-tx) bg: var(--manus-elevated)
|
||||
.sp-card → content cards → bg: var(--manus-elevated) border: var(--manus-hover)
|
||||
.sp-section → section wrappers → no change needed (inherit)
|
||||
.sp-section-title → section headings → color: var(--manus-tx)
|
||||
.sp-section-desc → section descriptions → color: var(--manus-tx2)
|
||||
.sp-label → field labels → color: var(--manus-tx2)
|
||||
.sp-input → text inputs → bg: var(--manus-surface) border: var(--manus-elevated) color: var(--manus-tx)
|
||||
.sp-select → select elements → bg: var(--manus-surface) border: var(--manus-elevated) color: var(--manus-tx)
|
||||
.sp-page → full page container → bg: var(--bg) [already set via --bg]
|
||||
```
|
||||
|
||||
Manus design tokens available after plan 06-02:
|
||||
```css
|
||||
var(--manus-base): #171717 /* page bg */
|
||||
var(--manus-surface): #1E1E1E /* nav, inputs, cards bg */
|
||||
var(--manus-elevated): #262626 /* card bg, borders */
|
||||
var(--manus-hover): #333333 /* hover states, borders on cards */
|
||||
var(--manus-tx): #F3F4F6 /* primary text */
|
||||
var(--manus-tx2): #9CA3AF /* secondary text, labels */
|
||||
var(--manus-tx3): #52525B /* muted text */
|
||||
var(--manus-blue): #3B82F6 /* accent */
|
||||
```
|
||||
|
||||
SettingsPage.tsx — inline Tailwind patterns (lines ~571-644 already use Tailwind):
|
||||
- HF search area uses classes like `flex`, `gap-2`, `text-sm` — extend these with manus token classes
|
||||
- Nav items in TSX that use inline styles — switch to `className` with manus token names
|
||||
</interfaces>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Update SettingsPage.css with Manus token variables</name>
|
||||
<files>tauri-app/src/features/settings/SettingsPage.css</files>
|
||||
<action>
|
||||
Read `SettingsPage.css` fully, then replace hardcoded hex values for the key class groups with Manus CSS vars. Do NOT restructure the CSS — only update background, border, and color property values. Target classes:
|
||||
|
||||
**Left nav panel:**
|
||||
```css
|
||||
.sp-nav {
|
||||
background: var(--manus-surface); /* was hardcoded bg */
|
||||
border-right: 1px solid var(--manus-elevated);
|
||||
}
|
||||
.sp-nav-item {
|
||||
color: var(--manus-tx2);
|
||||
}
|
||||
.sp-nav-item:hover {
|
||||
background: var(--manus-elevated);
|
||||
color: var(--manus-tx);
|
||||
}
|
||||
.sp-nav-item.active, .sp-nav-item[data-active="true"] {
|
||||
background: var(--manus-elevated);
|
||||
color: var(--manus-tx);
|
||||
}
|
||||
```
|
||||
|
||||
**Content cards:**
|
||||
```css
|
||||
.sp-card {
|
||||
background: var(--manus-elevated);
|
||||
border: 1px solid var(--manus-hover);
|
||||
}
|
||||
```
|
||||
|
||||
**Section text:**
|
||||
```css
|
||||
.sp-section-title {
|
||||
color: var(--manus-tx);
|
||||
}
|
||||
.sp-section-desc {
|
||||
color: var(--manus-tx2);
|
||||
}
|
||||
.sp-label {
|
||||
color: var(--manus-tx2);
|
||||
}
|
||||
```
|
||||
|
||||
**Form fields:**
|
||||
```css
|
||||
.sp-input, .sp-select {
|
||||
background: var(--manus-surface);
|
||||
border-color: var(--manus-elevated);
|
||||
color: var(--manus-tx);
|
||||
}
|
||||
.sp-input:focus, .sp-select:focus {
|
||||
border-color: var(--manus-blue);
|
||||
outline: none;
|
||||
}
|
||||
```
|
||||
|
||||
**Page container:**
|
||||
```css
|
||||
.sp-page {
|
||||
background: var(--bg); /* picks up updated #171717 */
|
||||
}
|
||||
```
|
||||
|
||||
Strategy: Read each targeted selector's current rules, replace ONLY the `background`, `border`, `color` values — keep all padding, margin, flex, font-size, and other layout properties exactly as-is. If a property uses `var(--bg)` or `var(--text)` already (and those were updated in plan 06-02), it will inherit the correct Manus value automatically — no change needed for those.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd tauri-app && npm run build 2>&1 | grep -E "error" | head -10</automated>
|
||||
</verify>
|
||||
<done>SettingsPage.css updated — .sp-nav uses var(--manus-surface), .sp-card uses var(--manus-elevated), text uses var(--manus-tx) / var(--manus-tx2). No layout changes.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Update SettingsPage.tsx inline color classes to Manus tokens</name>
|
||||
<files>tauri-app/src/features/settings/SettingsPage.tsx</files>
|
||||
<action>
|
||||
Read `SettingsPage.tsx`. Find all locations where color or background classes are applied inline in JSX as Tailwind utilities or inline style attributes — these should use Manus token Tailwind classes (added in plan 06-02).
|
||||
|
||||
**Specific replacements:**
|
||||
1. Any `bg-[#0d1115]` or `bg-[#12171d]` or `bg-[#171d24]` → replace with `bg-manus-surface` or `bg-manus-elevated` as appropriate for the element role (nav bg = surface, card bg = elevated).
|
||||
2. Any `text-[#a0a9b4]` or `text-gray-400` used for labels/descriptions → `text-manus-tx2`
|
||||
3. Any `text-[#f2f4f7]` or `text-white` used for primary content text → `text-manus-tx`
|
||||
4. Any `border-[#1e252d]` or similar border colors → `border-manus-elevated`
|
||||
5. HF search area (lines ~571-644): If using raw hex Tailwind classes, switch to manus token versions
|
||||
|
||||
**Do NOT change:**
|
||||
- Any `className` attributes that already use the existing `c-*` Tailwind token names (they inherit via CSS vars updated in plan 06-02)
|
||||
- Layout properties (flex, grid, padding, gap, margin, width, height)
|
||||
- Component structure, logic, or event handlers
|
||||
- The `.sp-*` BEM class names (those are handled in Task 1 via CSS)
|
||||
- Any dynamic or conditional class logic — preserve as-is
|
||||
|
||||
If SettingsPage.tsx has very few inline hex classes (the RESEARCH notes it mostly uses `.sp-*` BEM classes), this task may be small. Confirm by reading the file — if all coloring is done via `.sp-*` CSS classes (already handled in Task 1), this task only needs to verify correctness and make no changes. Still create the SUMMARY confirming the audit.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd tauri-app && npm run build 2>&1 | tail -10</automated>
|
||||
</verify>
|
||||
<done>TypeScript build passes. SettingsPage.tsx uses Manus token classes or inherits via updated CSS vars. No hardcoded hex colors for backgrounds/text remain in inline JSX.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
- `npm run build` passes clean
|
||||
- SettingsPage.css `.sp-nav` uses `var(--manus-surface)` for background
|
||||
- SettingsPage.css `.sp-card` uses `var(--manus-elevated)` for background
|
||||
- SettingsPage.css `.sp-section-title` uses `var(--manus-tx)` for color
|
||||
- Two-panel layout is visually intact (no layout regressions)
|
||||
- Settings page accessible and all sections navigable
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Settings page left nav is #1E1E1E (Manus surface), not navy-black
|
||||
- Cards/sections are #262626 (Manus elevated)
|
||||
- Text hierarchy is correct: titles #F3F4F6, labels/descriptions #9CA3AF
|
||||
- All form inputs, selects, and buttons remain functional
|
||||
- Build passes clean
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/06-chat-ui-redesign/06-03-SUMMARY.md`
|
||||
</output>
|
||||
Reference in new issue
Block a user