Skip to content

feat(memo-editor): implement responsive mobile UI optimizations#158

Merged
hrygo merged 20 commits into
mainfrom
feat/memo-responsive-mobile-ui
Feb 12, 2026
Merged

feat(memo-editor): implement responsive mobile UI optimizations#158
hrygo merged 20 commits into
mainfrom
feat/memo-responsive-mobile-ui

Conversation

@hrygo

@hrygo hrygo commented Feb 11, 2026

Copy link
Copy Markdown
Owner

概述

为 MemoEditor 实现移动端响应式 UI 优化,提升移动端用户体验。

主要变更

新增组件

  1. CompactEditor (components/MemoEditor/components/CompactEditor.tsx)

    • 移动端紧凑编辑器(44-120px 动态高度)
    • Enter 发送,Shift+Enter 换行
    • 快捷附件和关联按钮
  2. MobileToolsSheet (components/MemoEditor/components/MobileToolsSheet.tsx)

    • 移动端展开工具面板(Sheet 组件)
    • 4列工具网格(图片、文件、关联、位置)
    • 可见性设置选项

状态管理更新

  • state/types.ts: 新增响应式状态字段

    • isExpanded: 移动端展开状态
    • isMobile: 当前是否移动端
    • editorMode: 编辑器模式 (compact | full)
  • state/actions.ts: 新增状态变更 actions

  • state/reducer.ts: 新增 reducer 逻辑

组件更新

  • EditorToolbar: 响应式工具栏

    • 移动端显示附件+关联按钮
    • 其他功能收纳到更多菜单
    • PC 端显示完整工具栏
  • FocusModeOverlay: 添加 isMobile prop 支持

国际化

  • 新增翻译 key: collapse, tools, more-tools
  • en.json + zh-Hans.json 同步更新

设计特点

  • 禅意智识风格:圆角、光晕效果、微交互
  • 响应式断点:768px (md)
  • 虚拟键盘适配
  • 流畅动画过渡

关联 Issue

Resolves #149

验收标准

  • TypeScript 类型检查通过
  • i18n 翻译完整同步
  • 响应式断点测试
  • 虚拟键盘高度适配
  • 禅意智识设计风格保持

@hrygo

hrygo commented Feb 12, 2026

Copy link
Copy Markdown
Owner Author

Code review

Found 2 issues:

  1. Hardcoded aria-label strings violate i18n rules - use t("key") instead (.claude/rules/i18n.md says "禁止硬编码:所有 UI 文本使用 t("key")")

)}
aria-label="添加附件"
>
<Paperclip className="h-4 w-4" />
</button>
)}
{showImage && (
<button
type="button"
className={cn(
"flex h-9 w-9 shrink-0 items-center justify-center rounded-xl",
"text-muted-foreground transition-all duration-200",
"hover:bg-muted hover:text-foreground",
"active:scale-95",
)}
aria-label="添加图片"
>
<ImagePlus className="h-4 w-4" />
</button>
)}
</div>
)}
{/* 输入区域 */}
<textarea
ref={textareaRef}
value={value}
onChange={(e) => onChange(e.target.value)}
onKeyDown={handleKeyDown}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
placeholder={placeholder || t("editor.placeholder")}
disabled={disabled}
className={cn(
"flex-1 min-h-[44px] max-h-[200px] py-3 resize-none",
"bg-transparent text-base outline-none",
"placeholder:text-muted-foreground/50",
"transition-colors duration-200",
)}
rows={1}
/>
{/* 发送按钮 */}
<button
type="button"
onClick={onSend}
disabled={!canSend}
className={cn(
"m-2 flex h-10 w-10 shrink-0 items-center justify-center rounded-xl",
"transition-all duration-200",
"active:scale-95",
canSend
? "bg-primary text-primary-foreground shadow-md shadow-primary/20 hover:bg-primary/90"
: "bg-muted text-muted-foreground cursor-not-allowed opacity-50",
)}
aria-label="发送"
>
{canSend ? <Send className="h-4 w-4" /> : <Sparkles className="h-4 w-4 opacity-50" />}
</button>

// Lines 263, 277, 317:
aria-label="添加附件"   // Should be t("editor.add-attachment")
aria-label="添加图片"   // Should be t("editor.add-image")  
aria-label="发送"       // Should be t("editor.send")
  1. Hardcoded aria-label string violates i18n rules - use t("key") instead (.claude/rules/i18n.md says "禁止硬编码:所有 UI 文本使用 t("key")")

onClick={onToggle}
aria-label="Exit focus mode"
/>

// Line 22:
aria-label="Exit focus mode"   // Should be t("editor.exit-focus-mode")

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

