Skip to content

Commit

Permalink
fix: don’t initialize tippy on requestAnimationFrame to avoid race co…
Browse files Browse the repository at this point in the history
…nditions (#1820)

Instead of initializting tippy when
the bubble menu and floating menu plugins are initialized,
defer the initialization of tippy to the moment when
the the editor should display the floating or bubble menu

Co-authored-by: Enrique Alcantara <ealcantara@gitlab.com>
  • Loading branch information
enriquecastl and ealcantara-gitlab authored Sep 7, 2021
1 parent 67ce72a commit ca3763d
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 36 deletions.
46 changes: 28 additions & 18 deletions packages/extension-bubble-menu/src/bubble-menu-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export class BubbleMenuView {

public tippy: Instance | undefined

public tippyOptions?: Partial<Props>

public shouldShow: Exclude<BubbleMenuPluginProps['shouldShow'], null> = ({ state, from, to }) => {
const { doc, selection } = state
const { empty } = selection
Expand All @@ -59,7 +61,7 @@ export class BubbleMenuView {
editor,
element,
view,
tippyOptions,
tippyOptions = {},
shouldShow,
}: BubbleMenuViewProps) {
this.editor = editor
Expand All @@ -74,13 +76,10 @@ export class BubbleMenuView {
this.view.dom.addEventListener('dragstart', this.dragstartHandler)
this.editor.on('focus', this.focusHandler)
this.editor.on('blur', this.blurHandler)
this.tippyOptions = tippyOptions
// Detaches menu content from its current parent
this.element.remove()
this.element.style.visibility = 'visible'

// We create tippy asynchronously to make sure that `editor.options.element`
// has already been moved to the right position in the DOM
requestAnimationFrame(() => {
this.createTooltip(tippyOptions)
})
}

mousedownHandler = () => {
Expand Down Expand Up @@ -113,17 +112,26 @@ export class BubbleMenuView {
this.hide()
}

createTooltip(options: Partial<Props> = {}) {
this.tippy = tippy(this.editor.options.element, {
duration: 0,
getReferenceClientRect: null,
content: this.element,
interactive: true,
trigger: 'manual',
placement: 'top',
hideOnClick: 'toggle',
...options,
})
createTooltip() {
if (this.tippy) {
return
}

const { element: editorElement } = this.editor.options

// Wait until editor element is attached to the document
if (editorElement.parentElement) {
this.tippy = tippy(editorElement, {
duration: 0,
getReferenceClientRect: null,
content: this.element,
interactive: true,
trigger: 'manual',
placement: 'top',
hideOnClick: 'toggle',
...this.tippyOptions,
})
}
}

update(view: EditorView, oldState?: EditorState) {
Expand All @@ -135,6 +143,8 @@ export class BubbleMenuView {
return
}

this.createTooltip()

// support for CellSelections
const { ranges } = selection
const from = Math.min(...ranges.map(range => range.$from.pos))
Expand Down
46 changes: 28 additions & 18 deletions packages/extension-floating-menu/src/floating-menu-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ export class FloatingMenuView {

public tippy: Instance | undefined

public tippyOptions?: Partial<Props>

public shouldShow: Exclude<FloatingMenuPluginProps['shouldShow'], null> = ({ state }) => {
const { selection } = state
const { $anchor, empty } = selection
Expand All @@ -50,7 +52,7 @@ export class FloatingMenuView {
editor,
element,
view,
tippyOptions,
tippyOptions = {},
shouldShow,
}: FloatingMenuViewProps) {
this.editor = editor
Expand All @@ -64,13 +66,10 @@ export class FloatingMenuView {
this.element.addEventListener('mousedown', this.mousedownHandler, { capture: true })
this.editor.on('focus', this.focusHandler)
this.editor.on('blur', this.blurHandler)
this.tippyOptions = tippyOptions
// Detaches menu content from its current parent
this.element.remove()
this.element.style.visibility = 'visible'

// We create tippy asynchronously to make sure that `editor.options.element`
// has already been moved to the right position in the DOM
requestAnimationFrame(() => {
this.createTooltip(tippyOptions)
})
}

mousedownHandler = () => {
Expand Down Expand Up @@ -99,17 +98,26 @@ export class FloatingMenuView {
this.hide()
}

createTooltip(options: Partial<Props> = {}) {
this.tippy = tippy(this.editor.options.element, {
duration: 0,
getReferenceClientRect: null,
content: this.element,
interactive: true,
trigger: 'manual',
placement: 'right',
hideOnClick: 'toggle',
...options,
})
createTooltip() {
if (this.tippy) {
return
}

const { element: editorElement } = this.editor.options

// Wait until editor element is attached to the document
if (editorElement.parentElement) {
this.tippy = tippy(editorElement, {
duration: 0,
getReferenceClientRect: null,
content: this.element,
interactive: true,
trigger: 'manual',
placement: 'right',
hideOnClick: 'toggle',
...this.tippyOptions,
})
}
}

update(view: EditorView, oldState?: EditorState) {
Expand All @@ -122,6 +130,8 @@ export class FloatingMenuView {
return
}

this.createTooltip()

const shouldShow = this.shouldShow?.({
editor: this.editor,
view,
Expand Down

0 comments on commit ca3763d

Please sign in to comment.