Version 2025-07 is the last API version to support React-based UI components. Later versions use web components, native UI elements with built-in accessibility, better performance, and consistent styling with Shopify's design system. Check out the migration guide to upgrade your extension.
Button
The Button component triggers actions like submitting forms, opening dialogs, or navigating to other pages. It supports multiple visual variants and tones to establish a clear hierarchy of actions within your extension.
For navigation-focused interactions within text, use Link. To make a custom area clickable without button styling, use Pressable.
Supported targets
- admin.
abandoned-checkout-details. action. render - admin.
abandoned-checkout-details. block. render - admin.
catalog-details. action. render - admin.
catalog-details. block. render - admin.
collection-details. action. render - admin.
collection-details. block. render - admin.
collection-index. action. render - admin.
company-details. action. render - admin.
company-details. block. render - admin.
company-location-details. block. render - admin.
customer-details. action. render - admin.
customer-details. block. render - admin.
customer-index. action. render - admin.
customer-index. selection-action. render - admin.
customer-segment-details. action. render - admin.
discount-details. action. render - admin.
discount-details. function-settings. render - admin.
discount-index. action. render - admin.
draft-order-details. action. render - admin.
draft-order-details. block. render - admin.
draft-order-index. action. render - admin.
draft-order-index. selection-action. render - admin.
gift-card-details. action. render - admin.
gift-card-details. block. render - admin.
order-details. action. render - admin.
order-details. block. render - admin.
order-details. print-action. render - admin.
order-fulfilled-card. action. render - admin.
order-index. action. render - admin.
order-index. selection-action. render - admin.
order-index. selection-print-action. render - admin.
product-details. action. render - admin.
product-details. block. render - admin.
product-details. configuration. render - admin.
product-details. print-action. render - admin.
product-details. reorder. render - admin.
product-index. action. render - admin.
product-index. selection-action. render - admin.
product-index. selection-print-action. render - admin.
product-purchase-option. action. render - admin.
product-variant-details. action. render - admin.
product-variant-details. block. render - admin.
product-variant-details. configuration. render - admin.
product-variant-purchase-option. action. render - admin.
settings. order-routing-rule. render - admin.
settings. validation. render
Supported targets
- admin.
abandoned-checkout-details. action. render - admin.
abandoned-checkout-details. block. render - admin.
catalog-details. action. render - admin.
catalog-details. block. render - admin.
collection-details. action. render - admin.
collection-details. block. render - admin.
collection-index. action. render - admin.
company-details. action. render - admin.
company-details. block. render - admin.
company-location-details. block. render - admin.
customer-details. action. render - admin.
customer-details. block. render - admin.
customer-index. action. render - admin.
customer-index. selection-action. render - admin.
customer-segment-details. action. render - admin.
discount-details. action. render - admin.
discount-details. function-settings. render - admin.
discount-index. action. render - admin.
draft-order-details. action. render - admin.
draft-order-details. block. render - admin.
draft-order-index. action. render - admin.
draft-order-index. selection-action. render - admin.
gift-card-details. action. render - admin.
gift-card-details. block. render - admin.
order-details. action. render - admin.
order-details. block. render - admin.
order-details. print-action. render - admin.
order-fulfilled-card. action. render - admin.
order-index. action. render - admin.
order-index. selection-action. render - admin.
order-index. selection-print-action. render - admin.
product-details. action. render - admin.
product-details. block. render - admin.
product-details. configuration. render - admin.
product-details. print-action. render - admin.
product-details. reorder. render - admin.
product-index. action. render - admin.
product-index. selection-action. render - admin.
product-index. selection-print-action. render - admin.
product-purchase-option. action. render - admin.
product-variant-details. action. render - admin.
product-variant-details. block. render - admin.
product-variant-details. configuration. render - admin.
product-variant-purchase-option. action. render - admin.
settings. order-routing-rule. render - admin.
settings. validation. render
Anchor to PropertiesProperties
Props for the Button component. A button can either be a standard action button () or an anchor-style button that navigates to a URL ().
- stringstringrequiredrequired
The URL to navigate to when the button is pressed. When set, the button behaves as a link. If an
callback is also provided, it runs first, then the navigation occurs.- stringstring
A label read by assistive technologies like screen readers to describe the button's purpose. Use this when the button contains only an icon or when the visible text doesn't provide enough context on its own for users who can't see the button.
- booleanbooleanDefault: falseDefault: false
Whether the button is disabled. When
true, the button can't be interacted with and is rendered in a visually muted style to indicate it isn't available.- boolean | stringboolean | string
When set, the linked resource is downloaded instead of being navigated to. Pass a string to specify a custom filename for the downloaded file, or
trueto use the default filename.- stringstring
A unique identifier for the button. Use this when you need to reference the button programmatically or distinguish it from other buttons in the same view.
- stringstring
An alias for
language. The language of the button's text content. Use this when the button text is in a different language than the rest of the page so assistive technologies can invoke the correct pronunciation. Must be a valid IANA language subtag.- stringstring
The language of the button's text content. Use this when the button text is in a different language than the rest of the page so assistive technologies can invoke the correct pronunciation. Must be a valid IANA language subtag.
- () => void() => void
A callback fired when the button loses focus. Use this to trigger validation or other logic when the merchant moves away from the button.
- () => void() => void
A callback fired when the link button is pressed. The callback runs first, then the navigation to
hrefoccurs.- () => void() => void
A callback fired when the button receives focus. Use this to trigger logic when the merchant focuses the button through keyboard navigation or other input methods.
- () => void() => void
An alias for
. A callback fired when the link button is pressed. The callback runs first, then the navigation tohrefoccurs.- '_blank' | '_self''_blank' | '_self'Default: '_self'Default: '_self'
The browsing context in which to open the linked URL.
_blank: Opens in a new tab or window._self: Opens in the same context (default).
- stringstring
An alias for
href. The URL to navigate to when the button is pressed.- 'default' | 'critical''default' | 'critical'Default: 'default'Default: 'default'
The color treatment of the button, used to convey its intent.
default: Standard button color for general actions.critical: Red coloring to indicate a destructive or irreversible action, such as deleting a resource.
- 'primary' | 'secondary' | 'tertiary''primary' | 'secondary' | 'tertiary'Default: 'secondary'Default: 'secondary'
The visual style of the button, used to convey its level of emphasis.
primary: A high-emphasis button for the main action in a section.secondary: A medium-emphasis button for supporting actions.tertiary: A low-emphasis button for less prominent actions, rendered as a plain text link-style button.
- stringstring
A label read by assistive technologies like screen readers to describe the button's purpose. Use this when the button contains only an icon or when the visible text doesn't provide enough context on its own for users who can't see the button.
- Default: 'button'Default: 'button'
The semantic role of the button for assistive technologies.
submit: Submits the nearest containing form when pressed.button: A standard button that triggers an action (default).reset: Resets the nearest containing form to its default values.
- booleanbooleanDefault: falseDefault: false
Whether the button is disabled. When
true, the button can't be interacted with and is rendered in a visually muted style to indicate it isn't available.- stringstring
A unique identifier for the button. Use this when you need to reference the button programmatically or distinguish it from other buttons in the same view.
- stringstring
An alias for
language. The language of the button's text content. Use this when the button text is in a different language than the rest of the page so assistive technologies can invoke the correct pronunciation. Must be a valid IANA language subtag.- stringstring
The language of the button's text content. Use this when the button text is in a different language than the rest of the page so assistive technologies can invoke the correct pronunciation. Must be a valid IANA language subtag.
- () => void() => void
A callback fired when the button loses focus. Use this to trigger validation or other logic when the merchant moves away from the button.
- () => void() => void
A callback fired when the button is pressed. If
hrefis set, the callback runs first, then the navigation occurs.- () => void() => void
A callback fired when the button receives focus. Use this to trigger logic when the merchant focuses the button through keyboard navigation or other input methods.
- () => void() => void
An alias for
. A callback fired when the button is pressed. Ifhrefis set, the callback runs first, then the navigation occurs.- 'default' | 'critical''default' | 'critical'Default: 'default'Default: 'default'
The color treatment of the button, used to convey its intent.
default: Standard button color for general actions.critical: Red coloring to indicate a destructive or irreversible action, such as deleting a resource.
- 'primary' | 'secondary' | 'tertiary''primary' | 'secondary' | 'tertiary'Default: 'secondary'Default: 'secondary'
The visual style of the button, used to convey its level of emphasis.
primary: A high-emphasis button for the main action in a section.secondary: A medium-emphasis button for supporting actions.tertiary: A low-emphasis button for less prominent actions, rendered as a plain text link-style button.
ButtonBaseProps
Props for a standard action button that triggers behavior when pressed. Extends `CommonProps` and adds an `accessibilityRole` to control the semantic role (button, submit, or reset).
- accessibilityLabel
A label read by assistive technologies like screen readers to describe the button's purpose. Use this when the button contains only an icon or when the visible text doesn't provide enough context on its own for users who can't see the button.
string - accessibilityRole
The semantic role of the button for assistive technologies. - `submit`: Submits the nearest containing form when pressed. - `button`: A standard button that triggers an action (default). - `reset`: Resets the nearest containing form to its default values.
- disabled
Whether the button is disabled. When `true`, the button can't be interacted with and is rendered in a visually muted style to indicate it isn't available.
boolean - id
A unique identifier for the button. Use this when you need to reference the button programmatically or distinguish it from other buttons in the same view.
string - lang
An alias for `language`. The language of the button's text content. Use this when the button text is in a different language than the rest of the page so assistive technologies can invoke the correct pronunciation. Must be a valid [IANA language subtag](https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry).
string - language
The language of the button's text content. Use this when the button text is in a different language than the rest of the page so assistive technologies can invoke the correct pronunciation. Must be a valid [IANA language subtag](https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry).
string - onBlur
A callback fired when the button loses focus. Use this to trigger validation or other logic when the merchant moves away from the button.
() => void - onClick
A callback fired when the button is pressed. If `href` is set, the callback runs first, then the navigation occurs.
() => void - onFocus
A callback fired when the button receives focus. Use this to trigger logic when the merchant focuses the button through keyboard navigation or other input methods.
() => void - onPress
An alias for `onClick`. A callback fired when the button is pressed. If `href` is set, the callback runs first, then the navigation occurs.
() => void - tone
The color treatment of the button, used to convey its intent. - `default`: Standard button color for general actions. - `critical`: Red coloring to indicate a destructive or irreversible action, such as deleting a resource.
'default' | 'critical' - variant
The visual style of the button, used to convey its level of emphasis. - `primary`: A high-emphasis button for the main action in a section. - `secondary`: A medium-emphasis button for supporting actions. - `tertiary`: A low-emphasis button for less prominent actions, rendered as a plain text link-style button.
'primary' | 'secondary' | 'tertiary'
ButtonAnchorProps
Props for an anchor-style button that navigates to a URL when pressed. Extends `CommonProps` and adds link-specific properties like `href`, `target`, and `download`.
- accessibilityLabel
A label read by assistive technologies like screen readers to describe the button's purpose. Use this when the button contains only an icon or when the visible text doesn't provide enough context on its own for users who can't see the button.
string - disabled
Whether the button is disabled. When `true`, the button can't be interacted with and is rendered in a visually muted style to indicate it isn't available.
boolean - download
When set, the linked resource is downloaded instead of being navigated to. Pass a string to specify a custom filename for the downloaded file, or `true` to use the default filename.
boolean | string - href
The URL to navigate to when the button is pressed. When set, the button behaves as a link. If an `onClick` callback is also provided, it runs first, then the navigation occurs.
string - id
A unique identifier for the button. Use this when you need to reference the button programmatically or distinguish it from other buttons in the same view.
string - lang
An alias for `language`. The language of the button's text content. Use this when the button text is in a different language than the rest of the page so assistive technologies can invoke the correct pronunciation. Must be a valid [IANA language subtag](https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry).
string - language
The language of the button's text content. Use this when the button text is in a different language than the rest of the page so assistive technologies can invoke the correct pronunciation. Must be a valid [IANA language subtag](https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry).
string - onBlur
A callback fired when the button loses focus. Use this to trigger validation or other logic when the merchant moves away from the button.
() => void - onClick
A callback fired when the link button is pressed. The callback runs first, then the navigation to `href` occurs.
() => void - onFocus
A callback fired when the button receives focus. Use this to trigger logic when the merchant focuses the button through keyboard navigation or other input methods.
() => void - onPress
An alias for `onClick`. A callback fired when the link button is pressed. The callback runs first, then the navigation to `href` occurs.
() => void - target
The browsing context in which to open the linked URL. - `_blank`: Opens in a new tab or window. - `_self`: Opens in the same context (default).
'_blank' | '_self' - to
An alias for `href`. The URL to navigate to when the button is pressed.
string - tone
The color treatment of the button, used to convey its intent. - `default`: Standard button color for general actions. - `critical`: Red coloring to indicate a destructive or irreversible action, such as deleting a resource.
'default' | 'critical' - variant
The visual style of the button, used to convey its level of emphasis. - `primary`: A high-emphasis button for the main action in a section. - `secondary`: A medium-emphasis button for supporting actions. - `tertiary`: A low-emphasis button for less prominent actions, rendered as a plain text link-style button.
'primary' | 'secondary' | 'tertiary'
Anchor to ExamplesExamples
Anchor to Sync product to backendSync product to backend
Sync product data to a warehouse and close the action modal, or cancel. This example renders a primary Button that posts to a backend API and calls close(), alongside a secondary cancel button.
Sync product to backend