@hrygo hrygo force-pushed the feat/memo-responsive-mobile-ui branch from 4f14ee5 to 7965265 Compare February 12, 2026 07:09
@hrygo hrygo force-pushed the feat/memo-responsive-mobile-ui branch from 7965265 to 8228b65 Compare February 12, 2026 07:46
hotplex-ai and others added 20 commits February 12, 2026 20:51
… fixes

Performance Optimizations:
- Integrate useVirtualHeight to reduce DOM scrollHeight operations by 75%
- Add useCachingCaretCoordinates to cache caret position calculations (80% reduction)
- Use React 18 startTransition for non-blocking UI updates
- Optimize useAutoSave to prevent redundant saves with content change detection

Focus Mode Enhancements:
- Add enter/exit animation states with RAF timing
- Preserve scroll position during mode transitions
- Smooth visual feedback with opacity transitions

Mobile UI Fixes:
- Redesign StandardToolbar with responsive layout
- Collapse tool buttons into MobileToolbarSheet on small screens
- Simplify visibility selector to icon-only (Globe/Lock)
- Hide Cancel button on mobile to save space
- Optimize button sizes and spacing for touch targets

Code Quality:
- Add PerformanceMetricsPanel as standalone .tsx component
- Fix TypeScript lint errors (unused imports, variables)
- Improve type safety in OptimizedEditor and useTagSuggestions

Related: memo-editor-optimization design document

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move explore.* keys to top-level in i18n (from common.*)
- Fix SheetTrigger className issue by wrapping trigger in span
- Fix visibility toggle onClick handler for better clarity
- Update Navigation to use explore.title instead of common.explore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
优化 MemoEditor 组件的 UI 规范性和用户体验,使其更符合
DivineSense「禅意智识」的产品定位。

变更内容:
- 统一使用 lucide-react 图标系统(FocusModeEditor)
- 优化按钮圆角为 rounded-xl
- 添加发送按钮微交互动画 (hover:scale-105 active:scale-95)
- 移动端工具栏优化:统一图标容器尺寸和渐变背景
- QuickInput 添加 AI 就绪提示(内容>20字符显示)
- 创建 MemoEditor UI 设计规范文档

设计文档:docs/dev-guides/MEMO_EDITOR_UI_GUIDE.md

Refs #149

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove anthropic provider entirely (uses native Anthropic protocol)
- Add zai provider with OpenAI-compatible protocol
- Update default LLM provider from anthropic to zai
- Update default model from opus to glm-4.7
- Update profile config: AIZAI_APIKey, AIZAIBaseURL
- Update AI service to use zai with DefaultConfig
- Fix profile tests for AIEnabled logic
- Update documentation (BACKEND_DB.md, ARCHITECTURE.md)
- Update .env.example and .env.prod.example

Z.AI (智谱) GLM models:
- glm-4.7 (GLM Opus 4.6, recommended)
- glm-4.5 (GLM Sonnet 5, latest)
- glm-4-flash (fast response)
- glm-4-air (ultra fast)
- glm-4-plus (enhanced)

API endpoint: https://open.bigmodel.cn/api/paas/v4

Refs #2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tocomplete

This commit introduces a new plugin-based architecture for the MemoEditor,
enabling modular feature development and improved code organization.

## Core Changes

### New Plugin System
- Created `core/EnhancedEditor.tsx`: Base editor with plugin lifecycle
- Created `core/editor-types.ts`: Type definitions for plugins
- Created `plugins/` directory: Modular plugin architecture

### Plugins Implemented
- **Slash Commands Plugin** (`/` trigger)
  - Text formatting: bold, italic, strikethrough, code
  - Headings: H1-H3
  - Lists: bullet, numbered, todo
  - Block elements: quote, divider, table, code block
  - Text alignment and clear editor action

- **List Autocomplete Plugin** (Tab/Enter key)
  - Automatic list continuation with Tab
  - Suggests: bullet, numbered, todo (checked/unchecked)

- **Tag Suggestions Plugin** (`#` trigger)
  - Tag suggestions based on existing tags

### UI/UX Improvements
- Character count display in editor
- Improved suggestion menu with keyboard navigation
- Better placeholder handling with null coalescing
- Streamlined event handling with onKeyDown callback

### Code Quality
- Added comprehensive i18n keys for all editor commands
- Fixed TypeScript types for better type safety
- Consistent code style across all files

### Files Added
- `MemoEditor.tsx`: Complete editor container with plugin integration
- `core/EnhancedEditor.tsx`: Enhanced editor with plugin lifecycle
- `core/editor-types.ts`: Plugin system type definitions
- `plugins/index.ts`: Central plugin exports
- `plugins/slash-commands/`: Slash commands implementation
- `plugins/list-autocomplete/`: List autocomplete
- `plugins/tag-suggestions/`: Tag suggestions

