By signing up for this Early Access Program (“EAP”), you acknowledge that use of the Forge global:ui module and Global component is governed by the Atlassian Developer Terms. The Forge global:ui module and Global component are considered Early Access Materials and currently support only UI Kit (render: native), as set forth in Section 12 of the Atlassian Developer Terms and are subject to applicable terms, conditions, and disclaimers. The Forge global:ui module, Global component, and any related documentation are provided solely for testing purposes and are considered Atlassian Confidential Information.
As conditions on your right to use the Forge global:ui module and Global component during this EAP, you agree not to (and not to authorize any third party to) deploy any Marketplace App using the Forge global:ui module or Global component in a Production environment.
To join the EAP for global:ui, complete the sign up form.
For more details, see Forge EAP, Preview, and GA.
The global UI Kit components provide the navigation experience for your app. They deliver a complete layout with a header, sidebar navigation, and main content area that integrates with the Atlassian platform.
You can only use the Global component inside the global:ui module.
These UI Kit components are exported from the @forge/react/global entry point.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16import { Global, Sidebar, LinkMenuItem, FlyOutMenuItem, ExpandableMenuItem, MenuSection, ReorderableMenuItems, HelpLink, PersonalSettings, PersonalSettingsItem, CreateButton, CreateMenuItem, Main, } from "@forge/react/global";
The Global component is composed of sub-components that work together to create the full layout:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29<Global> ├─ <HelpLink /> │ ├─ <CreateButton /> │ └─ <CreateMenuItem /> │ ├─ <PersonalSettings /> │ └─ <PersonalSettingsItem /> │ ├─ <Sidebar /> │ ├─ <MenuSection /> │ │ ├─ <LinkMenuItem /> │ │ ├─ <ReorderableMenuItems /> │ │ ├─ <FlyOutMenuItem /> │ │ └─ <ExpandableMenuItem /> │ │ │ ├─ <LinkMenuItem /> │ │ │ ├─ <ReorderableMenuItems /> │ │ │ ├─ <FlyOutMenuItem /> │ │ └─ <LinkMenuItem /> │ │ │ └─ <ExpandableMenuItem /> │ └─ <LinkMenuItem /> │ └─ <Main /> └─ {Your app content}
Both <Sidebar> and <Main> must be present as direct children of <Global>.
The component renders three layout areas:
forYouMenuItem prop is true, the For you menu item is displayed at the top of the sidebar
and the app uses the route /for-you as its home page.
When the forYouMenuItem prop is false, the For you menu item is hidden and the app uses the root
route (/) as its home page.
Below it, you configure additional menu items using Sidebar,
LinkMenuItem, ExpandableMenuItem, and related components.<Main>.GlobalThe root component that wraps the full layout.
| Name | Type | Required | Description |
|---|---|---|---|
children | ForgeElement | Yes | Accepts HelpLink, CreateButton, PersonalSettings, Sidebar, and Main. |
SidebarRenders the left navigation panel.
| Name | Type | Required | Description |
|---|---|---|---|
children | ForgeElement | Yes | Accepts LinkMenuItem, ExpandableMenuItem, FlyOutMenuItem, MenuSection, and ReorderableMenuItems. |
forYouMenuItem | boolean | No | Whether to show the built-in For you menu item. Defaults to true. When true, displays the For you item and uses /for-you as the home page. When false, hides the item and uses the root route / as the home page. |
LinkMenuItemA clickable navigation link in the sidebar.
| Name | Type | Required | Description |
|---|---|---|---|
label | string | Yes | The text displayed for the menu item. |
href | string | Yes | The route this item navigates to. |
icon | string | No | The name of an Atlassian Design System (ADS) icon glyph to display alongside the label. For example, "chart-bar" or "settings". The platform controls the icon size and color. Always use with a visible label. |
activePath | string | string[] | No | One or more glob patterns, such as "/projects/*/settings", that highlight this item when the current path matches. Use this to keep an item highlighted on routes nested below its href. |
By default, a LinkMenuItem is highlighted only when the current path matches its href exactly.
Apps with deeply nested routes often need the item to stay highlighted on child routes as well.
For example, you might want Projects to stay highlighted while the user navigates to
/projects/alpha/boards/3.
The activePath prop takes a glob pattern, or an array of glob patterns, that the platform matches
against the current path. If any pattern matches, the item is highlighted. Matching against the
item's own href still applies, so you only need to describe the additional paths.
1 2 3 4 5 6 7<LinkMenuItem label="Projects" href="/projects" icon="folder-closed" activePath="/projects/**" />
Patterns support the following wildcards:
| Wildcard | Description |
|---|---|
* | Matches exactly one path segment (no slashes). |
** | Matches one or more path segments, at any depth. |
Unlike some glob libraries, ** matches one or more path segments, not zero or more. To also match
the path itself, combine it with an exact pattern: activePath={["/projects", "/projects/**"]}.
| Pattern | Matches | Doesn't match |
|---|---|---|
"/projects/*" | /projects/alpha | /projects, /projects/alpha/boards |
"/projects/*/settings" | /projects/alpha/settings | /projects/alpha/boards/settings |
"/projects/**" | /projects/alpha, /projects/alpha/boards/3 | /projects |
"/projects/**/settings" | /projects/alpha/settings, /projects/alpha/boards/3/settings | /projects/settings |
The icon prop accepts an ADS icon glyph name as a string. The platform renders the icon at the correct size and color for the sidebar context. Browse all available glyph names in the ADS icon explorer.
1 2<LinkMenuItem label="Reports" href="/reports" icon="chart-bar" />
Use icons to help users identify destinations more quickly. Icons work alongside labels — they don't replace them.
Follow these guidelines when choosing icons for sidebar navigation:
Use icons that represent destinations, not actions. Choose icons for places your users navigate to, such as a dashboard, a reports area, or a settings section. Avoid icons that suggest transient actions like create, edit, or run — those belong in buttons and menus.
Always pair icons with labels. The icon prop should always appear alongside a label. Don't rely on an icon alone to communicate a destination — very few icons are universally understood, especially in a custom app context.
Maintain a one-to-one relationship between icons and destinations. Each icon should represent exactly one destination, and each destination should use exactly one icon. Duplicating an icon across two items, or swapping icons for the same item in different parts of the navigation, weakens recognition.
Be mindful of Atlassian's existing navigation icons. Some ADS icons are already associated with specific Atlassian products and navigation areas. Reusing them for unrelated destinations in your app can mislead users into thinking they are navigating to an Atlassian-native area.
The following icons are used in Atlassian's own global navigation for specific primary objects and areas. We recommend avoiding them for destinations that are unrelated to the Atlassian product they represent.
| ADS glyph name | ADS icon | Meaning | Guidance |
|---|---|---|---|
"spaces" | Spaces directory in Confluence | Avoid if your destination isn't related to Confluence Spaces. | |
"project" | Projects directory in Jira | Avoid if your destination isn't related to Jira Projects. | |
"goal" | Goal object in the Goals app | Avoid if your destination isn't related to Atlassian Goals. | |
"dashboard" | Dashboard object in the Home app | Avoid if your destination isn't related to Atlassian Dashboards. | |
"teams" | Teams object in the Teams app | Avoid if your destination isn't related to Atlassian Teams. | |
"person" | "For you" landing page in Atlassian navigation | Avoid reusing this icon to prevent confusion with Atlassian's "For you" navigation item. | |
"clock" | "Recent" flyout in Atlassian navigation | Avoid to prevent confusion with Atlassian's "Recent" navigation item. | |
"star-starred", "star-unstarred" | "Starred" flyout in Atlassian navigation | Avoid unless your destination represents starred or favourited content. |
MenuSectionGroups sidebar menu items under an optional section header. Use the label prop to display a section header above the items.
| Name | Type | Required | Description |
|---|---|---|---|
label | string | No | The section header displayed above the grouped menu items. |
children | ForgeElement | Yes | Accepts LinkMenuItem, ExpandableMenuItem, FlyOutMenuItem, and ReorderableMenuItems components. |
Use MenuSection with a label prop to add a section header for menu items in the sidebar.
1 2 3 4 5 6 7 8 9<Global> <Sidebar> <MenuSection label="Your homes"> <LinkMenuItem label="Home 1" href="/home-1" /> <LinkMenuItem label="Home 2" href="/home-2" /> </MenuSection> </Sidebar> </Global>
ExpandableMenuItemAn expandable menu item that reveals nested links when selected.
| Name | Type | Required | Description |
|---|---|---|---|
label | string | Yes | The text displayed for the expandable menu item. |
children | ForgeElement | Yes | Accepts LinkMenuItem, ExpandableMenuItem (can be nested up to 3 levels), and ReorderableMenuItems. |
FlyOutMenuItemA sidebar item that opens a flyout containing nested menu items.
| Name | Type | Required | Description |
|---|---|---|---|
label | string | Yes | The text displayed for the flyout menu item. |
children | ForgeElement | Yes | Accepts nested sidebar menu items, such as LinkMenuItem. |
ReorderableMenuItemsGroups sidebar menu items that users can reorder. Use this when your app supports a customizable navigation order.
| Name | Type | Required | Description |
|---|---|---|---|
items |
| Yes | An array of sidebar menu items that the user can reorder. Each item must include a unique id, a display label, and a navigation href. An optional ADS icon glyph name from ADS icon explorer can also be included to render the corresponding icon. An optional activePath glob pattern, or array of patterns, highlights the item on nested routes — see Highlighting nested paths. |
onReorder |
| Yes | A callback invoked after the user changes the item order. Receives the reordered items so the app can update local state or persist the new order. |
onError |
| No | A callback invoked when reordering fails. Receives the error, the current items before the attempted reorder, and the next items from the attempted reorder. |
MainWraps your app's main content area.
| Name | Type | Required | Description |
|---|---|---|---|
children | ForgeElement | Yes | Your app's main content. |
HelpLinkRenders a help link in the app header. Use it to direct users to support, documentation, or other help resources for your app.
| Name | Type | Required | Description |
|---|---|---|---|
href | string | Yes | The URL opened when the help link is selected. |
PersonalSettingsRenders a personal settings menu in the app header. Use it to group user-specific settings and account actions.
| Name | Type | Required | Description |
|---|---|---|---|
children | ForgeElement | Yes | Accepts PersonalSettingsItem components. |
PersonalSettingsItemRenders an item inside the personal settings menu.
| Name | Type | Required | Description |
|---|---|---|---|
label | string | Yes | The text displayed for the settings item. |
onClick | () => void | Yes | The handler called when the item is selected. |
CreateButtonRenders a create button in the app header. Use it to expose one or more create actions for your app.
| Name | Type | Required | Description |
|---|---|---|---|
children | ForgeElement | Yes | Accepts CreateMenuItem components. |
CreateMenuItemRenders an item inside the create menu.
| Name | Type | Required | Description |
|---|---|---|---|
label | string | Yes | The text displayed for the create action. |
onClick | () => void | Yes | The handler called when the item is selected. |
The header is rendered automatically. You do not configure it in code. It uses the following properties from your manifest:
| Manifest property | Description |
|---|---|
title | Displayed in the header next to your app icon. Also appears in the Atlassian app switcher. |
icon | A reference to a local SVG resource, in the format resource:<resource-key>;<filename>. Displayed as a 24×24px icon in the header. In smaller viewports, only the icon is shown. |
The header automatically includes:
title and icon. Selecting it navigates to the root
route (/).For details on configuring title and icon, see the global:ui module reference.
<Sidebar> and <Main> must both be present as direct children of <Global>.global:ui. The platform enforces a UI chrome around the module
and UI Kit is the public API that lets you control it. To embed custom web content in the main
content area, use the Frame component inside <Main>./for-you and acts as the app's home page.
Set forYouMenuItem to false to hide it; the app then uses the root route / as the home page.The following example assembles a complete app layout with header actions, sidebar navigation, and main content:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105import React, { useState } from "react"; import ForgeReconciler, { Button, Text } from "@forge/react"; import { Global, Sidebar, LinkMenuItem, ExpandableMenuItem, MenuSection, HelpLink, PersonalSettings, PersonalSettingsItem, ReorderableMenuItems, CreateButton, CreateMenuItem, FlyOutMenuItem, Main, } from "@forge/react/global"; const initialNotes = [ { id: "1", label: "Document 1", href: "/notes/1" }, { id: "2", label: "Document 2", href: "/notes/2" }, { id: "3", label: "Document 3", href: "/notes/3" }, ]; const App = () => { const [notes, setNotes] = useState(initialNotes); const [message, setMessage] = useState( "Select an action from the header or sidebar." ); const handleCreateDocument = () => { setMessage("Create document selected."); }; const handleCreateFolder = () => { setMessage("Create folder selected."); }; return ( <Global> <HelpLink href="https://support.atlassian.com/" /> <CreateButton> <CreateMenuItem label="Create document" onClick={handleCreateDocument} /> <CreateMenuItem label="Create folder" onClick={handleCreateFolder} /> </CreateButton> <PersonalSettings> <PersonalSettingsItem label="Notification preferences" onClick={() => {}} /> <PersonalSettingsItem label="Preferences" onClick={() => {}} /> </PersonalSettings> <Sidebar> <LinkMenuItem label="Reports" href="/reports" icon="chart-bar" /> <LinkMenuItem label="Recent" href="/recent" /> <MenuSection label="Dashboards"> <LinkMenuItem label="Sales performance" href="/reports/sales-performance" /> <LinkMenuItem label="Team activity" href="/reports/team-activity" /> </MenuSection> <ExpandableMenuItem label="Projects"> <LinkMenuItem label="Project Alpha" href="/projects/alpha" /> <LinkMenuItem label="Project Beta" href="/projects/beta" /> </ExpandableMenuItem> <FlyOutMenuItem label="Resources"> <LinkMenuItem label="Documentation" href="/resources/docs" /> <LinkMenuItem label="Templates" href="/resources/templates" /> </FlyOutMenuItem> <ReorderableMenuItems items={notes} onReorder={(items) => { setNotes(items); setMessage("Sidebar order changed."); }} onError={(error, currentItems, nextItems) => { console.error("Failed to persist sidebar order:", error); }} /> </Sidebar> <Main> <Text>{message}</Text> <Button onClick={() => setMessage("Main content action selected.")}> Run action </Button> </Main> </Global> ); }; ForgeReconciler.render( <React.StrictMode> <App /> </React.StrictMode> );
If using a Frame component in the Main content area of your app, there may be scenarios where you want to update the app state from within the Frame resource. You can use the dispatch prop to define a function that can be called inside the resource to dispatch updates to its parent.
The implementation of the function is up to you, although the most common pattern will be to use a reducer and its associated dispatch function. This is a pattern that will be familiar to developers who have used React’s useReducer hook or React Redux for complex state management.
In the main app, the sidebar state is defined as a list of items that can be dynamically updated, with each item mapping to a LinkMenuItem component. The reducer is a pure function that updates the state based on a provided action, which it receives when dispatch is called.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69import React, { useReducer } from "react"; import ForgeReconciler, { Frame } from "@forge/react"; import { Global, Sidebar, LinkMenuItem, LinkMenuItemProps, Main, } from "@forge/react/global"; interface GlobalState { sidebar: LinkMenuItemProps[]; } type AddSidebarItemAction = { type: "ADD_SIDEBAR_ITEM"; item: LinkMenuItemProps; }; const initialState: GlobalState = { sidebar: [ { id: "dashboard", label: "Dashboard", href: "/dashboard" }, { id: "bugs", label: "Bugs", href: "/bugs" }, { id: "reports", label: "Reports", type: "expandable", children: [ { id: "weekly", label: "Weekly", href: "/reports/weekly" }, { id: "monthly", label: "Monthly", href: "/reports/monthly" }, ], }, ], }; const reducer = (state: GlobalState, action: Action) => { switch (action.type) { case "ADD_SIDEBAR_ITEM": return { ...state, sidebar: [...state.sidebar, action.item], }; default: return state; } }; const App = () => { const [state, dispatch] = useReducer(reducer, initialState); return ( <Global> <Sidebar> {state.sidebar.map((item) => ( <LinkMenuItem key={item.id} {...item} /> ))} </Sidebar> <Main> <Frame resource="my-resource" dispatch={dispatch} /> </Main> </Global> ); }; ForgeReconciler.render( <React.StrictMode> <App /> </React.StrictMode> );
Inside the resource, the dispatch function can be retrieved by calling view.getFrameDispatch(). It can then be used to dispatch actions to the parent to trigger state updates. In this example, it adds a new Settings item to the sidebar menu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41import React, { useEffect, useState } from "react"; import { view } from "@forge/bridge"; const App = () => { const [dispatch, setDispatch] = useState(undefined); useEffect(() => { view .getFrameDispatch() // If using React to set the dispatch function in state to use, make sure to // wrap it in a callback. Otherwise React treats dispatch as a functional updater // and tries to execute it. .then((dispatch) => setDispatch(() => dispatch)); }, []); if (!dispatch) { return <div>Loading...</div>; } return ( <div> <button onClick={() => dispatch({ type: "ADD_SIDEBAR_ITEM", item: { id: "settings", label: "Settings", href: "/settings", }, }) } > Add Settings menu item </button> </div> ); }; export default App;
Rate this page: