Skip to content

Commit 6824e34

Browse files
committed
docs: update toolbar docs to reflect component extraction, lucide icons, and new list behavior
1 parent f84f2d8 commit 6824e34

6 files changed

Lines changed: 131 additions & 20 deletions

File tree

docs/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414

1515
- **[AI 集成指南](./ai-integration-guide.md)** - AI功能实现、统一服务层和最佳实践
1616

17+
### 🖼️ UI 组件与交互
18+
19+
- **[Markdown 浮动工具栏](./ui/markdown-floating-toolbar.md)** - 选区触发的 Markdown 格式化工具栏与实现要点
20+
- **[Markdown 工具栏:已知问题与 TODO](./ui/markdown-toolbar-issues.md)**
21+
- **[Focus Mode 文本域](./ui/focus-mode-textarea.md)** - 通过 Portal 和动画实现沉浸式编辑
22+
1723
### 🧩 组件参考
1824

1925
- **[组件 API 参考](./component-api-reference.md)** - 详细的组件接口和使用方法

docs/ai/ai-integration-overview.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,13 @@ if (!apiKeyToUse && process.env.NODE_ENV === 'development') {
134134

135135
#### `AutocompleteTextarea.tsx` 实现说明
136136

137-
`AutocompleteTextarea.tsx` 组件已被完全重构,以使用 `copilot-react-kit` 库,提供了更优越的、光标感知的内联自动补全体验。
137+
`AutocompleteTextarea.tsx` 组件已被完全重构,以使用 `copilot-react-textarea` 库,提供了更优越的、光标感知的内联自动补全体验。
138138

139139
关键实现细节:
140140

141-
- **适配器模式**: 该组件作为 `copilot-react-kit` 的一个"智能包装器"。
141+
- **适配器模式**: 该组件作为 `copilot-react-textarea` 的一个"智能包装器"。
142142
- **"热路径"调用**: 为了将延迟降至最低,该组件**不通过Zustand Store**来发起AI调用,而是直接 `await` 调用 `autocompleteInput` 这个Genkit Flow。
143-
- **防抖机制**: 组件利用 `copilot-react-kit` 原生的 `debounceTime` prop 来控制 AI 建议的请求频率。
143+
- **防抖机制**: 组件利用 `copilot-react-textarea` 原生的 `debounceTime` prop 来控制 AI 建议的请求频率。
144144
- **竞态条件处理**: 使用一个基于 `useRef` 的标志 (`suggestionJustAccepted`) 来解决用户接受建议时可能触发冗余调用的问题。
145145
- **v3 简化**: 随着 v3 改进系统的实施,旧的、基于 `forcedSuggestion` prop 的**双重建议系统已被移除**。组件现在只专注于处理其自身的内联自动补全逻辑,代码更简洁、职责更单一。
146146

docs/component-api-reference.md

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -168,52 +168,81 @@ interface SidebarNavigatorProps {
168168

169169
### 6. AutocompleteTextarea
170170

171-
集成了 `copilot-react-kit` 的、支持 AI 自动补全的 Schema 驱动文本输入组件。它现在可以与 `AutocompleteModelSelector` 配合使用,允许用户选择不同的 AI 模型。
171+
集成了 `copilot-react-textarea` 的、支持 AI 自动补全的 Schema 驱动文本输入组件。它现在可以与 `AutocompleteModelSelector` 配合使用,允许用户选择不同的 AI 模型。
172172

173173
#### Props
174174

175175
```typescript
176176
interface AutocompleteTextareaProps
177177
extends Omit<React.ComponentProps<'textarea'>, 'onChange' | 'value'> {
178-
// --- Core Functionality ---
178+
// --- Core ---
179179
value: string;
180180
onValueChange: (value: string) => void;
181181

182-
// --- AI Context (from parent) ---
182+
// --- AI Context ---
183183
isAutocompleteEnabledGlobally: boolean;
184-
uniqueFieldId: string; // 用于唯一标识textarea实例
184+
autocompleteModel: AutocompleteModel;
185+
sectionId: string;
186+
itemId?: string;
187+
sectionType?: string; // 可选:用于跳过特定字段类型(如 personalDetailsField)
185188

186-
// --- AI Suggestions (from store) ---
187-
forcedSuggestion?: string | null;
188-
onForcedSuggestionAccepted?: () => void;
189-
onForcedSuggestionRejected?: () => void;
189+
// --- 视图 ---
190+
isFocusMode?: boolean;
190191
}
191192
```
192193

193-
_注意:其他用于构建AI上下文的内部props(如`sectionType`, `itemId`, `name`)被视为 `AIFieldWrapper` 的实现细节,在此处省略以简化API文档_
194+
_注意:标准 textarea 属性(如 `id`, `name`, `placeholder`, `rows`, `cols`, `disabled`, `className` 等)作为透传 props 支持,此处省略。强制建议(forced suggestion)相关 props 已移除,行为改为通过对话框承载_
194195

195196
#### 使用示例
196197

197198
```tsx
198-
// 在 AIFieldWrapper.tsx 内部使用
199+
// 在 AIFieldWrapper.tsx 内部使用(节选)
199200
<AutocompleteTextarea
200201
id={uniqueFieldId}
202+
name={fieldId}
203+
sectionType={schemaId}
204+
sectionId={sectionId}
205+
itemId={itemId}
201206
value={value}
202207
onValueChange={handleValueChange}
203208
placeholder={field.uiProps?.placeholder}
204209
isAutocompleteEnabledGlobally={isAutocompleteEnabled}
210+
autocompleteModel={autocompleteModel}
205211
/>
206212
```
207213

208214
#### 特性
209215

210216
-`SchemaRegistry` 驱动的上下文感知自动补全。
211-
- 使用 `copilot-react-kit` 提供高性能的内联建议 ("幽灵文本")。
212-
- "热路径"优化:为降低延迟,直接调用AI服务,不通过Store Action。
213-
- 无缝集成来自Store的"强制建议"(AI改进建议)。
214-
- Tab键接受建议。
215-
- Escape键拒绝强制建议。
216-
- **支持AI模型选择**:与 `AutocompleteModelSelector` 配合使用,允许用户选择不同的自动补全模型。
217+
- 使用 `copilot-react-textarea` 提供高性能的内联建议 ("幽灵文本")。
218+
- "热路径"优化:为降低延迟,直接调用 AI 服务,不通过 Store Action。
219+
- 强制建议改为对话框呈现,不在文本域内联显示。
220+
- Tab 键接受建议(由 CopilotTextarea 处理)。
221+
- **支持 AI 模型选择**:与 `AutocompleteModelSelector` 配合使用,允许用户选择不同的自动补全模型。
222+
223+
#### Markdown 浮动工具栏集成
224+
225+
- 通过 `insideSlateChildren` 插槽向上游 `CopilotTextarea` 注入 Markdown 工具栏(仅在选区非折叠时显示)。
226+
- 下游注入,避免入侵式修改上游 HoveringToolbar(保留 Cmd/Ctrl+K 的 AI 悬浮框)。
227+
- 工具栏通过 React Portal 渲染到 `document.body`,避免被父容器裁剪。
228+
229+
使用示例(节选):
230+
231+
```tsx
232+
<CopilotTextarea
233+
/* 其他 props */
234+
insideSlateChildren={<MarkdownFloatingToolbar />}
235+
/>
236+
```
237+
238+
详见:`docs/ui/markdown-floating-toolbar.md` 与已知问题 `docs/ui/markdown-toolbar-issues.md`
239+
240+
##### 内部实现与扩展插槽
241+
242+
- `insideSlateChildren` 插槽定义:`packages/src/types/base/base-copilot-textarea-props.tsx` 中的 `BaseCopilotTextareaProps.insideSlateChildren?: ReactNode`
243+
- 插槽渲染位置:`packages/src/components/base-copilot-textarea/base-copilot-textarea.tsx` 内,渲染于 Slate Provider 内、`Editable` 之前。
244+
- 向上游转发:`packages/src/components/copilot-textarea/copilot-textarea.tsx` 使用 `...forwardedProps``insideSlateChildren` 透传给 `BaseCopilotTextarea`
245+
- 本项目集成点:`src/components/resume/ui/AutocompleteTextarea.tsx` 通过 `insideSlateChildren={<MarkdownFloatingToolbar />}` 挂载 Toolbar。
217246

218247
---
219248

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Markdown Floating Toolbar
2+
3+
本页介绍在编辑区中基于选区自动显示的 Markdown 浮动工具栏(下称“Toolbar”)的设计、使用方式与实现要点。
4+
5+
## 概要
6+
7+
- 基于 Slate 选区:当选区非折叠时显示。
8+
- 放置策略:始终显示在所选文本“上方”,尽量避免遮挡内容。
9+
- 渲染方式:使用 `createPortal` 将浮层渲染到 `document.body`,避免被父容器裁剪(overflow、z-index 等问题)。
10+
- 操作项:加粗、斜体、行内代码、链接、无序/有序列表(以 Markdown 语法包裹选中文本)。
11+
- 操作项:加粗、斜体、行内代码、链接、无序/有序列表(以 Markdown 语法包裹选中文本);图标使用 `lucide-react` 统一。
12+
- 与 AI 悬浮编辑框(Cmd/Ctrl + K)互不干扰,后者仍由快捷键触发。
13+
14+
实现位置:`src/components/resume/ui/MarkdownFloatingToolbar.tsx`,通过 `insideSlateChildren` 注入到 `src/components/resume/ui/AutocompleteTextarea.tsx`
15+
16+
## 使用方式(当前实现)
17+
18+
当前版本为独立组件 `src/components/resume/ui/MarkdownFloatingToolbar.tsx`,并在 `AutocompleteTextarea` 中通过 `insideSlateChildren={<MarkdownFloatingToolbar />}` 注入,无需额外配置即可生效。
19+
20+
> 说明:若后续有跨模块复用需求,可再迁移至 `src/components/common/` 目录并沉淀公共样式与子组件。
21+
22+
## 关键实现细节
23+
24+
- 选区侦测:通过 `slate-react``useSlate()``useSlateSelection()` 获取编辑器与选区;当 `selection` 存在且 `!Range.isCollapsed(selection)` 时显示。
25+
- 定位与布局:基于原生 `Selection``Range` 进行测量与定位:
26+
- 优先使用 `range.getClientRects()`,选择最靠上的 `rect` 作为锚点;
27+
- 默认显示在选区“上方”,若上方空间不足则翻转到“下方”;
28+
- 以选区中心水平居中,左右做视窗边界夹取;
29+
- 监听 `selectionchange``scroll``resize`,用 `requestAnimationFrame` 进行轻节流重算;
30+
- 通过 `createPortal(..., document.body)` 保证不被父容器裁剪。
31+
32+
同时引入纯文本变换模块 `src/lib/markdownTextTransforms.ts`,避免“吞标点”等问题。
33+
- 文本替换:通过 `Transforms.delete` + `Transforms.insertText` 在原选区处替换为包裹后的 Markdown 文本。
34+
35+
## 与 AI 功能的关系
36+
37+
- 顶层悬浮 AI 编辑框(Hovering Editor/Prompt Box)仍通过快捷键 Cmd/Ctrl + K 显示;
38+
- Toolbar 与其互不干扰:Toolbar 根据选区出现;AI 悬浮框根据快捷键出现;
39+
- 已预留可选的“AI Modify”按钮(默认关闭),点击时会派发 `resume:openHoveringEditor` 自定义事件;如需联动,可在上层监听该事件后打开 Hovering Editor(或在核心包内增加 Event Bridge)。
40+
41+
## 可访问性(A11y)
42+
43+
- 每个按钮具备 `aria-label``title`
44+
- 后续可补充键盘导航(Tab/Shift+Tab)与聚焦样式;
45+
- 可为按钮提供快捷键提示(例如 Ctrl/Cmd + B/I 等)。
46+
47+
## 已知限制与边界
48+
49+
详见《markdown-toolbar-issues.md》。
50+
51+
## 变更记录
52+
53+
- 2025-08-09:抽取为独立组件 `src/components/resume/ui/MarkdownFloatingToolbar.tsx`;统一使用 `lucide-react` 图标;改进定位(`getClientRects` + 翻转 + 夹取 + 事件监听 + rAF);新增纯文本变换模块 `src/lib/markdownTextTransforms.ts`;加入可选的“AI Modify”按钮(默认关闭)。

docs/ui/markdown-toolbar-issues.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Markdown Toolbar - Known Issues & TODOs
2+
3+
以下问题留给下一位 Agent 或未来的我们继续优化:
4+
5+
- [x] 选区与翻转定位改进:已使用 `Range.getClientRects()` 选择最靠上的 rect,默认“上方”显示,空间不足则翻转到“下方”,并做水平居中与视窗边界夹取;监听 `selectionchange`/`scroll`/`resize`,以 `requestAnimationFrame` 轻节流。仍需:多行极端选区与嵌套滚动容器回归验证。
6+
7+
- [x] 图标风格统一:已改为 `lucide-react` 图标。后续如需进一步统一样式,可新增 `src/components/ui/icons.tsx` 进行集中封装(可选)。
8+
9+
- [x] 文本包裹算法(首版优化):新增 `src/lib/markdownTextTransforms.ts`,对加粗/斜体/代码包裹在尾随标点时进行外移处理;链接支持解包与 `prompt` 获取 URL。后续可补充更复杂的边界与单元测试。
10+
11+
- [x] 组件模块化:已抽取为独立文件 `src/components/resume/ui/MarkdownFloatingToolbar.tsx`,并通过 `insideSlateChildren` 注入。公共子组件与样式常量的进一步沉淀可在需要时进行。
12+
13+
- [x] “AI Modify”按钮(可选):已加入可选按钮(默认关闭),点击派发 `resume:openHoveringEditor` 自定义事件;上层可监听后打开 Hovering Editor。为保持解耦,未直接引用内部 Hook。
14+
15+
- [ ] A11y 与快捷键:
16+
- 为 Toolbar 增加键盘导航(Tab/Shift+Tab)与 `aria-pressed` 状态;
17+
- 按钮快捷键(Ctrl/Cmd + B/I/`)与选中状态高亮(检测是否被 Markdown 包裹)。
18+
19+
- [ ] 定位鲁棒性(进一步):已具备基本翻转与夹取。可评估引入 Floating UI/Popper 以覆盖更多边界(如滚动容器嵌套、碰撞避让)。
20+
21+
- [x] 性能与抖动:已通过 `selectionchange`/`scroll`/`resize` + rAF 轻节流,并在隐藏/卸载时移除监听。仍需在长文档场景做压力测试。
22+
23+
> 注:本文件仅记录问题与方案方向,具体实现以代码注释与 PR 说明为准。

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "resume-studio",
3-
"version": "1.2.0",
3+
"version": "1.3.0-alpha.1",
44
"type": "module",
55
"packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748",
66
"private": true,

0 commit comments

Comments
 (0)