• Skip to main content
  • Select language
  • Skip to search
MDN Web Docs
  • Technologies
    • HTML
    • CSS
    • JavaScript
    • Graphics
    • HTTP
    • APIs / DOM
    • WebExtensions
    • MathML
  • References & Guides
    • Learn web development
    • Tutorials
    • References
    • Developer Guides
    • Accessibility
    • Game development
    • ...more docs
Add-ons
  1. MDN
  2. Mozilla
  3. Add-ons
  4. Add-on SDK
  5. Low-Level APIs
  6. ui/button/action

ui/button/action

In This Article
  1. Usage
    1. Creating buttons
    2. Badged buttons
    3. Specifying multiple icons
    4. Responding to click events
    5. Disabling buttons
    6. Updating state
    7. Destroying buttons
  2. Globals
    1. Constructors
      1. ActionButton(options)
  3. ActionButton
    1. Methods
      1. click()
      2. state()
      3. on()
      4. once()
      5. removeListener()
      6. destroy()
    2. Properties
      1. id
      2. label
      3. icon
      4. disabled
      5. badge
      6. badgeColor
    3. Events
      1. click

Add-ons using the techniques described in this document are considered a legacy technology in Firefox. Don't use these techniques to develop new add-ons. Use WebExtensions instead. If you maintain an add-on which uses the techniques described here, consider migrating it to use WebExtensions.

From Firefox 53 onwards, no new legacy add-ons will be accepted on addons.mozilla.org (AMO).

From Firefox 57 onwards, WebExtensions will be the only supported extension type, and Firefox will not load other types.

Even before Firefox 57, changes coming up in the Firefox platform will break many legacy extensions. These changes include multiprocess Firefox (e10s), sandboxing, and multiple content processes. Legacy extensions that are affected by these changes should migrate to WebExtensions if they can. See the "Compatibility Milestones" document for more.

A wiki page containing resources, migration paths, office hours, and more, is available to help developers transition to the new technologies.

Experimental

Add a button to the Firefox user interface. With this module you can create buttons that display icons and can respond to click events.

Usage


Creating buttons

To create a button you must give it an ID, an icon, and a label:

var { ActionButton } = require("sdk/ui/button/action");
var button = ActionButton({
    id: "my-button",
    label: "my button",
    icon: {
      "16": "./firefox-16.png",
      "32": "./firefox-32.png"
    },
    onClick: function(state) {
        console.log("button '" + state.label + "' was clicked");
    }
  });

By default, the button appears in the Firefox toolbar:

However, users can move it to the Firefox menu panel using the toolbar customization feature:

Badged buttons

New in Firefox 36.

You can add a "badge" to a button using its badge property. This can be a number or a string, and you can update it at any time. By default the badge's color is red, but you can set your own color using the badgeColor property, specified as a CSS <color> value:

var { ToggleButton } = require("sdk/ui/button/toggle");
var button = ToggleButton({
    id: "my-button1",
    label: "my button1",
    icon: "./icon-16.png",
    onChange: changed,
    badge: 0,
    badgeColor: "#00AAAA"
  });
function changed(state) {
  button.badge = state.badge + 1;
  if (state.checked) {
    button.badgeColor = "#AA00AA";
  }
  else {
    button.badgeColor = "#00AAAA";
  }
}

Specifying multiple icons

You can specify just one icon, or multiple icons in different sizes.

If you specify multiple icons, Firefox will select the best-fitting icon based on the device screen resolution and the place the icon appears. For example, in the screenshots above, Firefox uses the small icon when the button is in the toolbar and the large icon when the button is in the menu panel. Read more about specifying icons in the reference documentation for the ActionButton constructor.

Responding to click events

You can respond to click events by assigning a listener to the button's click event. You can do this in the button's constructor, by assigning the listener to the onClick option. You can also add, or change, the listener afterwards:

var { ActionButton } = require("sdk/ui/button/action");
var button = ActionButton({
    id: "my-button",
    label: "my button",
    icon: {
      "16": "./firefox-16.png",
      "32": "./firefox-32.png"
    },
    onClick: firstClick
  });
function firstClick(state) {
  console.log("You clicked '" + state.label + "'");
  button.removeListener("click", firstClick);
  button.on("click", subsequentClicks);
}
function subsequentClicks(state) {
  console.log("You clicked '" +  state.label + "' again");
}

The listener is passed a state object that contains all the button's properties.

You can generate click events programmatically with the button's click() method.

Disabling buttons

You can disable a button by setting its disabled property to true. A disabled button will not generate click events and its icon will appear disabled:

