SubGraphExpanderButton design

how can I change the design of the button to remove the default + sign and blue to white background and change it to something of my own?

You can see the definition of the SubGraphExpanderButton in Buttons.js. You can modify that definition as you like and include it in your project.

You can see the definition of the “SubGraphExpanderButton”, and the “Button” that it uses, in

For example, using triangles instead of “+” and “-”, and using simple colors for the button states:

                  "_subGraphExpandedFigure": "TriangleUp",
                  "_subGraphCollapsedFigure": "TriangleDown",
                  "_buttonFillNormal": "white",
                  "_buttonStrokeNormal": "black",
                  "_buttonFillOver": "lightgreen",
                  "_buttonStrokeOver": "green",

for some reason this only works partially for me?
the “over” part works great, but when I try to override the “normal” part it just ignores?
also how do I use my image instead of the + sign (which needs to change based on an attribute i get from the model?)?

The “SubGraphExpanderButton” is designed around a Shape whose Shape.figure is toggled by the value of Group.isSubGraphExpanded.

If you want to use a Picture instead of a Shape, I suggest that you copy and modify the definition of the whole button.

how do I do the actual override of the button? I have the updated template, but how do I tell the group template to use this template for the button instead of the original?

If you have defined a new “CustomSubGraphExpanderButton”, then just use that in your Group template.

Here you go. You just need to provide the two image files.

    go.GraphObject.defineBuilder("SubGraphExpanderImageButton", function(args) {
      var button = /** @type {Panel} */ (
            { "ButtonBorder.spot1": go.Spot.TopLeft, "ButtonBorder.spot2": go.Spot.BottomRight },
            go.GraphObject.make(go.Picture,  // the icon
                name: "ButtonIcon",
                source: "expand.png",
                desiredSize: new go.Size(12, 12)
              // bind the Shape.figure to the Group.isSubGraphExpanded value using this converter:
              new go.Binding("source", "isSubGraphExpanded",
                             function(exp, pict) {
                               var but = pict.panel;
                               return exp ? "collapse.png" : "expand.png";

      // subgraph expand/collapse behavior = function(e, button) {
        var group = button.part;
        if (group instanceof go.Adornment) group = group.adornedPart;
        if (!(group instanceof go.Group)) return;
        var diagram = group.diagram;
        if (diagram === null) return;
        var cmd = diagram.commandHandler;
        if (group.isSubGraphExpanded) {
          if (!cmd.canCollapseSubGraph(group)) return;
        } else {
          if (!cmd.canExpandSubGraph(group)) return;
        e.handled = true;
        if (group.isSubGraphExpanded) {
        } else {

      return button;

The event handler is exactly the same as in the original “SubGraphExpanderButton” definition. The only thing I changed was to replace the Shape with a Picture.

OK, figured it out,
the last issue is “_buttonFillNormal” is ignored for some reason, while “_buttonFillOver” works perfectly. ,
same for stroke
any ideas?

We posted simultaneously.

If you want to use images, you should ignore the standard definition which makes use of a Shape.

thanks, the issue is I have to pass the image in - it’s different for each button,
but that’s OK if I can just make the button transparent, I can put the image behind or over it.

the problem is it refuses to accept the “buttonFillNormal” property,
does it work for you or is it a bug?

You might need to set both _buttonFillNormal and "ButtonBorder.fill"

thanks, that did the trick