diff --git a/src/components/updatemenus/attributes.js b/src/components/updatemenus/attributes.js
index f37e02e9e46..2d2a8794e8b 100644
--- a/src/components/updatemenus/attributes.js
+++ b/src/components/updatemenus/attributes.js
@@ -48,6 +48,22 @@ var buttonsAttrs = templatedArray('button', {
             'method set in `method` on click.'
         ].join(' ')
     },
+    args2: {
+        valType: 'info_array',
+        role: 'info',
+        freeLength: true,
+        items: [
+            {valType: 'any'},
+            {valType: 'any'},
+            {valType: 'any'}
+        ],
+        description: [
+            'Sets a 2nd set of `args`,',
+            'these arguments values are passed to the Plotly',
+            'method set in `method` when clicking this button while in the active state.',
+            'Use this to create toggle buttons.'
+        ].join(' ')
+    },
     label: {
         valType: 'string',
         role: 'info',
diff --git a/src/components/updatemenus/defaults.js b/src/components/updatemenus/defaults.js
index 492b9c911a9..3c646a5efac 100644
--- a/src/components/updatemenus/defaults.js
+++ b/src/components/updatemenus/defaults.js
@@ -74,6 +74,7 @@ function buttonDefaults(buttonIn, buttonOut) {
     if(visible) {
         coerce('method');
         coerce('args');
+        coerce('args2');
         coerce('label');
         coerce('execute');
     }
diff --git a/src/components/updatemenus/draw.js b/src/components/updatemenus/draw.js
index 58c21b9122b..ac4ca74ef16 100644
--- a/src/components/updatemenus/draw.js
+++ b/src/components/updatemenus/draw.js
@@ -119,6 +119,7 @@ module.exports = function draw(gd) {
         var gHeader = d3.select(this);
 
         var _gButton = menuOpts.type === 'dropdown' ? gButton : null;
+
         Plots.manageCommandObserver(gd, menuOpts, menuOpts.buttons, function(data) {
             setActive(gd, menuOpts, menuOpts.buttons[data.index], gHeader, _gButton, scrollBox, data.index, true);
         });
@@ -306,10 +307,14 @@ function drawButtons(gd, gHeader, gButton, scrollBox, menuOpts) {
             // skip `dragend` events
             if(d3.event.defaultPrevented) return;
 
-            setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, buttonIndex);
-
             if(buttonOpts.execute) {
-                Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args);
+                if(buttonOpts.args2 && menuOpts.active === buttonIndex) {
+                    setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, -1);
+                    Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args2);
+                } else {
+                    setActive(gd, menuOpts, buttonOpts, gHeader, gButton, scrollBox, buttonIndex);
+                    Plots.executeAPICommand(gd, buttonOpts.method, buttonOpts.args);
+                }
             }
 
             gd.emit('plotly_buttonclicked', {menu: menuOpts, button: buttonOpts, active: menuOpts.active});
diff --git a/test/image/baselines/updatemenus_toggle.png b/test/image/baselines/updatemenus_toggle.png
new file mode 100644
index 00000000000..8652d930e56
Binary files /dev/null and b/test/image/baselines/updatemenus_toggle.png differ
diff --git a/test/image/mocks/updatemenus_toggle.json b/test/image/mocks/updatemenus_toggle.json
new file mode 100644
index 00000000000..45b67ee019e
--- /dev/null
+++ b/test/image/mocks/updatemenus_toggle.json
@@ -0,0 +1,33 @@
+{
+  "data": [
+    {
+      "mode": "lines",
+      "y": [1, 1],
+      "line": {
+        "width": 5,
+        "color": "blue"
+      }
+    }
+  ],
+  "layout": {
+    "updatemenus": [
+      {
+        "type": "buttons",
+        "buttons": [
+          {
+            "label": "toggle",
+            "method": "restyle",
+            "args": [
+              "line.color",
+              "blue"
+            ],
+            "args2": [
+              "line.color",
+              "red"
+            ]
+          }
+        ]
+      }
+    ]
+  }
+}
diff --git a/test/jasmine/tests/updatemenus_test.js b/test/jasmine/tests/updatemenus_test.js
index e0f86a5bbcf..81449b9dc18 100644
--- a/test/jasmine/tests/updatemenus_test.js
+++ b/test/jasmine/tests/updatemenus_test.js
@@ -601,6 +601,50 @@ describe('update menus interactions', function() {
         .then(done);
     });
 
+    it('should apply update on button click (toggle via args2 case)', function(done) {
+        var menuOpts = {
+            type: 'buttons',
+            buttons: [{
+                label: 'toggle',
+                method: 'restyle',
+                args: ['line.color', 'blue'],
+                args2: ['line.color', 'red']
+            }]
+        };
+
+        var btn;
+
+        function assertLineColor(msg, lineColor) {
+            expect(gd.data[2].line.color).toBe(lineColor, 'gd.data line.color| ' + msg);
+            expect(gd._fullData[2].line.color).toBe(lineColor, 'gd._fullData line.color| ' + msg);
+        }
+
+        Plotly.relayout(gd, 'updatemenus', null)
+        .then(function() { return Plotly.relayout(gd, 'updatemenus[0]', menuOpts); })
+        .then(function() {
+            btn = selectButton(0, {type: 'buttons'});
+            assertItemColor(btn, activeColor);
+            assertLineColor('base', 'blue');
+            return click(btn);
+        })
+        .then(function() {
+            assertItemColor(btn, bgColor);
+            assertLineColor('base', 'red');
+            return click(btn);
+        })
+        .then(function() {
+            assertItemColor(btn, activeColor);
+            assertLineColor('base', 'blue');
+            return click(btn);
+        })
+        .then(function() {
+            assertItemColor(btn, bgColor);
+            assertLineColor('base', 'red');
+        })
+        .catch(failTest)
+        .then(done);
+    });
+
     it('should update correctly on failed binding comparisons', function(done) {
         // See https://github.com/plotly/plotly.js/issues/1169
         // for more info.
@@ -871,8 +915,10 @@ describe('update menus interactions', function() {
         return header;
     }
 
-    function selectButton(buttonIndex) {
-        var buttons = d3.selectAll('.' + constants.dropdownButtonClassName);
+    function selectButton(buttonIndex, opts) {
+        opts = opts || {};
+        var k = opts.type === 'buttons' ? 'buttonClassName' : 'dropdownButtonClassName';
+        var buttons = d3.selectAll('.' + constants[k]);
         var button = d3.select(buttons[0][buttonIndex]);
         return button;
     }