Updating state

You can update all the button's properties except for its id.

By default, the button has global state: that is, its properties are the same across all open windows and tabs, and updating them updates the button's state across all open windows and tabs.

You can set state to be specific to a window or tab using the button's state() method. To set state like this, call state() with 2 parameters:

  • the first parameter is a window or tab object or as a shorthand, the string "window" for the currently active window, or the string "tab" for the currently active tab
  • the second parameter is an object containing the state properties you wish to update.

Here's an add-on with a button that disables itself when you click it, but only for the currently active window:

var { ActionButton } = require("sdk/ui/button/action");
var button = ActionButton({
    id: "my-button",
    label: "my button",
    icon: {
      "16": "./firefox-16.png",
      "32": "./firefox-32.png"
    },
    onClick: disableForThisWindow
  });
function disableForThisWindow(state) {
  button.state("window", {
    disabled: true
  });
}

To fetch the state for a specific window or tab, call state(), passing in the window or tab you are interested in, and it will return the state:

var labelForActiveTab = button.state("tab").label;

To learn more about this, see the API documentation for state().

Destroying buttons

When you've finished with a button, destroy it by calling its destroy() method. After that, any attempts to access any of its properties or to call any of its methods will throw exceptions.

Globals

Constructors

ActionButton(options)

Creates an action button.

Parameters

options : object
Required options:

Name Type  
id string

The button's ID. This is used internally to keep track of this button. The ID must be unique within your add-on.

label string

The button's human-readable label. When the button is in the toolbar, this appears in a tooltip, and when the button is in the menu, it appears underneath the button as a legend.

icon url, string, object

One or more icons for the button. You can specify this in one of three ways: 

  • as a resource:// URL pointing at an icon file in your add-on's "data" directory, typically constructed using self.data.url(iconfile)
  • as a relative path: a string in the form "./iconfile", where "iconfile" is a relative path to the icon file beginning in your add-on's "data" directory
  • as an object, or dictionary of key-value pairs. Here you can specify a range of sizes for your button's icon. Each key-value pair specifies an icon:
    • each value specifies an image file as a resource:// URL or relative path.
    • each key must be a numeric string such as "16", or "32", which represents the size in pixels of the corresponding image.
var { ActionButton } = require('sdk/ui/button/action');
var self = require("sdk/self");
var button1 = ActionButton({
    id: "my-button1",
    label: "my button1",
    icon: self.data.url("firefox-16.png")
  });
var button2 = ActionButton({
    id: "my-button2",
    label: "my button2",
    icon: "./firefox-16.png"
  });
var button3 = ActionButton({
    id: "my-button3",
    label: "my button3",
    icon: {
      "16" : "./firefox-16.png",
      "32" : "./firefox-32.png",
      "64" : "./firefox-64.png"
    }
  });

If you use the final form, Firefox will automatically choose the best-fit icon for your button, depending on the device screen resolution and where the button is in the UI. On a device with a "normal" screen resolution, the toolbar has space for 18 x 18 pixels and the menu panel has space for 32 x 32 pixels. On a high resolution screen (such as a HiDPI display), these are doubled to 36 x 36 and 64 x 64 pixels, respectively. So you can supply three icon files:

icon: {
  "16": "./addon16.png",
  "32": "./addon32.png",
  "64": "./addon64.png"
}

This will look fine in both toolbar and menu panel, and for both screen resolutions. However, the icons in the toolbar will not quite fill the space available, so you can instead supply four icons:

icon: {
  "18": "./addon18.png", // toolbar icon non HiDPI
  "32": "./addon32.png", // menu panel icon non HiDPI
  "36": "./addon36.png", // toolbar icon HiDPI
  "64": "./addon64.png"  // menu panel icon HiDPI
}

Optional options:

Name Type  
disabled boolean

Determines whether the button is disabled. Disabled buttons appear disabled in the UI, and do not respond to clicks. Defaults to false.

onClick function

Click handler for the button.

badge Number or String

New in Firefox 36.

Badge to attach to the button.

The badge can contain as many characters (or digits) as you like, but only the first four will be displayed.

badgeColor CSS <color> value

New in Firefox 36.

Color for the badge. If badgeColor is omitted and badge is specified, then the badge is red.

ActionButton

Methods

click()

Click the button. This will cause the button to generate the click event:

var { ActionButton } = require('sdk/ui/button/action');
var button = ActionButton({
  id: "my-button",
  label: "my button",
  icon: {
    "16": "./firefox-16.png",
    "32": "./firefox-32.png"
  },
  onClick: function(state) {
      console.log("You clicked '" + state.label + "'");
  }
});
button.click();