Sync product to backend
React
import {reactExtension, useApi, Button, BlockStack, Text} from '@shopify/ui-extensions-react/admin';
function App() {
const {data, close} = useApi('admin.product-details.action.render');
const productId = data.selected[0]?.id;
return (
<BlockStack>
<Text>Product: {productId}</Text>
<Button
variant="primary"
onPress={async () => {
await fetch('/api/products/sync', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId}),
});
close();
}}
>
Sync to warehouse
</Button>
<Button variant="secondary" onPress={() => close()}>
Cancel
</Button>
</BlockStack>
);
}
export default reactExtension(
'admin.product-details.action.render',
() => <App />,
);TS
import {extension, Button, Text, BlockStack} from '@shopify/ui-extensions/admin';
export default extension(
'admin.product-details.action.render',
(root, api) => {
const {data, close} = api;
const productId = data.selected[0]?.id;
const stack = root.createComponent(BlockStack);
const info = root.createComponent(
Text,
{},
`Product: ${productId}`,
);
const saveButton = root.createComponent(Button, {
variant: 'primary',
onPress: async () => {
await fetch('/api/products/sync', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId}),
});
close();
},
}, 'Sync to warehouse');
const cancelButton = root.createComponent(Button, {
variant: 'secondary',
onPress: () => close(),
}, 'Cancel');
stack.appendChild(info);
stack.appendChild(saveButton);
stack.appendChild(cancelButton);
root.appendChild(stack);
},
);Present publish, archive, and delete actions for a product using variant and tone props to communicate intent. This example uses primary for the main action, tertiary for a low-emphasis option, and critical tone for the destructive delete.
Set button variants and tones
React
import {reactExtension, useApi, Button, BlockStack, Text} from '@shopify/ui-extensions-react/admin';
function App() {
const {data, close} = useApi('admin.product-details.action.render');
const productId = data.selected[0]?.id;
return (
<BlockStack>
<Text>Choose an action for this product:</Text>
<Button
variant="primary"
onPress={async () => {
await fetch(`/api/products/${productId}/publish`, {method: 'POST'});
close();
}}
>
Publish product
</Button>
<Button
variant="tertiary"
onPress={async () => {
await fetch(`/api/products/${productId}/archive`, {method: 'POST'});
close();
}}
>
Archive product
</Button>
<Button
tone="critical"
onPress={async () => {
await fetch(`/api/products/${productId}`, {method: 'DELETE'});
close();
}}
>
Delete product
</Button>
</BlockStack>
);
}
export default reactExtension(
'admin.product-details.action.render',
() => <App />,
);TS
import {extension, Button, BlockStack, Text} from '@shopify/ui-extensions/admin';
export default extension(
'admin.product-details.action.render',
(root, api) => {
const {data, close} = api;
const productId = data.selected[0]?.id;
const stack = root.createComponent(BlockStack);
const heading = root.createComponent(
Text,
{},
'Choose an action for this product:',
);
const publishButton = root.createComponent(Button, {
variant: 'primary',
onPress: async () => {
await fetch(`/api/products/${productId}/publish`, {method: 'POST'});
close();
},
}, 'Publish product');
const archiveButton = root.createComponent(Button, {
variant: 'tertiary',
onPress: async () => {
await fetch(`/api/products/${productId}/archive`, {method: 'POST'});
close();
},
}, 'Archive product');
const deleteButton = root.createComponent(Button, {
tone: 'critical',
onPress: async () => {
await fetch(`/api/products/${productId}`, {method: 'DELETE'});
close();
},
}, 'Delete product');
stack.appendChild(heading);
stack.appendChild(publishButton);
stack.appendChild(archiveButton);
stack.appendChild(deleteButton);
root.appendChild(stack);
},
);Anchor to Open external linksOpen external links
Link to the product storefront page and documentation using href and target props. This example renders buttons as external links that open in new tabs, and uses accessibilityLabel to provide screen reader context.
Open external links
React
import {reactExtension, useApi, Button, BlockStack, Text} from '@shopify/ui-extensions-react/admin';
function App() {
const {data} = useApi('admin.product-details.block.render');
const productId = data.selected[0]?.id;
const numericId = productId?.split('/').pop();
return (
<BlockStack>
<Text>External resources</Text>
<Button
href={`https://your-store.myshopify.com/products/${numericId}`}
target="_blank"
variant="secondary"
accessibilityLabel="View product on storefront in a new tab"
>
View on storefront
</Button>
<Button
href="https://help.shopify.com/manual/products"
target="_blank"
variant="tertiary"
>
Product documentation
</Button>
</BlockStack>
);
}
export default reactExtension(
'admin.product-details.block.render',
() => <App />,
);TS
import {extension, Button, BlockStack, Text} from '@shopify/ui-extensions/admin';
export default extension(
'admin.product-details.block.render',
(root, api) => {
const {data} = api;
const productId = data.selected[0]?.id;
const numericId = productId?.split('/').pop();
const stack = root.createComponent(BlockStack);
const label = root.createComponent(
Text,
{},
'External resources',
);
const storefrontLink = root.createComponent(Button, {
href: `https://your-store.myshopify.com/products/${numericId}`,
target: '_blank',
variant: 'secondary',
accessibilityLabel: 'View product on storefront in a new tab',
}, 'View on storefront');
const docsLink = root.createComponent(Button, {
href: 'https://help.shopify.com/manual/products',
target: '_blank',
variant: 'tertiary',
}, 'Product documentation');
stack.appendChild(label);
stack.appendChild(storefrontLink);
stack.appendChild(docsLink);
root.appendChild(stack);
},
);Anchor to Best practicesBest practices
- Label buttons clearly: Use strong, actionable verbs that describe the action, such as Save, Edit, or Add tags. Write labels in sentence case and avoid unnecessary articles like a, an, or the.
- Use appropriate tones: Apply
criticaltone only for destructive actions that are difficult or impossible to undo, such as deleting a resource. Leave the tone asdefaultfor all other actions. - Establish clear hierarchy: Avoid placing multiple primary buttons in the same view. Reserve
primaryfor the single most important action, usesecondaryfor supporting actions, andtertiaryfor low-emphasis or supplementary actions. - Position consistently: Place buttons in predictable locations. In AdminAction components, use the
primaryActionandsecondaryActionproperties. In Form components, place submit buttons at the bottom of the form. - Provide accessibility labels for icon-only usage: When using a Button without visible text, always set
accessibilityLabelso screen reader users understand the button's purpose.
Anchor to LimitationsLimitations
- The Button component doesn't include a built-in loading state. To indicate that an async operation is in progress, consider disabling the button and displaying a nearby ProgressIndicator component.
- When using
hreffor navigation, external URLs (domains outside the Shopify admin) might be blocked or trigger a confirmation dialog depending on the extension context and browser security settings. - Disabled buttons (
disabled={true}) can't receive focus or be triggered by keyboard, which may cause confusion if the reason for disabling isn't clear to the merchant. Pair disabled states with visible helper text explaining why the action is unavailable.