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.
ProgressIndicator
The ProgressIndicator component displays an animated spinner to communicate that content is loading or an action is being processed. Use ProgressIndicator to provide visual feedback during asynchronous operations like data fetching, form submission, or background processing.
ProgressIndicator supports a range of sizes from compact inline indicators to larger full-section spinners, so it can be placed alongside other components or used as a standalone loading state.
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 ProgressIndicator component, which renders a visual cue (such as a spinner) to communicate that a process is underway. Use this component to reassure users that content is loading or an action is being processed.
- Anchor to sizesizesizeSizeScaleSizeScalerequiredrequired
The size of the progress indicator. This prop is required and determines how large the indicator renders. Use smaller sizes for inline or compact placements, and larger sizes for prominent loading states.
- Anchor to accessibilityLabelaccessibilityLabelaccessibilityLabelstringstring
A label that describes the purpose or contents of the element. When set, it will be announced to users using assistive technologies and will provide them with more context. When set, any children or
labelsupplied won't be announced to screen readers.- Anchor to idididstringstring
A unique identifier for the element.
- Anchor to tonetonetone'inherit' | 'default''inherit' | 'default'Default: 'default'Default: 'default'
The color of the progress indicator.
inherit: Takes the color value from its parent, giving the progress indicator a monochrome appearance. This is useful when you want the indicator to blend with surrounding text or icons.default: Uses the standard progress indicator color.
- Anchor to variantvariantvariant'spinner''spinner'Default: 'spinner'Default: 'spinner'
The visual style of the progress indicator.
spinner: Renders a circular spinning animation to indicate an indeterminate loading state.
SizeScale
A relative size scale used for typography sizing. Values range from smallest to largest: - `small-300`: The smallest available size. - `small-200`: Smaller than small-100. - `small-100`: Slightly below the base size. - `base`: The default size. - `large-100`: Slightly above the base size. - `large-200`: Larger than large-100. - `large-300`: The largest available size.
'small-300' | 'small-200' | 'small-100' | 'base' | 'large-100' | 'large-200' | 'large-300'Anchor to ExamplesExamples
Anchor to Show loading during API queryShow loading during API query
Show a loading indicator while querying product data from the GraphQL Admin API, then replace it with the results. This example uses ProgressIndicator with size and accessibilityLabel props during the query, then displays the product title and inventory count.
Show loading during API query
, then replace it with the results. This example uses `ProgressIndicator` with `size` and `accessibilityLabel` props during the query, then displays the product title and inventory count.](https://cdn.shopify.com/shopifycloud/shopify-dev/production/assets/assets/images/templated-apis-screenshots/admin-extensions/2025-07/progressindicator-default-CmcDGbTw.png)
Show loading during API query
React
import {useState, useEffect} from 'react';
import {reactExtension, useApi, ProgressIndicator, Text, BlockStack} from '@shopify/ui-extensions-react/admin';
function App() {
const {data, query} = useApi('admin.product-details.block.render');
const productId = data.selected[0]?.id;
const [product, setProduct] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
query(
`query Product($id: ID!) {
product(id: $id) { title totalInventory }
}`,
{variables: {id: productId}},
).then((result) => {
setProduct(result?.data?.product);
setLoading(false);
});
}, [productId, query]);
return (
<BlockStack>
{loading ? (
<ProgressIndicator
size="small-200"
accessibilityLabel="Loading product data"
/>
) : product ? (
<>
<Text fontWeight="bold">{product.title}</Text>
<Text>Total inventory: {product.totalInventory} units</Text>
</>
) : null}
</BlockStack>
);
}
export default reactExtension(
'admin.product-details.block.render',
() => <App />,
);TS
import {extension, ProgressIndicator, Text, BlockStack} from '@shopify/ui-extensions/admin';
export default extension(
'admin.product-details.block.render',
async (root, api) => {
const {data, query} = api;
const productId = data.selected[0]?.id;
const stack = root.createComponent(BlockStack);
const loader = root.createComponent(ProgressIndicator, {
size: 'small-200',
accessibilityLabel: 'Loading product data',
});
stack.appendChild(loader);
root.appendChild(stack);
const result = await query(
`query Product($id: ID!) {
product(id: $id) { title totalInventory }
}`,
{variables: {id: productId}},
);
stack.removeChild(loader);
const product = result?.data?.product;
if (product) {
const title = root.createComponent(
Text,
{fontWeight: 'bold'},
product.title,
);
const inventory = root.createComponent(
Text,
{},
`Total inventory: ${product.totalInventory} units`,
);
stack.appendChild(title);
stack.appendChild(inventory);
}
},
);Anchor to Display sync progress in action modalDisplay sync progress in action modal
Show a prominent loading indicator while a sync is in progress inside an action modal. This example pairs a base-sized indicator with a status message and a cancel Button, keeping merchants informed and in control.
Display sync progress in action modal
React
import {reactExtension, ProgressIndicator, Text, Button, BlockStack, InlineStack} from '@shopify/ui-extensions-react/admin';
function App() {
const {data, close} = useApi('admin.product-details.action.render');
return (
<BlockStack>
<Text>Syncing product data to your warehouse system...</Text>
<InlineStack>
<ProgressIndicator
size="base"
accessibilityLabel="Syncing in progress"
/>
</InlineStack>
<Button variant="tertiary" onPress={() => close()}>
Cancel
</Button>
</BlockStack>
);
}
export default reactExtension(
'admin.product-details.action.render',
() => <App />,
);TS
import {extension, ProgressIndicator, Text, Button, BlockStack, InlineStack} from '@shopify/ui-extensions/admin';
export default extension(
'admin.product-details.action.render',
(root, api) => {
const {data, close} = api;
const stack = root.createComponent(BlockStack);
const message = root.createComponent(
Text,
{},
'Syncing product data to your warehouse system...',
);
const spinnerRow = root.createComponent(InlineStack);
const spinner = root.createComponent(ProgressIndicator, {
size: 'base',
accessibilityLabel: 'Syncing in progress',
});
spinnerRow.appendChild(spinner);
const cancelButton = root.createComponent(
Button,
{
variant: 'tertiary',
onPress: () => close(),
},
'Cancel',
);
stack.appendChild(message);
stack.appendChild(spinnerRow);
stack.appendChild(cancelButton);
root.appendChild(stack);
},
);Anchor to Add inline loading indicatorAdd inline loading indicator
Place a compact small-300 spinner inline with status text using tone="inherit" to match the surrounding text color. This example renders the indicator alongside a description inside an InlineStack, creating a subtle loading cue.
Add inline loading indicator
React
import {reactExtension, ProgressIndicator, Text, InlineStack, BlockStack} from '@shopify/ui-extensions-react/admin';
function App() {
return (
<BlockStack>
<Text fontWeight="bold">Checking eligibility...</Text>
<InlineStack>
<ProgressIndicator
size="small-300"
tone="inherit"
accessibilityLabel="Checking product eligibility"
/>
<Text>Verifying product meets marketplace requirements</Text>
</InlineStack>
</BlockStack>
);
}
export default reactExtension(
'admin.product-details.block.render',
() => <App />,
);TS
import {extension, ProgressIndicator, Text, InlineStack, BlockStack} from '@shopify/ui-extensions/admin';
export default extension(
'admin.product-details.block.render',
(root) => {
const stack = root.createComponent(BlockStack);
const heading = root.createComponent(
Text,
{fontWeight: 'bold'},
'Checking eligibility...',
);
const row = root.createComponent(InlineStack);
const indicator = root.createComponent(ProgressIndicator, {
size: 'small-300',
tone: 'inherit',
accessibilityLabel: 'Checking product eligibility',
});
const label = root.createComponent(
Text,
{},
'Verifying product meets marketplace requirements',
);
row.appendChild(indicator);
row.appendChild(label);
stack.appendChild(heading);
stack.appendChild(row);
root.appendChild(stack);
},
);Anchor to Best practicesBest practices
- Match the size to the context: Use smaller sizes for inline indicators next to buttons or fields, and larger sizes for full-section or full-page loading states.
- Show spinners only when needed: Display the ProgressIndicator only while an operation is in progress. Remove it immediately when loading completes or an error occurs. Avoid leaving a spinner visible indefinitely.
Anchor to LimitationsLimitations
- ProgressIndicator supports only the
spinnervariant. There is no progress bar or determinate progress indicator available. - ProgressIndicator doesn't communicate progress percentage or estimated time remaining. For operations where progress can be measured, consider pairing the spinner with a text description of the current status.
- The spinner animation can't be paused or customized. It always displays the same continuous rotation animation.