state()

Get or set the button's state for a specific window or tab.

By default, a button's properties are global, meaning that they are the same across all open windows and tabs, and that if you update these properties, then they are updated across all windows and tabs. But sometimes you want a button attached to one window (or tab) to have a different state to a button attached to a different window (or tab). That's what state() is for.

To set a button's properties for a specific window or tab, call state(), passing it the window or tab you want the property to apply to, and the property value to set. A special shortcut allows you to pass the string "window" or "tab" to select the currently active window or tab.

For example, if you have a button like this:

var { ActionButton } = require('sdk/ui/button/action');
var button = ActionButton({
  id: "my-button",
  label: "default",
  icon: "./firefox-16.png"
});

You can change its label for only the currently active window like this:

button.state("window", {
  "label" : "window-specific label"
});

You can change its label for only the currently active tab like this:

button.state("tab", {
  "label" : "tab-specific label"
});

To fetch the button state for a specific window or tab, call state(), passing it the window or tab you're interested in, and it will return a state object containing all the properties for the button associated with that window or tab. Again. you can use the strings "window" or "tab" as shortcuts. For example, this add-on:

  • creates a button with a default label
  • opens a new tab
  • sets a new label only for the new tab
  • logs the result of accessing the global label, the window-specific label, and each of the 2 tab-specific labels
var { ActionButton } = require('sdk/ui/button/action');
var tabs = require("sdk/tabs");
var button = ActionButton({
  id: "my-button",
  label: "default label",
  icon: "./firefox-16.png"
});
tabs.open({
  url: "https://mozilla.org/",
  onOpen: onNewTab
});
function onNewTab(tab) {
  // Modify the label only for the new tab
  button.state(tab, {
    "label" : "tab-specific label"
  });
  // access the global label -> "default label"
  console.log(button.label);
  // access the window's label -> "default label"
  console.log(button.state("window").label);
  // access the first tab's label -> "default label"
  console.log(button.state(tabs[0]).label);
  // access the second tab's label -> "tab-specific label"
  console.log(button.state(tabs[1]).label);
}

Setting a property won't affect a more-specific property setting. For example, if you have a window with two tabs, and you set a tab-specific label, then set the window-specific label, this will not overwrite the tab-specific label:

var { ActionButton } = require('sdk/ui/button/action');
var tabs = require("sdk/tabs");
var button = ActionButton({
  id: "my-button",
  label: "default label",
  icon: "./firefox-16.png"
});
tabs.open({
  url: "https://mozilla.org/",
  onOpen: onNewTab
});
function onNewTab(tab) {
  // Modify the label only for the new tab
  button.state(tab, {
    "label" : "tab-specific label"
  });
  // Modify the label for the window
  button.state("window", {
    "label" : "window-specific label"
  });
  // access the global label -> "default label"
  console.log(button.label);
  // access the window's label -> "window-specific label"
  console.log(button.state("window").label);
  // access the first tab's label -> "window-specific label"
  console.log(button.state(tabs[0]).label);
  // access the second tab's label -> "tab-specific label"
  console.log(button.state(tabs[1]).label);
}

The best way to think of this is as a tree: the global state is the root, followed by the state for each window, followed by the state for each tab in a window. If a property value for a node in the tree has not been set explicitly using state(), then it inherits its value from the next level up. So if you have one window containing two tabs, and have set the button's label only for tab A, then tab B will inherit label's value from the window, and changing the value for the window will implicitly change the value for tab B.

To delete a tab- or window-specific state, assign null to the property. After that, the property will inherit its value from the less-specific state as before:

var { ActionButton } = require('sdk/ui/button/action');
var tabs = require("sdk/tabs");
var button = ActionButton({
  id: "my-button",
  label: "default label",
  icon: "./firefox-16.png"
});
tabs.open({
  url: "https://mozilla.org/",
  onOpen: onNewTab
});
function onNewTab(tab) {
  // Modify the label only for the new tab
  button.state(tab, {
    "label" : "tab-specific label"
  });
  // Modify the label for the window
  button.state("window", {
    "label" : "window-specific label"
  });
  // access the global label -> "default label"
  console.log(button.label);
  // access the window's label -> "window-specific label"
  console.log(button.state("window").label);
  // access the first tab's label -> "window-specific label"
  console.log(button.state(tabs[0]).label);
  // access the second tab's label -> "tab-specific label"
  console.log(button.state(tabs[1]).label);
  // Reset the tab-specific state
  button.state(tab, null);
  // access the second tab's label -> "window-specific label"
  console.log(button.state(tabs[1]).label);
}