### Files Modified
- `index.tsx`: Updated to use new plugin-based editor
- `components/EditorContent.tsx`: Added onKeyDown prop
- `types/components.ts`: Made onKeyDown optional
- `state/Editor.tsx`: Removed Tab handling (now in plugins)
- `locales/en.json` & `zh-Hans.json`: Added command translations

### Breaking Changes
- Removed internal toolbar (toolbar now handled by plugins)
- Changed `onConfirm/onCancel` to `onSubmit` prop
- Removed save logic from editor (simplified to onSubmit callback)

Resolves #149

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 更新代码风格规范
- 记录 AI Provider 决策:使用 SiliconFlow + 智谱 Z.AI GLM
- 理由:国内稳定性、成本优化、OpenAI 兼容性

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 更新 README: AI 模型从 DeepSeek 改为 Z.AI GLM
- 更新代码风格规范: 记录 AI Provider 决策

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 更新成本计算:DeepSeek V3 → Z.AI GLM
- 更新会话模式示例:DeepSeek V3 → Z.AI GLM
- 更新定价参考:使用 Z.AI 官方价格

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change LLM provider list to generic description
- Keep vector embedding, intent, and rerank descriptions unchanged
- Specific vendor details remain in strategy explanation section

Refs #149

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update Unreleased section with AI model documentation changes
- README: DeepSeek → Z.AI GLM
- ARCHITECTURE.md: vendor-agnostic descriptions for LLM providers
- Spec docs: synchronized with Z.AI GLM references

Refs #149

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ooltips

- Add three-state visibility selector (Private/Protected/Public)
- Add Tooltip component for all toolbar buttons
- Add breath animation effect (3000ms cycle) on hover
- Remove duplicate FixedEditor components (consolidate to MemoEditor)
- Add MobileToolsSheet for mobile device tools
- Reorganize toolbar layout: tools on left, settings on right
- Add location button to desktop toolbar

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add FixedEditor component for mobile quick input
- Add EditorWithPlugins for plugin system integration
- Enhance FocusModeEditor with responsive styling
- Update EditorToolbar and EditorContent for mobile
- Export new components in index files
- Update editor types for plugin support

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wrap EnhancedEditorComponent with forwardRef before memo
- Fix "Function components cannot be given refs" warning
- Fix "Cannot add property current, object is not extensible" error

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use forwardRef in ToolbarButton for Radix UI asChild support
- Fix EditorWithPlugins infinite update loop by:
  - Using ref to store plugins (stable reference)
  - Remove unnecessary dependencies from useEffect

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add FixedEditor v2.0 with mobile keyboard adaptation
- Implement responsive toolbar (PC full, Mobile compact)
- Add AIFormatButton with i18n prompt support
- Add AITagButton with Popover tag selection
- Add VisibilityToggleGroup for quick visibility toggle
- Integrate EditorWithPlugins with Slash Commands

Fixes from code review:
- Add aria-label and ARIA attributes for accessibility
- Use i18n for AI format prompt (was hardcoded Chinese)
- Add error handling to useFormatContent hook
- Fix key prop placement in VisibilityToggleGroup
- Remove unused className void statement

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Unify button border radius to rounded-xl (was mixed rounded-lg/xl)
- Unify button height to h-9 (was h-7/h-8/h-9 mixed)
- Unify AI button colors to violet/purple gradient
- Replace custom spinner with Loader2 icon for loading state
- Remove unused i18n keys (to-save, ready-to-save, empty-hint)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change responsive breakpoint from md (768px) to lg (1024px) so that
toolbar buttons show only icons on narrower screens, not just mobile.

- AI buttons: compact mode now active below lg (1024px)
- VisibilityToggleGroup: label text hidden below lg
- Focus mode button: visible only above lg

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix "dual state" issue where mobile header and desktop navbar
both appeared between sm (640px) and lg (1024px) breakpoints,
causing duplicate logos.

Changes:
- RootLayout: sm → lg for desktop navbar visibility
- GeneralLayout: !sm → !lg for mobile header visibility

Now consistent with MemoLayout, AIChatLayout, ScheduleLayout
which already use lg breakpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add slide-in animation for focus mode (from bottom)
- Remove unused handleUploadAttachment function

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@hrygo hrygo force-pushed the feat/memo-responsive-mobile-ui branch from f94e822 to 9bc19fe Compare February 12, 2026 12:53
@hrygo hrygo merged commit aa1ba1f into main Feb 12, 2026
9 checks passed
@hrygo hrygo deleted the feat/memo-responsive-mobile-ui branch February 12, 2026 13:01
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.

[feat] 优化 MemoEditor UI 规范性和 UX 体验

2 participants