diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/bubble-menu-chrome.ts b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/bubble-menu-chrome.ts new file mode 100644 index 00000000000..b10e143c4ce --- /dev/null +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/bubble-menu-chrome.ts @@ -0,0 +1,9 @@ +/** + * Shared chrome for the editor's selection-driven bubble toolbars — the text formatting bar and the + * table bar. Single source of truth so the two read identically; never re-derive this class string + * per consumer. + */ + +/** The floating toolbar: bordered card, popover layer, with the enter animation. */ +export const BUBBLE_MENU_CLASS = + 'fade-in-0 z-[var(--z-popover)] flex animate-in items-center gap-0.5 rounded-lg border border-[var(--border)] bg-[var(--bg)] p-1 shadow-sm duration-150 ease-out motion-reduce:animate-none' diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/bubble-menu.tsx b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/bubble-menu.tsx index 160657905fe..1da1a6d7caf 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/bubble-menu.tsx +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/bubble-menu.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { Blimp, Bold, @@ -20,6 +20,7 @@ import { PluginKey } from '@tiptap/pm/state' import type { Editor } from '@tiptap/react' import { useEditorState } from '@tiptap/react' import { BubbleMenu } from '@tiptap/react/menus' +import { BUBBLE_MENU_CLASS } from './bubble-menu-chrome' import { applyLink, LinkUrlInput } from './link-editing' import { ToolbarButton, ToolbarDivider } from './toolbar-button' import { useBubbleMenuFloating } from './use-bubble-menu-floating' @@ -181,6 +182,18 @@ export function EditorBubbleMenu({ const { resolveAnchor, appendTo } = useBubbleMenuFloating(editor, scrollContainerRef) + const shouldShow = useCallback( + ({ editor: e, from, to }: { editor: Editor; from: number; to: number }) => { + // Read-only never shows the menu — even mid-link-edit (e.g. a stream starting) — so a link + // can't be applied to a doc that must not mutate. + if (!e.isEditable) return false + if (isEditingLink) return true + if (isPointerDownRef.current) return false + return hasFormattableSelection(e, from, to) + }, + [isEditingLink] + ) + return ( { - // Read-only never shows the menu — even mid-link-edit (e.g. a stream starting) — so a link - // can't be applied to a doc that must not mutate. - if (!e.isEditable) return false - if (isEditingLink) return true - if (isPointerDownRef.current) return false - return hasFormattableSelection(e, from, to) - }} - className='fade-in-0 z-[var(--z-popover)] flex animate-in items-center gap-0.5 rounded-lg border border-[var(--border)] bg-[var(--bg)] p-1 shadow-sm duration-150 ease-out motion-reduce:animate-none' + shouldShow={shouldShow} + className={BUBBLE_MENU_CLASS} > {isEditingLink ? ( <> diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/table-menu.tsx b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/table-menu.tsx index 329fb525b18..66f8849ecd2 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/table-menu.tsx +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/table-menu.tsx @@ -13,6 +13,7 @@ import { PluginKey } from '@tiptap/pm/state' import type { Editor } from '@tiptap/react' import { useEditorState } from '@tiptap/react' import { BubbleMenu } from '@tiptap/react/menus' +import { BUBBLE_MENU_CLASS } from './bubble-menu-chrome' import { ToolbarButton, ToolbarDivider } from './toolbar-button' import { useBubbleMenuFloating } from './use-bubble-menu-floating' @@ -22,6 +23,9 @@ interface TableBubbleMenuProps { scrollContainerRef: React.RefObject } +const shouldShowTableMenu = ({ editor }: { editor: Editor }) => + editor.isEditable && editor.isActive('table') + /** * Floating toolbar shown whenever the selection is inside a table: row/column insert-before/after, * row/column delete, header-row toggle, and delete-table. `@tiptap/extension-table` already exposes @@ -49,8 +53,8 @@ export function TableBubbleMenu({ editor, scrollContainerRef }: TableBubbleMenuP role='toolbar' aria-label='Table editing' updateDelay={0} - shouldShow={({ editor: e }) => e.isEditable && e.isActive('table')} - className='fade-in-0 z-[var(--z-popover)] flex animate-in items-center gap-0.5 rounded-lg border border-[var(--border)] bg-[var(--bg)] p-1 shadow-sm duration-150 ease-out motion-reduce:animate-none' + shouldShow={shouldShowTableMenu} + className={BUBBLE_MENU_CLASS} >