From 0bdc9f98f5a27bbc432fcfb48575d2d4f1d8ba58 Mon Sep 17 00:00:00 2001 From: agent_coder Date: Thu, 2 Jul 2026 03:06:23 +0300 Subject: [PATCH] refactor(editor): widen BubbleMenuItem.icon type, drop IconStress cast (#270 review F1) Icons are rendered only as , so type the field as ComponentType<{ style?; stroke? }> instead of typeof IconBold. stroke is string|number to match Tabler's own prop type, so Tabler icons and the local IconStress both satisfy it without the 'as unknown as' cast. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../components/bubble-menu/bubble-menu.tsx | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/apps/client/src/features/editor/components/bubble-menu/bubble-menu.tsx b/apps/client/src/features/editor/components/bubble-menu/bubble-menu.tsx index d3010831..be7e311e 100644 --- a/apps/client/src/features/editor/components/bubble-menu/bubble-menu.tsx +++ b/apps/client/src/features/editor/components/bubble-menu/bubble-menu.tsx @@ -1,7 +1,14 @@ import { BubbleMenu, BubbleMenuProps } from "@tiptap/react/menus"; import { isNodeSelection, useEditorState } from "@tiptap/react"; import type { Editor } from "@tiptap/react"; -import { FC, useEffect, useRef, useState } from "react"; +import { + ComponentType, + CSSProperties, + FC, + useEffect, + useRef, + useState, +} from "react"; import { IconBold, IconCode, @@ -41,7 +48,7 @@ function IconStress({ stroke = 2, }: { style?: React.CSSProperties; - stroke?: number; + stroke?: string | number; }) { return ( boolean; command: () => void; - icon: typeof IconBold; + // Rendered as , so the real contract is + // just { style?, stroke? }. stroke is string|number to match Tabler's own prop + // type; Tabler icons and the local IconStress both satisfy it (no cast needed). + icon: ComponentType<{ style?: CSSProperties; stroke?: string | number }>; } type EditorBubbleMenuProps = Omit & { @@ -161,9 +171,7 @@ export const EditorBubbleMenu: FC = (props) => { editor.view.dispatch(toggleStressAccent(editor.state)); editor.view.focus(); }, - // Local SVG icon; cast to the Tabler icon type used by the other items. - // It renders with the same { style, stroke } props they are given. - icon: IconStress as unknown as typeof IconBold, + icon: IconStress, }, { name: "Clear formatting",