Commit Graph

24 Commits

Author SHA1 Message Date
Nicolas Varrot
9ef1c8be0d perf: lazy-load highlight.js in ToolCall for better code-splitting
ToolCall.tsx previously imported highlight.js statically, pulling the
entire hljs bundle into the main Chat chunk and preventing Vite from
splitting it into the lazy markdown chunk.

Now hljs is dynamically imported and loaded on first use. This:
- Removes the Vite build warning about mixed static/dynamic imports
- Reduces the Chat chunk by ~1.6 KB
- Consolidates hljs into the lazy markdown chunk
- Renders unhighlighted text instantly, then re-renders with syntax
  highlighting once hljs loads (typically < 100ms)
2026-02-27 21:02:13 +00:00
Nicolas Varrot
9faa5014a6 perf: wrap ToolCall, CodeBlock, ThinkingBlock, ImageBlock in React.memo
Prevents unnecessary re-renders of these frequently rendered child
components when parent message list updates but individual props
haven't changed.
2026-02-22 21:03:31 +00:00
Nicolas Varrot
414e2ccae5 fix: session tooltip click-through, copy buttons stopPropagation, rename spacebar (v1.64.2) 2026-02-15 20:39:28 +00:00
Nicolas Varrot
7606a09ba9 fix: clipboard fallback for insecure contexts, session rename via sessions.patch
- Add copyToClipboard utility with execCommand fallback for HTTP deployments (#76)
- Replace all navigator.clipboard.writeText calls with copyToClipboard
- Session rename now persists server-side via sessions.patch (#78)
- Pass onRename callback from App to Sidebar
2026-02-15 20:07:33 +00:00
Nicolas Varrot
e230f9791f feat: improve accessibility — semantic HTML landmarks, skip-to-content link, ARIA attributes
- Replace div with <main> for primary chat pane (screen reader landmark)
- Replace div with <section> for split pane
- Add skip-to-content link for keyboard navigation (Tab → jump to chat input)
- Add aria-expanded and aria-label to tool call badge buttons
- Add id='chat-input' to textarea for skip link target
- Add i18n keys for new ARIA labels (EN + FR)
2026-02-13 13:28:02 +00:00
Nicolas Varrot
5acc5a820d fix: improve light theme readability for tool badges and user bubbles
- Expose resolvedTheme in ThemeContext for theme-aware rendering
- Tool call badges: darker text colors and higher bg opacity in light theme
- User message bubbles: increased bg opacity and border strength in light theme
- Progress bars and send button already use accent CSS variables (no change needed)

Closes feedback #60
2026-02-13 09:27:42 +00:00
Nicolas Varrot
b783ae181b feat: optimistic message rendering with send status indicators
- User messages appear instantly with 'sending' state (dimmed, clock icon)
- Transitions to 'sent' (checkmark) when server acknowledges
- Shows error state (alert icon, retry visible) if send fails
- Applied to both primary and secondary sessions
2026-02-13 09:12:09 +00:00
Nicolas Varrot
6b0261f9c1 perf: reduce bundle size by using custom highlight.js subset
Replace highlight.js/lib/common (36 languages) with a curated subset
of 16 languages relevant for coding-assistant chat UIs. Both ToolCall
(direct hljs) and ChatMessage (rehype-highlight) now share the same
custom bundle from src/lib/highlight.ts.

Languages included: bash, css, diff, dockerfile, go, ini, javascript,
json, markdown, python, rust, shell, sql, typescript, xml, yaml.

Markdown chunk: 477KB → 336KB (-30%, -45KB gzipped)
2026-02-13 06:11:46 +00:00
Nicolas Varrot
1770e95d0a fix: resolve all ESLint warnings (setState in useEffect)
Suppress 3 react-hooks/set-state-in-effect warnings with targeted
eslint-disable comments. These are intentional patterns:
- ChatInput: restore draft text on session switch
- MessageSearch: reset active index on query change
- ToolCall: sync open state with global collapse/expand toggle

Lint now passes with 0 errors and 0 warnings.
2026-02-13 03:41:39 +00:00
Nicolas Varrot
b60c0ce3c4 fix: migrate all components to theme-aware CSS variables
Replace ~150 hardcoded Tailwind color classes (bg-zinc-*, text-zinc-*,
border-white/*, text-cyan-*, bg-cyan-*) with CSS custom properties
(--pc-*) across all 17 components.

Add @theme block in index.css for Tailwind v4 theme-aware utility
classes (bg-pc-elevated, text-pc-text, border-pc-border, etc.).

Add --pc-hover, --pc-hover-strong, --pc-separator variables per theme
(white/alpha for dark/OLED, black/alpha for light).

Theme switcher (dark/light/OLED) now actually works — all UI elements
respond to theme changes in real-time.

Fixes #55
2026-02-13 00:29:50 +00:00
Nicolas Varrot
73a46f3ba7 fix: resolve all ESLint errors blocking CI releases
- Extract ThemeContext and ToolCollapseContext definitions into separate
  files to satisfy react-refresh/only-export-components rule
- Move useTheme and useToolCollapse hooks to dedicated hook files
- Fix empty catch block in ThemeContext (add comment)
- Replace Date.now() ref in ThinkingIndicator with useState initializer
- Update all imports across components

Closes feedback #58
2026-02-13 00:13:12 +00:00
Nicolas Varrot
b20bf41bf4 feat: theme switcher — dark, light, OLED modes with configurable accent colors
- Add ThemeContext with CSS custom properties for all base colors
- Three theme modes: Dark (default), Light, OLED Black
- Six accent colors: Cyan, Violet, Emerald, Amber, Rose, Blue
- Theme switcher dropdown in header (palette icon)
- Persisted in localStorage
- CSS variables replace hardcoded hex colors in index.css and components
- i18n support (EN/FR) for theme labels
2026-02-12 23:51:01 +00:00
Nicolas Varrot
bd446aa2e6 feat: word-wrap toggle on tool call content blocks
Add a wrap/nowrap toggle button on tool call parameters and results.
Default: word-wrap enabled (pre-wrap + break-words) so content fits
without horizontal scrolling. Click the toggle to switch to nowrap
mode for raw formatting with horizontal scroll.

Closes feedback #41
2026-02-12 23:46:55 +00:00
Nicolas Varrot
2b1ca2d0c8 feat: add collapse/expand all tool calls toggle button
Adds a floating button in the chat area that lets users collapse or expand
all tool call details at once. Useful for long conversations with many tool
calls where scrolling through expanded results is tedious.

- New ToolCollapseContext provides global collapse/expand state
- ToolCall components react to global state changes via version tracking
- Toggle button appears only when conversation has tool calls
- Supports EN/FR i18n
2026-02-12 19:36:53 +00:00
Nicolas Varrot
8ef1b428a3 fix: mobile viewport overflow — prevent horizontal clipping on iPhone
- Add overflow-x: hidden on html/body and max-width: 100vw
- Add overflow-x: hidden on root app container
- Add overflow-x: hidden on chat scroll container
- Make markdown tables scrollable with display: block + overflow-x: auto
- Add overflow-hidden + min-w-0 on expanded tool call content
- Fix tool result summary max-width from max-w-md to max-w-full

Fixes #26
2026-02-12 12:42:20 +00:00
Nicolas Varrot
908dbb4a60 feat: add copy buttons to expanded tool call parameters and results 2026-02-12 11:16:34 +00:00
Nicolas Varrot
693229c14e refactor: replace any types with proper TypeScript types across gateway client, hooks, and components
- Add GatewayMessage and JsonPayload interfaces to gateway.ts
- Type WebSocket message parsing with GatewayMessage instead of any
- Use ReturnType<typeof setTimeout> for timer refs
- Type chat event payload destructuring explicitly
- Add ChatPayloadMessage interface for extractText()
- Replace any casts in loadSessions/loadHistory with typed assertions
- Add str() helper in ToolCall.tsx for safe unknown→string extraction
- Use Extract<MessageBlock, ...> type guards instead of `as any` casts
- Type CodeBlock children prop properly
2026-02-11 21:17:44 +00:00
Nicolas Varrot
72f7d76cc4 feat: add emoji icons to tool call badges
Replace Lucide icons with emojis on tool call badges for better visual
identification:  exec, 🔍 web_search, 📖 read, ✏️ write/edit,
🧠 memory,  cron, 🚀 sessions_spawn, and more.

Also reduces bundle by removing unused Lucide icon imports from ToolCall.

Closes feedback item #15.
2026-02-11 20:25:31 +00:00
Nicolas Varrot
195ad621f7 fix(i18n): use i18n key for 'Parameters' label in tool call expansion
The 'Paramètres' label in ToolCall.tsx was hardcoded in French instead of
using the i18n system. Added tool.parameters key to both EN and FR locales.
2026-02-11 18:56:11 +00:00
Nicolas Varrot
762a5f2026 feat: inline image display with lightbox
- Add image block type for base64 and URL images
- Parse image/image_url blocks from gateway history
- Render images inline in chat messages (rounded, dark-themed)
- Click-to-zoom lightbox with Escape to close
- Markdown images also use the lightbox component
- Detect base64 images in tool results (e.g. Read tool on image files)
- Support png, jpg, gif, webp formats
2026-02-11 17:18:10 +00:00
Nicolas Varrot
9b3aed4adc feat: add runtime language selector in header (EN/FR toggle)
- Add LanguageSelector component with globe icon + cycle button
- Refactor i18n to support reactive locale switching via useSyncExternalStore
- Locale priority: localStorage > VITE_LOCALE > navigator.language > 'en'
- All components now use useT() hook for reactive re-rendering on locale change
- Persists choice to localStorage (key: pinchchat-locale)
- No page reload needed — instant switch
2026-02-11 16:18:22 +00:00
Nicolas Varrot
99b7db9793 feat: add i18n support with VITE_LOCALE env var (en/fr)
- Lightweight i18n system in src/lib/i18n.ts (no external deps)
- All UI strings extracted to translation keys
- English (default) and French locales included
- Set VITE_LOCALE=fr in .env for French UI
- Fallback to English for unknown locales
2026-02-11 13:19:20 +00:00
Nicolas Varrot
3370916931 fix: localize UI to English and add ARIA accessibility attributes
- Replace all French UI strings with English (Connected, Thinking, Result, Send, etc.)
- Add role="log" + aria-live="polite" to chat message area
- Add role="form" + aria-label to message input area
- Add aria-label to sidebar toggle, attach file, send, and textarea
- Add role="banner" to header, role="navigation" to sidebar
- Add role="application" to app root
2026-02-11 12:17:54 +00:00
Nicolas Varrot
1f8ff9ae0a Initial commit — ClawChat v1.0.0 2026-02-11 00:48:43 +00:00