Skip to content

Commit f8a3e01

Browse files
committed
Enhance suggestion menu behavior
1 parent 1180131 commit f8a3e01

File tree

2 files changed

+36
-16
lines changed

2 files changed

+36
-16
lines changed

packages/editor/src/extensions/slashCommand.tsx

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ReactRenderer, useCurrentEditor } from "@tiptap/react";
44
import { DOMOutputSpec, Node as ProseMirrorNode } from "@tiptap/pm/model"
55
import { PluginKey } from "@tiptap/pm/state"
66
import Suggestion, { SuggestionOptions } from "@tiptap/suggestion";
7-
import { computePosition, offset, flip, shift, autoUpdate } from "@floating-ui/dom";
7+
import { autoUpdate, computePosition, flip, offset, shift } from "@floating-ui/dom";
88

99
import {
1010
AutoFixHighIcon,
@@ -312,7 +312,7 @@ export const suggestion = (ref: React.MutableRefObject<any>, {
312312
({
313313
items: ({ query }) => {
314314
const availableSuggestionItems = [...suggestionItems];
315-
if ( aiController) {
315+
if (aiController) {
316316
availableSuggestionItems.push(autocompleteSuggestionItem)
317317
}
318318

@@ -347,6 +347,7 @@ export const suggestion = (ref: React.MutableRefObject<any>, {
347347

348348
// Create floating container
349349
containerEl = document.createElement("div");
350+
containerEl.setAttribute("data-suggestion-menu", "true");
350351
containerEl.style.position = "fixed";
351352
containerEl.style.left = "0px";
352353
containerEl.style.top = "0px";
@@ -366,7 +367,10 @@ export const suggestion = (ref: React.MutableRefObject<any>, {
366367
placement: "bottom-start",
367368
middleware: [offset(4), flip(), shift()],
368369
strategy: "fixed"
369-
}).then(({ x, y }) => {
370+
}).then(({
371+
x,
372+
y
373+
}) => {
370374
Object.assign(containerEl!.style, {
371375
left: `${x}px`,
372376
top: `${y}px`,
@@ -390,7 +394,10 @@ export const suggestion = (ref: React.MutableRefObject<any>, {
390394
placement: "bottom-start",
391395
middleware: [offset(4), flip(), shift()],
392396
strategy: "fixed"
393-
}).then(({ x, y }) => {
397+
}).then(({
398+
x,
399+
y
400+
}) => {
394401
Object.assign(containerEl!.style, {
395402
left: `${x}px`,
396403
top: `${y}px`,
@@ -402,7 +409,8 @@ export const suggestion = (ref: React.MutableRefObject<any>, {
402409
onKeyDown(props) {
403410
if (props.event.key === "Escape") {
404411
props.event.preventDefault();
405-
return true
412+
props.event.stopPropagation();
413+
return false
406414
}
407415

408416
return component.ref?.onKeyDown(props)
@@ -433,8 +441,10 @@ const CommandList = forwardRef((props: {
433441
const [selectedIndex, setSelectedIndex] = useState(0);
434442

435443
const { editor } = useCurrentEditor();
436-
const selectItem = (item?: SuggestionItem) => {
444+
const selectItem = (item?: SuggestionItem, event?: React.MouseEvent) => {
437445
if (!editor) return;
446+
event?.preventDefault();
447+
event?.stopPropagation();
438448
item?.command?.({
439449
editor,
440450
range: props.range,
@@ -497,7 +507,8 @@ const CommandList = forwardRef((props: {
497507
if (!el) return;
498508
itemRefs.current[index] = el;
499509
}}
500-
onClick={() => selectItem(item)}
510+
onMouseDown={(e) => e.preventDefault()}
511+
onClick={(e) => selectItem(item, e)}
501512
tabIndex={index === selectedIndex ? 0 : -1}
502513
aria-selected={index === selectedIndex}
503514
className={cls("flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm hover:bg-blue-50 hover:dark:bg-surface-700 aria-selected:bg-blue-50 aria-selected:dark:bg-surface-700",
@@ -524,7 +535,6 @@ const CommandList = forwardRef((props: {
524535
});
525536
CommandList.displayName = "CommandList";
526537

527-
528538
const autocompleteSuggestionItem: SuggestionItem = {
529539
title: "Autocomplete",
530540
description: "Add text based on the context.",

packages/firecms_core/src/core/SideDialogs.tsx

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback, useContext, useEffect, useRef, useState } from "react";
1+
import React, { useContext, useEffect, useState } from "react";
22
import { useSideDialogsController } from "../hooks";
33
import { SideDialogPanelProps } from "../types";
44
import { Sheet } from "@firecms/ui";
@@ -61,15 +61,15 @@ export function SideDialogs() {
6161
<SideDialogView
6262
key={`side_dialog_${index}`}
6363
panel={panel}
64-
offsetPosition={sidePanels.length - index - 1}/>)
64+
offsetPosition={sidePanels.length - index - 1} />)
6565
}
6666
</>;
6767
}
6868

6969
function SideDialogView({
70-
offsetPosition,
71-
panel
72-
}: {
70+
offsetPosition,
71+
panel
72+
}: {
7373
offsetPosition: number,
7474
panel?: SideDialogPanelProps
7575
}) {
@@ -134,7 +134,17 @@ function SideDialogView({
134134

135135
<Sheet
136136
open={Boolean(panel)}
137-
onOpenChange={(open) => !open && onCloseRequest()}
137+
onOpenChange={(open) => {
138+
if (!open) {
139+
// Check if any suggestion menu (e.g., slash command) is visible in DOM
140+
const suggestionMenu = document.querySelector("[data-suggestion-menu=\"true\"]");
141+
if (suggestionMenu && window.getComputedStyle(suggestionMenu).visibility !== "hidden") {
142+
// Don't close the sheet if a suggestion menu is visible
143+
return;
144+
}
145+
onCloseRequest();
146+
}
147+
}}
138148
title={"Side dialog " + panel?.key}
139149
>
140150
{panel &&
@@ -150,15 +160,15 @@ function SideDialogView({
150160
</ErrorBoundary>
151161
</div>}
152162

153-
{!panel && <div style={{ width }}/>}
163+
{!panel && <div style={{ width }} />}
154164

155165
</Sheet>
156166

157167
<UnsavedChangesDialog
158168
open={drawerCloseRequested}
159169
handleOk={drawerCloseRequested ? handleDrawerCloseOk : handleNavigationOk}
160170
handleCancel={drawerCloseRequested ? handleDrawerCloseCancel : handleNavigationCancel}
161-
body={blockedNavigationMessage}/>
171+
body={blockedNavigationMessage} />
162172

163173
</SideDialogContext.Provider>
164174

0 commit comments

Comments
 (0)