From d2ddb07a0fb767890696f7fa5428810bdde7370a Mon Sep 17 00:00:00 2001 From: tianma-if Date: Wed, 30 Sep 2026 19:34:20 +0800 Subject: [PATCH] fix(web): cycle rich text and Markdown from one toolbar button The two view icons were the same choice. One button now switches between them, and the tooltip names the mode the click will open. --- apps/web/src/components/EditorToolbar.tsx | 73 ++++++++----------- .../MemoEditorHeaderActions.test.mjs | 7 ++ packages/shared/src/i18n/en-US.ts | 1 - packages/shared/src/i18n/ja.ts | 1 - packages/shared/src/i18n/zh-CN.ts | 1 - 5 files changed, 36 insertions(+), 47 deletions(-) diff --git a/apps/web/src/components/EditorToolbar.tsx b/apps/web/src/components/EditorToolbar.tsx index 260d4bef..65ee5276 100644 --- a/apps/web/src/components/EditorToolbar.tsx +++ b/apps/web/src/components/EditorToolbar.tsx @@ -61,12 +61,14 @@ const EditorToolbarButton = ({ children, disabled = false, onClick, + shortcutLabel, title, }: { active?: boolean; children: ReactNode; disabled?: boolean; onClick: () => void; + shortcutLabel?: string | null; title: string; }) => ( @@ -88,7 +90,16 @@ const EditorToolbarButton = ({ {children} - {title} + + {shortcutLabel ? ( + <> + {title} + + {shortcutLabel} + + + ) : title} + ); @@ -221,6 +232,8 @@ export const EditorToolbar = ({ : "plaintext"; const activeEditorView = onEditorViewChange ? editorView : markdownMode ? "markdown" : "rich"; const showFormattingTools = activeEditorView === "rich"; + const nextEditorViewMode = EDITOR_VIEW_MODES[activeEditorView === "rich" ? 1 : 0]; + const canCycleEditorView = Boolean(onEditorViewChange || onMarkdownModeChange); useEffect(() => { const controls = controlsRef.current; @@ -328,50 +341,22 @@ export const EditorToolbar = ({ !expanded && MEMO_EDITOR_TOOLBAR_COLLAPSED_CLASS_NAME )} > - {onEditorViewChange ? ( + {canCycleEditorView ? ( <> -
- {EDITOR_VIEW_MODES.map((mode) => ( - onEditorViewChange(mode.value)} - > - - - ))} -
- - - ) : onMarkdownModeChange ? ( - <> - - - - - - {markdownMode ? t("editorToolbar.richText") : t("editorToolbar.markdown")} - {markdownModeShortcutLabel && ( - - {markdownModeShortcutLabel} - - )} - - + { + if (onEditorViewChange) { + onEditorViewChange(nextEditorViewMode.value); + return; + } + onMarkdownModeChange?.(); + }} + > + + ) : null} diff --git a/apps/web/src/components/MemoEditorHeaderActions.test.mjs b/apps/web/src/components/MemoEditorHeaderActions.test.mjs index b4f0a261..bfe434ab 100644 --- a/apps/web/src/components/MemoEditorHeaderActions.test.mjs +++ b/apps/web/src/components/MemoEditorHeaderActions.test.mjs @@ -76,6 +76,13 @@ describe("shared memo editor header actions", () => { expect(densitySource).not.toContain("min-[1600px]:flex"); }); + test("cycles rich text and markdown from one toolbar button", () => { + expect(editorToolbarSource).toContain("const nextEditorViewMode = EDITOR_VIEW_MODES[activeEditorView === \"rich\" ? 1 : 0]"); + expect(editorToolbarSource).toContain("onEditorViewChange(nextEditorViewMode.value)"); + expect(editorToolbarSource).not.toContain("EDITOR_VIEW_MODES.map"); + expect(editorToolbarSource).not.toContain('t("editorToolbar.viewMode")'); + }); + test("aligns the note title, notebook row, and article on one reading gutter", () => { expect(editorSource).toContain("MEMO_EDITOR_READING_GUTTER_CLASS_NAME"); expect(densitySource).toContain('px-[var(--editor-reading-gutter)]'); diff --git a/packages/shared/src/i18n/en-US.ts b/packages/shared/src/i18n/en-US.ts index f9e63a3f..7b8b4451 100644 --- a/packages/shared/src/i18n/en-US.ts +++ b/packages/shared/src/i18n/en-US.ts @@ -2259,7 +2259,6 @@ export const enUS = { deleteTable: "Delete table", markdown: "Switch to Markdown source", richText: "Switch to rich text", - viewMode: "Note view", appearance: "Appearance and style", blockStyle: "Paragraph style", markdownSource: "Markdown source", diff --git a/packages/shared/src/i18n/ja.ts b/packages/shared/src/i18n/ja.ts index c0b1242b..33a7d166 100644 --- a/packages/shared/src/i18n/ja.ts +++ b/packages/shared/src/i18n/ja.ts @@ -2259,7 +2259,6 @@ export const ja = { deleteTable: "表を削除", markdown: "Markdown ソースに切り替え", richText: "リッチテキストに切り替え", - viewMode: "ノートの表示", appearance: "外観とスタイル", blockStyle: "段落スタイル", markdownSource: "Markdown ソース", diff --git a/packages/shared/src/i18n/zh-CN.ts b/packages/shared/src/i18n/zh-CN.ts index d46ea586..2b0854d7 100644 --- a/packages/shared/src/i18n/zh-CN.ts +++ b/packages/shared/src/i18n/zh-CN.ts @@ -2257,7 +2257,6 @@ export const zhCN = { deleteTable: "删除表格", markdown: "切换到 Markdown 源码", richText: "切换到富文本编辑", - viewMode: "笔记视图", appearance: "外观与样式", blockStyle: "段落样式", markdownSource: "Markdown 源码",