Create custom bubbles

  • Bubbles are pop-up UI elements resembling speech bubbles in comics, featuring a tail pointing at a block and a head containing SVG elements.

  • Custom bubbles can be created by subclassing the Bubble class if the built-in options are insufficient.

  • The bubble's view, consisting of all SVG elements within the head, should be created as children of this.contentContainer for automatic cleanup.

  • The bubble's size must be set using setSize during construction and whenever UI element sizes change to ensure the border properly surrounds the content.

  • When disposing of a bubble, any DOM elements not appended to this.contentContainer and external references need to be manually cleaned up within the dispose method.

A bubble is a pop up UI that looks like a speech bubble you would see in a comic. They have a "tail" that points at a block, and a "head" that contains arbitrary svg elements.

A bubble with the head and the tail labeled

If the built-in bubbles don't work for your use case, you can create a custom bubble by subclassing the Bubble class.

Create the view

A bubble's view is all of the svg elements that live inside the "head" of the bubble. These elements are created inside of the bubble's constructor, and they should be children of the this.contentContainer element so that they get automatically cleaned up when the icon is destroyed.

The Blockly.utils.dom module provides a clean interface for instantiating svgs.

class MyBubble extends Blockly.bubbles.Bubble {
  // See the Blockly.bubbles.Bubble class for information about what these
  // parameters are.
  constructor(workspace, anchor, ownerRect) {
    super(workspace, anchor, ownerRect);

    this.text = Blockly.utils.dom.createSvgElement(
          Blockly.utils.Svg.TEXT,
          {'class': 'my-bubble-class'},
          this.contentContainer);
    const node = Blockly.utils.dom.createTextNode('some text');
    this.text.appendChild(node);
  }
}

Set the size

The bubble's size needs to be set using setSize so that the outer border can properly surround the contents of the bubble. It should be set during construction, and whenever the size of the UI elements change.

constructor(workspace, anchor, ownerRect) {
  // Create the view elements... (see above)

  const bbox = this.text.getBBox();
  this.setSize(
    new Blockly.utils.Size(
      bbox.width + Blockly.bubbles.Bubble.BORDER_WIDTH * 2,
      bbox.height + Blockly.bubbles.Bubble.BORDER_WIDTH * 2,
    ),
    true
  );
}

Dispose of the bubble

Bubbles should clean up any dom elements or external references when they are disposed. By default, anything that is appended to this.contentContainer gets destroyed, but other references need to be manually cleaned up. This should be done within the dispose method.

dispose() {
  super.dispose();

  // Dispose of other references.
  this.myArbitraryReference.dispose();
}