> Note:
> This is a legacy API. Use the latest version of [`TitleBar`](/docs/api/app-bridge-library/web-components/ui-title-bar) instead.

The `TitleBar` action set allows you to populate a standardized title bar with button actions and navigation breadcrumbs.

<img alt="A close-up image of a title bar within the Shopify admin. The title bar displays the title: Breadcrumbs / Title. It also displays two buttons: a white button with the label Secondary Action, and a green button with the label Primary Action." src="/assets/apps/tools/app-bridge-title-bar.png" style="display: block; width: 100%; max-width: 524px">

You can use the title bar in the following ways:

1. [Plain JavaScript](#plain-javascript)
2. [React component](#react)

## Plain JavaScript

### Example code

Import the `createApp` function from `@shopify/app-bridge` and the `TitleBar` from `@shopify/app-bridge/actions`. Then use the `createApp` function to create an app.

> Note
> In the following example, `config` is a valid App Bridge configuration object. Learn more about [configuring App Bridge](/docs/api/app-bridge/previous-versions/app-bridge-from-npm/app-setup#initialize-shopify-app-bridge-in-your-app).


```js
import createApp from '@shopify/app-bridge';
import { TitleBar } from '@shopify/app-bridge/actions';

const app = createApp(config);
```

### Create a title bar

Create a title bar with the title set to `My page title`:

```js
const titleBarOptions = {
  title: 'My page title',
};

const myTitleBar = TitleBar.create(app, titleBarOptions);
```

### Create a title bar with a primary button

Set the title bar's primary button to a button. To learn more about buttons, refer to [Button](/docs/api/app-bridge/previous-versions/actions/button).

```js
const saveButton = Button.create(app, { label: 'Save' });
const titleBarOptions = {
  title: 'My page title',
  buttons: {
    primary: saveButton,
  },
};

const myTitleBar = TitleBar.create(app, titleBarOptions);
```

### Create a title bar with secondary buttons

Set the title bar's secondary buttons to one or more buttons. The following example creates a secondary action with the label **Settings**, which triggers a redirect to a settings page local to the app.

To learn more about buttons and redirects, refer to [Button](/docs/api/app-bridge/previous-versions/actions/button) and [Redirect](/docs/api/app-bridge/previous-versions/actions/navigation/redirect-navigate).

```js
import { TitleBar, Button, Redirect } from '@shopify/app-bridge/actions';
const settingsButton = Button.create(app, { label: 'Settings' });
const redirect = Redirect.create(app);

settingsButton.subscribe('click', () => {
  redirect.dispatch({
    type: Redirect.Action.APP,
    payload: { path: '/settings' },
  });
});

const titleBarOptions = {
  title: 'My new title',
  buttons: {
    secondary: [settingsButton],
  },
};

const myTitleBar = TitleBar.create(app, titleBarOptions);
```

### Create a title bar with grouped secondary buttons

Set the title bar's secondary buttons to one or more button groups. The following example creates a grouped secondary action with the label **More actions**, which contains two child buttons.

To learn more about button groups, refer to [ButtonGroup](/docs/api/app-bridge/previous-versions/actions/buttongroup) and [Button](/docs/api/app-bridge/previous-versions/actions/button).

```js
import { TitleBar, Button, ButtonGroup } from '@shopify/app-bridge/actions';

const button1 = Button.create(app, { label: 'Show toast message' });
const button2 = Button.create(app, { label: 'Open modal' });

const moreActions = ButtonGroup.create(app, {
  label: 'More actions',
  buttons: [button1, button2],
});

const titleBarOptions = {
  title: 'My new title',
  buttons: {
    secondary: [moreActions],
  },
};
const myTitleBar = TitleBar.create(app, titleBarOptions);
```

### Update title bar options

Call the `set` method with partial title bar options to update the options of an existing title bar. This automatically triggers the `update` action on the title bar and merges the given options with the existing options.

```js
const titleBarOptions = {
  title: 'My page title',
};

const myTitleBar = TitleBar.create(app, titleBarOptions);
// Update the title

myTitleBar.set({
  title: 'My new title',
});
```

> Note
> If your app contains a contextual save bar, you will not be able to make any updates to the title bar buttons while a contextual save bar is being shown. In addition, all title bar buttons will be disabled automatically while the contextual save bar is displayed. The disabled state of the title bar buttons are reset to their previous states when the contextual save bar is hidden. To learn more about the contextual save bar, see [Contextual Save Bar action](/docs/api/app-bridge/previous-versions/actions/contextualsavebar).

### Update title bar primary/secondary buttons

You can update buttons attached to a title bar. Any updates made to the title bar's children automatically trigger an `update` action on the title bar:

```js
import { TitleBar, Button, ButtonGroup } from '@shopify/app-bridge/actions';

const button1 = Button.create(app, { label: 'Show toast message' });
const button2 = Button.create(app, { label: 'Open modal' });

const moreActions = ButtonGroup.create(app, {
  label: 'More actions',
  buttons: [button1, button2],
});

const titleBarOptions = {
  title: 'My new title',
  buttons: {
    secondary: [moreActions],
  },
};

const myTitleBar = TitleBar.create(app, titleBarOptions);
// Update more button's label - changes automatically get propagated to the parent title bar
moreActions.set({
  label: 'Additional options',
});
```

> Note
> If your app contains a contextual save bar, you will not be able to make any updates to the title bar buttons while a contextual save bar is being shown. In addition, all title bar buttons will be disabled automatically while the contextual save bar is displayed. The disabled state of the title bar buttons are reset to their previous states when the contextual save bar is hidden. To learn more about the contextual save bar, see [Contextual Save Bar action](/docs/api/app-bridge/previous-versions/actions/contextualsavebar).

### Create a title bar with breadcrumbs

Enable breadcrumbs in the title bar by setting a button as the breadcrumb option. You can disable it by setting the option to `undefined`. **Note:** Breadcrumbs aren't shown without a title. The following example creates a breadcrumb with the label 'My Breadcrumb', which links to '/breadcrumb-link'.

To learn more about buttons and redirects, refer to [Button](/docs/api/app-bridge/previous-versions/actions/button) and [Redirect](/docs/api/app-bridge/previous-versions/actions/navigation/redirect-navigate).

```js
import { TitleBar, Button, Redirect } from '@shopify/app-bridge/actions';

const breadcrumb = Button.create(app, { label: 'My Breadcrumb' });

breadcrumb.subscribe(Button.Action.CLICK, () => {
  app.dispatch(Redirect.toApp({ path: '/breadcrumb-link' }));
});

const titleBarOptions = {
  title: 'My new title',
  breadcrumbs: breadcrumb,
};

const myTitleBar = TitleBar.create(app, titleBarOptions);
```

### Subscribe to title bar updates

You can subscribe to the title bar update action by calling `subscribe`. This returns a function that you can call to unsubscribe from the action:

```js
// Using the same title bar as above
const updateUnsubscribe = myTitleBar.subscribe(
  ButtonGroup.Action.UPDATE,
  data => {
    // Do something when the button group is updated
    // The data is in the following shape: {id: string, label: string, buttons: [{id: string, label: string, disabled: boolean} ...]}
  }
);

// Unsubscribe
updateUnsubscribe();
```

### Unsubscribe

You call `unsubscribe` to remove all subscriptions on the titlebar and its children:

```js
const settingsButton = Button.create(app, { label: 'Settings' });
settingsButton.subscribe('click', () => {
  redirect.dispatch({
    type: Redirect.Action.APP,
    payload: { path: '/settings' },
  });
});
const titleBarOptions = {
  title: 'My new title',
  buttons: {
    secondary: [settingsButton],
  },
};
const myTitleBar = TitleBar.create(app, titleBarOptions);

myTitleBar.subscribe(TitleBar.Action.UPDATE, data => {
  // Do something with the update action
});

// Unsubscribe from the button group update action
// Unsubscribe from settingsButton click action
myTitleBar.unsubscribe();
```

### Unsubscribe from titlebar actions only

You call `unsubscribe` with `false` to remove only titlebar subscriptions while leaving child subscriptions intact. For example, you might want to unsubscribe from the title bar but keep button listeners so that the buttons can be reused in a different actions (such as a modal).

```js
const settingsButton = Button.create(app, { label: 'Settings' });
settingsButton.subscribe('click', () => {
  redirect.dispatch({
    type: Redirect.Action.APP,
    payload: { path: '/settings' },
  });
});
const titleBarOptions = {
  title: 'My new title',
  buttons: {
    secondary: [settingsButton],
  },
};
const myTitleBar = TitleBar.create(app, titleBarOptions);

myTitleBar.subscribe(TitleBar.Action.UPDATE, data => {
  // Do something with the update action
  // The data is in the following shape: {id: string, title: string, buttons: [{id: string, label: string, disabled: boolean} ...]}
});

// Unsubscribe from the titlebar update action
myTitleBar.unsubscribe(false);

// Reuse settingsButton in a modal
const modalOptions = {
  title: 'My Modal',
  message: 'Hello world!',
  footer: { primary: settingsButton },
};

const myModal = Modal.create(app, modalOptions);
```

## React

### Example code

Import the `Provider` and `TitleBar` component from `@shopify/app-bridge-react`. Only one `Provider` is needed for your application.

> Note
> In the following example, `config` is a valid App Bridge configuration object. Learn more about [configuring App Bridge](/docs/api/app-bridge/previous-versions/app-bridge-from-npm/app-setup#initialize-shopify-app-bridge-in-your-app).


```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider, TitleBar} from '@shopify/app-bridge-react';

function MyApp() {
  const primaryAction = {content: 'Foo', url: '/foo'};
  const secondaryActions = [{content: 'Bar', url: '/bar', loading: true}];
  const actionGroups = [{title: 'Baz', actions: [{content: 'Baz', url: '/baz'}]}];

  return (
    <Provider config={config}>
      <TitleBar
        title="Hello world!"
        primaryAction={primaryAction}
        secondaryActions={secondaryActions}
        actionGroups={actionGroups}
      />
    </Provider>
  );
}

const root = document.createElement('div');
document.body.appendChild(root);
ReactDOM.createRoot(root).render(<MyApp />);
```

### Props

|Name|Type|Description|Required|
|---|---|---|---|
|title|`string`|TitleBar title|Yes|
|breadcrumbs|`Breadcrumb[]`|An array of breadcrumbs||
|primaryAction|`ActionProps`|Primary TitleBar action||
|secondaryActions|`ActionProps[]`|An array of secondary TitleBar actions||
|actionGroups|`ActionGroupProps[]`|An array of TitleBar groups of secondary actions||

#### Breadcrumb

|Name|Type|Description|Required|
|---|---|---|---|
|content|`string`|Content the action displays||
|url|`string`|A destination to link to||
|target|`"ADMIN_PATH"`, `"REMOTE"`, `"APP"`|Where to display the target link||
|onAction|`() => void`|Callback when an action takes place||

#### ActionProps

|Name|Type|Description|Required|
|---|---|---|---|
|content|`string`|Content the action displays|No|
|destructive|`boolean`|Should the action be styled as destructive|No|
|disabled|`boolean`|Should the action be disabled|No|
|external|`boolean`|Forces url to open in a new tab|No|
|loading|`boolean`|Should the action be loading|No|
|target|`"ADMIN_PATH"`, `"REMOTE"`, `"APP"`|Where to display the target link|No|
|url|`string`|A destination to link to|No|
|onAction|`() => void`|Callback when an action takes place|No|

#### ActionGroupProps

|Name|Type|Description|Required|
|---|---|---|---|
|title|`string`|Action group title|Yes|
|actions|`ActionProps[]`|List of actions|Yes|


## Using TitleBar with Polaris

When used with embedded app functionality, the Polaris `<Page>` component still renders important layout elements. App Bridge React’s `<TitleBar>` does not. Because of this, the recommended migration path is to keep the `<Page>` element, but pass its props to `<TitleBar>` instead.

The following examples show the migration path, starting with the use of deprecated Polaris embedded app functionality.

```jsx
import { AppProvider, Page } from "@shopify/polaris";

function MyApp() {
  return (
    <AppProvider apiKey="api_key" host="example.myshopify.com">
      <Page
        title="My App using legacy code"
        breadcrumbs={[{ content: "Breadcrumb" }]}
        primaryAction={primaryAction}
        secondaryActions={secondaryActions}
        actionGroups={actionGroups}
      >
        {content}
      </Page>
    </AppProvider>
  );
}
```

The recommended migration path uses App Bridge React along with the Polaris `<Page>` component.

```jsx
import { AppProvider, Page } from "@shopify/polaris";
import {
  Provider as AppBridgeProvider,
  TitleBar
} from "@shopify/app-bridge-react";

function MyApp() {
  const config = {
    // The client ID provided for your application in the Partner Dashboard.
    apiKey: "api_key",
    // The host of the specific shop that's embedding your app. This value is provided by Shopify as a URL query parameter that's appended to your application URL when your app is loaded inside the Shopify admin.
    host: "example.myshopify.com"
  }

  return (
    <AppProvider>
      <AppBridgeProvider
        config={config}
      >
        <Page>
          <TitleBar
            title="My App using up-to-date code"
            breadcrumbs={[{ content: "Breadcrumb" }]}
            primaryAction={primaryAction}
            secondaryActions={secondaryActions}
            actionGroups={actionGroups}
          />
          {content}
        </Page>
      </AppBridgeProvider>
    </AppProvider>
  );
}
```