From d413ad75607bcf5dd8b853486c76fc8572b2a473 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 9 Feb 2026 03:45:42 +0800 Subject: [PATCH] feat: add text size setting (S / M / L / XL) --- .../prompt-kit/code-block/index.tsx | 9 ++++--- apps/webclaw/src/hooks/use-chat-settings.ts | 10 +++++++ .../screens/chat/components/message-item.tsx | 4 ++- .../chat/components/settings-dialog.tsx | 27 ++++++++++++++++++- 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/apps/webclaw/src/components/prompt-kit/code-block/index.tsx b/apps/webclaw/src/components/prompt-kit/code-block/index.tsx index 10dab87..0e0d5b5 100644 --- a/apps/webclaw/src/components/prompt-kit/code-block/index.tsx +++ b/apps/webclaw/src/components/prompt-kit/code-block/index.tsx @@ -35,7 +35,7 @@ import langTypescript from '@shikijs/langs/typescript' import langTsx from '@shikijs/langs/tsx' import langXml from '@shikijs/langs/xml' import langYaml from '@shikijs/langs/yaml' -import { useResolvedTheme } from '@/hooks/use-chat-settings' +import { useResolvedTheme, useChatSettingsStore, TEXT_SIZE_CLASSES } from '@/hooks/use-chat-settings' import { cn } from '@/lib/utils' import { Button } from '@/components/ui/button' import { formatLanguageName, normalizeLanguage, resolveLanguage } from './utils' @@ -97,6 +97,8 @@ export function CodeBlock({ className, }: CodeBlockProps) { const resolvedTheme = useResolvedTheme() + const textSize = useChatSettingsStore((s) => s.settings.textSize) + const codeSizeClass = TEXT_SIZE_CLASSES[textSize] const [copied, setCopied] = useState(false) const [html, setHtml] = useState(null) const [resolvedLanguage, setResolvedLanguage] = useState('text') @@ -179,7 +181,8 @@ export function CodeBlock({ {html ? (
pre]:overflow-x-auto', + codeSizeClass, + 'text-primary-900 [&>pre]:overflow-x-auto', isSingleLine ? '[&>pre]:whitespace-pre [&>pre]:px-3 [&>pre]:py-2' : '[&>pre]:px-3 [&>pre]:py-3', @@ -189,7 +192,7 @@ export function CodeBlock({ ) : (
diff --git a/apps/webclaw/src/hooks/use-chat-settings.ts b/apps/webclaw/src/hooks/use-chat-settings.ts
index d10e4bc..c8a5be6 100644
--- a/apps/webclaw/src/hooks/use-chat-settings.ts
+++ b/apps/webclaw/src/hooks/use-chat-settings.ts
@@ -3,11 +3,20 @@ import { create } from 'zustand'
 import { persist } from 'zustand/middleware'
 
 export type ThemeMode = 'system' | 'light' | 'dark'
+export type TextSize = 'sm' | 'md' | 'lg' | 'xl'
+
+export const TEXT_SIZE_CLASSES: Record = {
+  sm: 'text-sm',
+  md: 'text-base',
+  lg: 'text-lg',
+  xl: 'text-xl',
+}
 
 export type ChatSettings = {
   showToolMessages: boolean
   showReasoningBlocks: boolean
   theme: ThemeMode
+  textSize: TextSize
 }
 
 type ChatSettingsState = {
@@ -22,6 +31,7 @@ export const useChatSettingsStore = create()(
         showToolMessages: true,
         showReasoningBlocks: true,
         theme: 'system',
+        textSize: 'md',
       },
       updateSettings: (updates) =>
         set((state) => ({
diff --git a/apps/webclaw/src/screens/chat/components/message-item.tsx b/apps/webclaw/src/screens/chat/components/message-item.tsx
index 310c18e..907e5ce 100644
--- a/apps/webclaw/src/screens/chat/components/message-item.tsx
+++ b/apps/webclaw/src/screens/chat/components/message-item.tsx
@@ -10,7 +10,7 @@ import type { ToolPart } from '@/components/prompt-kit/tool'
 import { Message, MessageContent } from '@/components/prompt-kit/message'
 import { Thinking } from '@/components/prompt-kit/thinking'
 import { Tool } from '@/components/prompt-kit/tool'
-import { useChatSettings } from '@/hooks/use-chat-settings'
+import { useChatSettings, TEXT_SIZE_CLASSES } from '@/hooks/use-chat-settings'
 import { cn } from '@/lib/utils'
 
 type MessageItemProps = {
@@ -176,6 +176,7 @@ function MessageItemComponent({
   const images = imagesFromMessage(message)
   const isUser = role === 'user'
   const timestamp = getMessageTimestamp(message)
+  const textSizeClass = TEXT_SIZE_CLASSES[settings.textSize]
 
   // Get tool calls from this message (for assistant messages)
   const toolCalls = role === 'assistant' ? getToolCallsFromMessage(message) : []
@@ -221,6 +222,7 @@ function MessageItemComponent({
           markdown={!isUser}
           className={cn(
             'text-primary-900',
+            textSizeClass,
             !isUser
               ? 'bg-transparent w-full'
               : 'bg-primary-100 px-4 py-2.5 max-w-[85%]',
diff --git a/apps/webclaw/src/screens/chat/components/settings-dialog.tsx b/apps/webclaw/src/screens/chat/components/settings-dialog.tsx
index 1bc15d8..e41f0d2 100644
--- a/apps/webclaw/src/screens/chat/components/settings-dialog.tsx
+++ b/apps/webclaw/src/screens/chat/components/settings-dialog.tsx
@@ -16,7 +16,7 @@ import {
 import { Switch } from '@/components/ui/switch'
 import { Tabs, TabsList, TabsTab } from '@/components/ui/tabs'
 import { useChatSettings } from '@/hooks/use-chat-settings'
-import type { ThemeMode } from '@/hooks/use-chat-settings'
+import type { ThemeMode, TextSize } from '@/hooks/use-chat-settings'
 import { Button } from '@/components/ui/button'
 
 type SettingsSectionProps = {
@@ -75,6 +75,12 @@ export function SettingsDialog({
     { value: 'light', label: 'Light', icon: Sun01Icon },
     { value: 'dark', label: 'Dark', icon: Moon01Icon },
   ] as const
+  const textSizeOptions = [
+    { value: 'sm', label: 'S' },
+    { value: 'md', label: 'M' },
+    { value: 'lg', label: 'L' },
+    { value: 'xl', label: 'XL' },
+  ] as const
   function applyTheme(theme: ThemeMode) {
     if (typeof document === 'undefined') return
     const root = document.documentElement
@@ -151,6 +157,25 @@ export function SettingsDialog({
                 
               
             
+            
+               {
+                  updateSettings({ textSize: value as TextSize })
+                }}
+              >
+                
+                  {textSizeOptions.map((option) => (
+                    
+                      {option.label}
+                    
+                  ))}
+                
+              
+