Finally, you can pass the button itself into state(). This is an alternative way to set or get the global state. The reason for using this, rather than setting properties individually, is that you can define an object with the properties to set in one place, then apply it to the global state with a single line:

const defaultState = {
  "label": "default label",
  "icon": "./default.png",
}
const differentState = {
  "label": "different label",
  "icon": "./different.png",
}
var { ActionButton } = require("sdk/ui/button/action");
var button = ActionButton({
    id: "default-label",
    label: "default label",
    icon: "./default.png",
    onClick: function(state) {
      if (button.label == "default label") {
        button.state(button, differentState);
      }
      else {
        button.state(button, defaultState);
      }
      console.log(button.state(button).label);
      console.log(button.state(button).icon);
    }
  });
Parameters

target : button, tab, window, string

  • To set or get the global state, this needs to be the button instance.
  • To get or set window-specific state, this needs to be the window object for which you wish to set a specific state, or the string "window" to select the currently active window.
  • To get or set tab-specific state this needs to be the tab object for which you wish to set a specific state, or the string "tab" to select the currently active tab.

state : object, null
Include this parameter only if you are setting state. It is an object containing all the properties you wish to set. For example:

button.state("tab", {
  "label" : "tab-specific label",
  "icon": "./tab-specific-icon.ico"
});

To reset state, pass null:

button.state("tab", null);
Returns

state : if you have passed the second state argument to make this function a setter, it returns undefined. Otherwise, it functions as a getter and returns the button's state for the specified object. This logs the state for the button associated with the currently active tab:

console.log(button.state("tab"));

This object represents a snapshot of the state at the time state() is called. It is not kept up to date with changes made to the button:

button.label = "foo";
var state = button.state(button);
button.label = "bar";
console.log(state.label) // foo

on()

Add a listener to an event emitted by the button. The button only emits one type of event, click:

button.on("click", handleClick)
function handleClick(state) {
  console.log("button '" + state.label + "' was clicked");
}
Parameters

event : string
The event to listen for. Action buttons only emit one type of event, "click".

listener : function
Function that will be called on click.

once()

Assign a listener to the first occurrence only of an event emitted by the button. The button only emits one type of event, click. The listener is automatically removed after the first time the event is emitted.

Parameters

event : string
The event to listen for. Action buttons only emit one type of event, "click".

listener : function
Function that will be called on click.

removeListener()

Removes an event listener. For example, this code is equivalent to once():

button.on("click", handleClick)
function handleClick(state) {
  console.log("button '" + state.label + "' was clicked");
  button.removeListener("click", handleClick);
} 
Parameters

event : string
The event to listener is listening for. Action buttons only emit one type of event, "click".

listener : function
The listener to remove.

destroy()

Destroy the button. After calling this function, the button will no longer appear in the UI, and accessing any of its properties or methods will throw an error.

Properties

id

The button's unique ID. This is read-only.

label

The button's label.

icon

The button's icon or icons, as a URL, relative path, or object containing a set of key-value pairs.

disabled

Boolean property indicating whether or not the button is disabled.

badge

New in Firefox 36.

Value to attach to the button as a badge. May be a number or a string.

The badge can contain as many characters (or digits) as you like, but only the first four will be displayed.

badgeColor

New in Firefox 36.

Color for the badge, specified as a CSS <color> value.

Events

click

This event is emitted when a user clicks the button or your add-on calls the button's click() method.

Arguments

state : The button's state. This contains all the button's properties.

Document Tags and Contributors

 Contributors to this page: wbamberg, addOn
 Last updated by: wbamberg, Dec 1, 2016, 10:36:18 AM
