Design the user interface
Published on • Updated on
Like Chrome's user interface (UI), an extension UI should be purposeful and minimal. Extensions should allow users to customize or enhance the user's browsing experience without distracting from it.
This guide explores required and optional user interface features. Use it to understand how and when to implement different UI elements within an extension.
The extension action
The Action API controls the extension's action (toolbar icon). It can either open a popup or trigger some functionality when it's clicked.
Users can trigger an extension's action by expanding the extension menu and selecting the desired extension.
To make it easier to access an extension, the user may choose to pin the extension's action to the toolbar. Once pinned, the extension's action will appear to the left of the extension menu. Users can rearrange their pinned extensions by dragging and dropping their action icons to the desired order.
![Unpinned extension](https://wd.imgix.net/image/BhuKGJaIeLNPW9ehns59NfwqKxF2/iouvm1a3lsQWGyg6fSMS.png?auto=format)
Unpinned extension
![Pinned extension](https://wd.imgix.net/image/BhuKGJaIeLNPW9ehns59NfwqKxF2/KS09fVoCj3YWuIoH5EFn.png?auto=format)
Pinned extension
Register the action
To use the Action API, the extension's manifest must contain an "action"
key. This informs the browser that the extension will customize the action.
{
"name": "My Awesome action MV3 Extension",
...
"action": {
...
}
...
}
See the manifest section of the Action API docs for a full description on the optional properties of this field.
Activate the action conditionally
The DeclarativeContent API allows you to enable the extension's action based on the page URL or if the CSS selectors match the elements on the page.
When an extension is disabled, the icon is grayed out. If the user clicks the disabled extension, the extension's context menu will appear.
![Clicked Disabled extension](https://wd.imgix.net/image/BhuKGJaIeLNPW9ehns59NfwqKxF2/hlYsQJPFsF7WBAjJZ6DS.png?auto=format)
Provide the extension icons
An extension requires at least one icon to represent it. Provide icons in PNG format for the best visual results, although any raster format supported by Blink including BMP, GIF, ICO, and JPEG is accepted.
SVG files are not supported for any icons declared in the manifest.
Ensure your icon follows the extension icon best practices.
Designate action icons
Icons specific to the toolbar are registered in the "default_icon"
field under action
in the manifest. Including multiple sizes is encouraged to scale for the 16-dip space. At minimum, 16x16 and 32x32 sizes are recommended.
{
"name": "My Awesome Extension",
...
"action": {
"default_icon": {
"16": "extension_toolbar_icon16.png",
"32": "extension_toolbar_icon32.png"
}
}
...
}
All icons should be square or they may be distorted. If no icons are supplied, Chrome will add a generic one to the toolbar with the first letter of the extension name.
Create and register additional icons
Include additional icons in the following sizes for uses outside of the toolbar.
Icon Size | Icon Use |
---|---|
16x16 | Favicon on the extension's pages and context menu icon. |
32x32 | Windows computers often require this size. |
48x48 | Displays on the extension management page. |
128x128 | Displays on installation and in the Chrome Web Store. |
Register icons in the manifest under the "icons"
field.
{
"name": "My Awesome Extension",
...
"icons": {
"16": "extension_icon16.png",
"32": "extension_icon32.png",
"48": "extension_icon48.png",
"128": "extension_icon128.png"
}
...
}
Additional UI features
Action badge
Badges display a colored banner on top of the action icon. They can only be used when the "action"
is declared in the manifest.
Use badges to indicate the state of the extension. The Drink Water sample extension displays a badge with "ON" to show the user they have successfully set an alarm and displays nothing when the extension is idle. Badges can contain up to 4 characters.
![Badge On](https://wd.imgix.net/image/BrQidfK9jaQyIHwdw91aVpkPiib2/nXwAHSWLBEgT8099ITT0.png?auto=format)
![Badge Off](https://wd.imgix.net/image/BrQidfK9jaQyIHwdw91aVpkPiib2/pNz8UgfTBMmcf7fE9wja.png?auto=format)
You can set the text of the badge by calling chrome.action.setBadgeText()
and the banner color by calling chrome.action.setBadgeBackgroundColor()
.
chrome.action.setBadgeText({text: 'ON'});
chrome.action.setBadgeBackgroundColor({color: '#4688F1'});
Popup
A popup is an HTML file that is displayed in a special window when the user clicks the action icon. A popup works very similarly to a web page; it can contain links to stylesheets and script tags, but does not allow inline JavaScript.
The Drink Water Event example popup displays available timer options. Users set an alarm by clicking one of the provided buttons.
![Popup sample screenshot](https://wd.imgix.net/image/BrQidfK9jaQyIHwdw91aVpkPiib2/JVduBMXnyUorfNjFZmue.png?auto=format)
<html>
<head>
<title>Water Popup</title>
</head>
<body>
<img src="./stay_hydrated.png" id="hydrateImage">
<button id="sampleSecond" value="0.1">Sample Second</button>
<button id="min15" value="15">15 Minutes</button>
<button id="min30" value="30">30 Minutes</button>
<button id="cancelAlarm">Cancel Alarm</button>
<script src="popup.js"></script>
</body>
</html>
The popup is registered in the manifest under the "action"
key.
{
"name": "Drink Water Event",
...
"action": {
"default_popup": "popup.html"
}
...
}
Popups can also be set dynamically by calling action.setPopup
.
chrome.storage.local.get('signed_in', (data) => {
if (data.signed_in) {
chrome.action.setPopup({popup: 'popup.html'});
} else {
chrome.action.setPopup({popup: 'popup_sign_in.html'});
}
});
Tooltip
Use a tooltip to give short descriptions or instructions to users when hovering over the action icon. By default, the tootip displays the name of the extension.
![A screenshot of an example tooltip](https://wd.imgix.net/image/BrQidfK9jaQyIHwdw91aVpkPiib2/Go8aQg0vd0f2hkOFElLK.png?auto=format)
Tooltips are registered in the "default_title"
field under the "action"
key in the manifest.
{
"name": "Tab Flipper",
...
"action": {
"default_title": "Press Ctrl(Win)/Command(Mac)+Shift+Right/Left to flip tabs"
}
...
}
Tooltips can also be set or updated by calling action.setTitle
.
Click Event
It's possible to register an OnClicked handler for when the user clicks the action item. However, this won't fire if the action has a popup (default or otherwise).
chrome.action.onClicked.addListener(function(tab) {
chrome.action.setTitle({tabId: tab.id, title: "You are on tab:" + tab.id});
});
Omnibox
Users can invoke extension functionality through the Omnibox API. Include the "omnibox"
field in the manifest and designate a keyword. The Omnibox New Tab Search sample extension uses nt as the keyword.
{
"name": "Omnibox New Tab Search",
...
"omnibox": { "keyword" : "nt" },
"default_icon": {
"16": "newtab_search16.png",
"32": "newtab_search32.png"
}
...
}
When the user types "nt" into the omnibox, it activates the extension. To signal this to the user, it grayscales the provided 16x16 icon and includes it in the omnibox next to the extension name.
![Active Omnibox Extension](https://wd.imgix.net/image/BrQidfK9jaQyIHwdw91aVpkPiib2/T0jCZDUVfuEANigPV6bY.png?auto=format)
The extension listens to the omnibox.onInputEntered
event. After it's triggered, the extension opens a new tab containing a Google search for the user's entry.
chrome.omnibox.onInputEntered.addListener(function(text) {
// Encode user input for special characters , / ? : @ & = + $ #
const newURL = 'https://www.google.com/search?q=' + encodeURIComponent(text);
chrome.tabs.create({ url: newURL });
});
Context menu
You can use the ContextMenus API by granting the "contextMenus"
permission in the manifest.
{
"name": "Global Google Search",
...
"permissions": [
"contextMenus",
"storage"
],
"icons": {
"16": "globalGoogle16.png",
"48": "globalGoogle48.png",
"128": "globalGoogle128.png"
}
...
}
The 16x16 icon is displayed next to the new menu entry.
![Context Menu Icon](https://wd.imgix.net/image/BrQidfK9jaQyIHwdw91aVpkPiib2/jpA0DLCg2sEnwIf4FkLp.png?auto=format)
Create a context menu by calling contextMenus.create()
in the background script. This should be done under the runtime.onInstalled
listener event.
// background.js
chrome.runtime.onInstalled.addListener(async () => {
for (let [tld, locale] of Object.entries(tldLocales)) {
chrome.contextMenus.create({
id: tld,
title: locale,
type: 'normal',
contexts: ['selection'],
});
}
});
const tldLocales = {
'com.au': 'Australia',
'com.br': 'Brazil',
'ca': 'Canada',
'cn': 'China',
'fr': 'France',
'it': 'Italy',
'co.in': 'India',
'co.jp': 'Japan',
'com.ms': 'Mexico',
'ru': 'Russia',
'co.za': 'South Africa',
'co.uk': 'United Kingdom'
};
The Global Google Search context menu example creates multiple options from the list in locales.js
. When an extension contains more than one context menu, Chrome automatically collapses them into a single parent menu.
![Multiple Context Menus will Collapse](https://wd.imgix.net/image/BrQidfK9jaQyIHwdw91aVpkPiib2/LhrliaEhN82maJmeNp7f.png?auto=format)
Commands
Extensions can define specific Commands API and bind them to a key combination. Register one or more shortcuts in the manifest under the "commands"
key.
{
"name": "Tab Flipper",
...
"commands": {
"flip-tabs-forward": {
"suggested_key": {
"default": "Ctrl+Shift+Right",
"mac": "Command+Shift+Right"
},
"description": "Flip tabs forward"
},
"flip-tabs-backwards": {
"suggested_key": {
"default": "Ctrl+Shift+Left",
"mac": "Command+Shift+Left"
},
"description": "Flip tabs backwards"
}
}
...
}
Commands can be used to provide new or alternative browser shortcuts. The Tab Flipper sample extension listens to the commands.onCommand
event in the background script and defines functionality for each registered combination.
// background.js
chrome.commands.onCommand.addListener(command => {
// command will be "flip-tabs-forward" or "flip-tabs-backwards"
chrome.tabs.query({currentWindow: true}, tabs => {
// Sort tabs according to their index in the window.
tabs.sort((a, b) => a.index - b.index);
const activeIndex = tabs.findIndex((tab) => tab.active);
const lastTab = tabs.length - 1;
let newIndex = -1;
if (command === 'flip-tabs-forward') {
newIndex = activeIndex === 0 ? lastTab : activeIndex - 1;
} else { // 'flip-tabs-backwards'
newIndex = activeIndex === lastTab ? 0 : activeIndex + 1;
}
chrome.tabs.update(tabs[newIndex].id, {active: true, highlighted: true});
});
});
Override pages
An extension can override and replace the History, New Tab, or Bookmarks page with a custom HTML file. Like a popup, it can include specialized logic and style, but does not allow inline JavaScript.
A single extension is limited to overriding only one of the three possible pages.
Register an override page in the manifest under the "chrome_url_overrides"
field.
{
"name": "Awesome Override Extension",
...
"chrome_url_overrides" : {
"newtab": "override_page.html"
},
...
}
The "newtab"
field should be replaced with "bookmarks"
or "history"
when overriding those pages.
<html>
<head>
<title>New Tab</title>
</head>
<body>
<h1>Hello World</h1>
<script src="logic.js"></script>
</body>
</html>
Notifications
You can communicate relevant information to users by displaying notifications directly in their system tray.
To use the Notifications API, you must declare the "notifications"
permission in the manifest.
// manifest.json
{
"name": "Drink Water Event Popup",
...
"permissions": [
"alarms",
"notifications",
"storage"
],
...
}
Once the permission is declared, you can display a notification by calling notifications.create()
.
// background.js
function showStayHydratedNotification() {
chrome.notifications.create({
type: 'basic',
iconUrl: 'stay_hydrated.png',
title: 'Time to Hydrate',
message: 'Everyday I\'m Guzzlin\'!',
buttons: [
{ title: 'Keep it Flowing.' }
],
priority: 0
});
}
![Mac OS notification](https://wd.imgix.net/image/BhuKGJaIeLNPW9ehns59NfwqKxF2/e5S112AtwfnA5o64JrGg.png?auto=format)
Internationalize the UI
You can use the I18n API to internationalize your extension. Create directories to house language specific messages within a folder called _locales/
, like this:
_locales/en/messages.json
_locales/es/messages.json
Format messages inside of each language's messages.json
. For example, the following code localizes the tooltip:
Located in _locales/en/messages.json
:
{
"__MSG_tooltip__": {
"message": "Hello!",
"description": "Tooltip"
}
}
Located in _locales/es/messages.json
:
{
"__MSG_tooltip__": {
"message": "Hola!",
"description": "Tooltip"
}
}
Specify the name of the message in the "default_title"
field of the manifest. The "default_locale"
field must be defined.
// manifest.json
{
"name": "Tab Flipper",
...
"action": {
"default_title": "__MSG_tooltip__"
},
"default_locale": "en"
...
}
Continue exploring
See the Action API example for a complete demonstration of the action APIs capabilities.
Updated on • Improve article