See also
  1. WebExtensions
  2. Getting started
    1. What are WebExtensions?
    2. Your first WebExtension
    3. Your second WebExtension
    4. Anatomy of a WebExtension
    5. Example WebExtensions
  3. How to
    1. Intercept HTTP requests
    2. Modify a web page
    3. Add a button to the toolbar
    4. Implement a settings page
  4. Concepts
    1. Using the JavaScript APIs
    2. User interface components
    3. Content scripts
    4. Match patterns
    5. Internationalization
    6. Content Security Policy
    7. Native messaging
  5. Porting
    1. Porting a Google Chrome extension
    2. Porting a legacy Firefox add-on
    3. Embedded WebExtensions
    4. Comparison with the Add-on SDK
    5. Comparison with XUL/XPCOM extensions
    6. Chrome incompatibilities
  6. Firefox workflow
    1. Temporary Installation in Firefox
    2. Debugging
    3. Getting started with web-ext
    4. web-ext command reference
    5. WebExtensions and the Add-on ID
    6. Publishing your WebExtension
  7. JavaScript APIs
    1. Browser support for JavaScript APIs
    2. alarms
    3. bookmarks
    4. browserAction
    5. browsingData
    6. commands
    7. contextMenus
    8. contextualIdentities
    9. cookies
    10. downloads
    11. events
    12. extension
    13. extensionTypes
    14. history
    15. i18n
    16. identity
    17. idle
    18. management
    19. notifications
    20. omnibox
    21. pageAction
    22. runtime
    23. sessions
    24. sidebarAction
    25. storage
    26. tabs
    27. topSites
    28. webNavigation
    29. webRequest
    30. windows
  8. Manifest keys
    1. applications
    2. author
    3. background
    4. browser_action
    5. chrome_url_overrides
    6. commands
    7. content_scripts
    8. content_security_policy
    9. default_locale
    10. description
    11. developer
    12. homepage_url
    13. icons
    14. manifest_version
    15. name
    16. omnibox
    17. options_ui
    18. page_action
    19. permissions
    20. short_name
    21. sidebar_action
    22. version
    23. web_accessible_resources
  9. Add-on SDK
  10. Getting started
    1. Installation
    2. Getting started
    3. Troubleshooting
  11. High-Level APIs
    1. addon-page
    2. base64
    3. clipboard
    4. context-menu
    5. hotkeys
    6. indexed-db
    7. l10n
    8. notifications
    9. page-mod
    10. page-worker
    11. panel
    12. passwords
    13. private-browsing
    14. querystring
    15. request
    16. selection
    17. self
    18. simple-prefs
    19. simple-storage
    20. system
    21. tabs
    22. timers
    23. ui
    24. url
    25. webextension
    26. widget
    27. windows
  12. Low-Level APIs
    1. /loader
    2. chrome
    3. console/plain-text
    4. console/traceback
    5. content/content
    6. content/loader
    7. content/mod
    8. content/symbiont
    9. content/worker
    10. core/heritage
    11. core/namespace
    12. core/promise
    13. dev/panel
    14. event/core
    15. event/target
    16. frame/hidden-frame
    17. frame/utils
    18. fs/path
    19. io/byte-streams
    20. io/file
    21. io/text-streams
    22. lang/functional
    23. lang/type
    24. loader/cuddlefish
    25. loader/sandbox
    26. net/url
    27. net/xhr
    28. places/bookmarks
    29. places/favicon
    30. places/history
    31. platform/xpcom
    32. preferences/event-target
    33. preferences/service
    34. remote/child
    35. remote/parent
    36. stylesheet/style
    37. stylesheet/utils
    38. system/child_process
    39. system/environment
    40. system/events
    41. system/runtime
    42. system/unload
    43. system/xul-app
    44. tabs/utils
    45. test/assert
    46. test/harness
    47. test/httpd
    48. test/runner
    49. test/utils
    50. ui/button/action
    51. ui/button/toggle
    52. ui/frame
    53. ui/id
    54. ui/sidebar
    55. ui/toolbar
    56. util/array
    57. util/collection
    58. util/deprecate
    59. util/list
    60. util/match-pattern
    61. util/object
    62. util/uuid
    63. window/utils
  13. Firefox for Android
  14. Getting started
    1. Walkthrough
    2. Debugging
    3. Code snippets
  15. APIs
    1. Accounts.jsm
    2. BrowserApp
    3. HelperApps.jsm
    4. Home.jsm
    5. HomeProvider.jsm
    6. JavaAddonManager.jsm
    7. NativeWindow
    8. Notifications.jsm
    9. PageActions.jsm
    10. Prompt.jsm
    11. RuntimePermissions.jsm
    12. Snackbars.jsm
    13. Sound.jsm
    14. Tab
  16. Legacy
  17. Restartless extensions
    1. Overview
  18. Overlay extensions
    1. Overview
  19. Themes
  20. Lightweight themes
    1. Overview
  21. Complete themes
    1. Overview
  22. Publishing add-ons
  23. Guides
    1. Signing and distribution overview
    2. Submit an add-on
    3. Review policies
    4. Developer agreement
    5. Featured add-ons
    6. Contact addons.mozilla.org
  24. Community and support
  25. Channels
    1. Add-ons blog
    2. Add-on forums
    3. Stack Overflow
    4. Development newsgroup
    5. IRC Channel