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.
Popover
The Popover component displays contextual content in a small overlay triggered by user interaction. Use for secondary actions, settings, or information that doesn't require a full modal.
The library automatically applies the WAI-ARIA Popover Widget pattern to both the activator and the popover content. For interactions that need more space or user focus, such as confirmations or complex forms, use Modal instead.
Supported targets
- Customer
Account::Kitchen Sink - customer-account.
footer. render-after - customer-account.
order-index. announcement. render - customer-account.
order-index. block. render - customer-account.
order-status. announcement. render - customer-account.
order-status. block. render - customer-account.
order-status. cart-line-item. render-after - customer-account.
order-status. cart-line-list. render-after - customer-account.
order-status. customer-information. render-after - customer-account.
order-status. fulfillment-details. render-after - customer-account.
order-status. payment-details. render-after - customer-account.
order-status. return-details. render-after - customer-account.
order-status. unfulfilled-items. render-after - customer-account.
order. action. menu-item. render - customer-account.
order. action. render - customer-account.
order. page. render - customer-account.
page. render - customer-account.
profile. addresses. render-after - customer-account.
profile. announcement. render - customer-account.
profile. block. render - customer-account.
profile. company-details. render-after - customer-account.
profile. company-location-addresses. render-after - customer-account.
profile. company-location-payment. render-after - customer-account.
profile. company-location-staff. render-after - customer-account.
profile. payment. render-after
Supported targets
- Customer
Account::Kitchen Sink - customer-account.
footer. render-after - customer-account.
order-index. announcement. render - customer-account.
order-index. block. render - customer-account.
order-status. announcement. render - customer-account.
order-status. block. render - customer-account.
order-status. cart-line-item. render-after - customer-account.
order-status. cart-line-list. render-after - customer-account.
order-status. customer-information. render-after - customer-account.
order-status. fulfillment-details. render-after - customer-account.
order-status. payment-details. render-after - customer-account.
order-status. return-details. render-after - customer-account.
order-status. unfulfilled-items. render-after - customer-account.
order. action. menu-item. render - customer-account.
order. action. render - customer-account.
order. page. render - customer-account.
page. render - customer-account.
profile. addresses. render-after - customer-account.
profile. announcement. render - customer-account.
profile. block. render - customer-account.
profile. company-details. render-after - customer-account.
profile. company-location-addresses. render-after - customer-account.
profile. company-location-payment. render-after - customer-account.
profile. company-location-staff. render-after - customer-account.
profile. payment. render-after
Anchor to PropertiesProperties
Configure the following properties on the Popover component.
- Anchor to alignmentalignmentalignmentAlignmentAlignmentDefault: 'center'Default: 'center'
The alignment of the popover in the axis determined by the position.
- Anchor to idididstringstring
A unique identifier for the component. Use this to target the component in scripts or stylesheets, or to distinguish it from other instances of the same component.
- Anchor to maxInlineSizemaxInlineSizemaxInlineSizeMaybeResponsiveConditionalStyle< number | `${number}%` | 'fill' >MaybeResponsiveConditionalStyle< number | `${number}%` | 'fill' >
The maximum inline size (maximum width in horizontal writing modes). The element won't grow wider than this value.
number: The size in pixels.`${number}%`: The size as a percentage of the parent container's inline size.'fill': Takes all the available space.
Learn more about the max-inline-size property.
- Anchor to minInlineSizeminInlineSizeminInlineSizeMaybeResponsiveConditionalStyle< number | `${number}%` | 'fill' >MaybeResponsiveConditionalStyle< number | `${number}%` | 'fill' >
The minimum inline size (minimum width in horizontal writing modes). The element won't shrink narrower than this value.
number: The size in pixels.`${number}%`: The size as a percentage of the parent container's inline size.'fill': Takes all the available space.
Learn more about the min-inline-size property.
- Anchor to onCloseonCloseonClose() => void() => void
A callback fired when the popover is closed.
- Anchor to onOpenonOpenonOpen() => void() => void
A callback fired when the popover is opened.
- Anchor to paddingpaddingpaddingMaybeResponsiveConditionalStyle<MaybeShorthandProperty<Spacing>>MaybeResponsiveConditionalStyle<MaybeShorthandProperty<Spacing>>
The padding on all edges of the element, using a shorthand syntax. You can specify one, two, or four values following the CSS shorthand convention.
T: A single value applied uniformly to all edges.[T, T]: The first value applies to block-start and block-end, the second to inline-start and inline-end.[T, T, T, T]: Values apply to block-start, inline-end, block-end, and inline-start respectively.
- Anchor to positionpositionpositionPopoverPositionPopoverPositionDefault: 'blockStart'Default: 'blockStart'
The position of the popover relative to the activator.
Alignment
Controls how content is aligned along the cross axis. - `'start'`: Aligns content to the start of the container. - `'center'`: Centers content within the container. - `'end'`: Aligns content to the end of the container.
'start' | 'center' | 'end'MaybeResponsiveConditionalStyle
A type that represents a value that can be a conditional style. The conditions are based on the viewport size. We highly recommend using the `Style` helper which simplifies the creation of conditional styles.
T | ConditionalStyle<T, ViewportSizeCondition>ConditionalStyle
A conditional style definition that maps one or more conditions to different values. The `default` value is used as a fallback when none of the conditions in `conditionals` are satisfied.
- conditionals
An array of conditional values.
ConditionalValue<T, AcceptedConditions>[] - default
The default value applied when none of the conditional values specified in `conditionals` are met.
T
ConditionalValue
A single conditional branch that pairs a set of conditions with the value to apply when those conditions are met.
- conditions
The conditions that must be met for the value to be applied. At least one condition must be specified.
AcceptedConditions - value
The value that will be applied if the conditions are met.
T
ViewportSizeCondition
A condition that targets layouts based on the inline size (width in horizontal writing modes) of the viewport.
- viewportInlineSize
The minimum viewport inline size that the condition must match.
{ min: T; }
MaybeShorthandProperty
A type that accepts either a single value applied to all edges or a shorthand tuple for per-edge control. - `T`: A single value applied uniformly to all edges. - `[T, T]`: The first value applies to block-start and block-end, the second to inline-start and inline-end. - `[T, T, T, T]`: Values apply to block-start, inline-end, block-end, and inline-start respectively.
T | ShorthandProperty<T>ShorthandProperty
A tuple type that accepts two or four values following the CSS shorthand convention for box edges. - `[T, T]`: The first value applies to block-start and block-end, the second to inline-start and inline-end. - `[T, T, T, T]`: Values apply to block-start, inline-end, block-end, and inline-start respectively.
[T, T] | [T, T, T, T]Spacing
A keyword that maps to a predefined spacing value from the design system. Use these instead of pixel values to ensure consistent spacing throughout the UI. - `none`: No spacing (0px). - `extraTight`: The smallest amount of spacing. - `tight`: A compact amount of spacing, suitable for tight layouts. - `base`: The default spacing, appropriate for most layouts. - `loose`: A generous amount of spacing, used to create visual separation. - `extraLoose`: The largest amount of spacing.
'none' | 'extraTight' | 'tight' | 'base' | 'loose' | 'extraLoose'PopoverPosition
The position of the popover relative to its activator element. - `'inlineStart'`: Positions the popover to the left (in LTR layouts) of the activator. - `'inlineEnd'`: Positions the popover to the right (in LTR layouts) of the activator. - `'blockStart'`: Positions the popover above the activator. - `'blockEnd'`: Positions the popover below the activator.
'inlineStart' | 'inlineEnd' | 'blockStart' | 'blockEnd'Anchor to ExamplesExamples
Anchor to Display contextual informationDisplay contextual information
Surface supplementary information on demand without cluttering the main view. This example shows payment details in a popover triggered by a pressable element.
Display contextual information

Display contextual information
React
import {
reactExtension,
Pressable,
Popover,
View,
TextBlock,
} from '@shopify/ui-extensions-react/customer-account';
export default reactExtension(
'customer-account.page.render',
() => <Extension />,
);
function Extension() {
return (
<Pressable
overlay={
<Popover>
<View
maxInlineSize={200}
padding="base"
>
<TextBlock>
A thoughtful way to pay
</TextBlock>
<TextBlock>Tap don’t type</TextBlock>
<TextBlock>
Shop Pay remembers your important
details, so you can fill carts, not
forms. And everything is encrypted
so you can speed safely through
checkout.
</TextBlock>
</View>
</Popover>
}
>
More info
</Pressable>
);
}JS
import {
extension,
Pressable,
Popover,
View,
TextBlock,
} from '@shopify/ui-extensions/customer-account';
export default extension('customer-account.page.render', (root) => {
const popoverFragment = root.createFragment();
const popover = root.createComponent(Popover, {}, [
root.createComponent(View, {maxInlineSize: 200, padding: 'base'}, [
root.createComponent(TextBlock, {}, 'A thoughtful way to pay'),
root.createComponent(TextBlock, {}, 'Tap don’t type'),
root.createComponent(
TextBlock,
{},
'Shop Pay remembers your important details, so you can fill carts, not forms. And everything is encrypted so you can speed safely through checkout.',
),
]),
]);
popoverFragment.appendChild(popover);
const pressable = root.createComponent(
Pressable,
{overlay: popoverFragment},
'More info',
);
root.appendChild(pressable);
});Anchor to Show a form in a popoverShow a form in a popover
Collect input inline without navigating away from the page. This example presents a text field and submit button inside a popover for verifying a veteran ID.
Show a form in a popover
React
import {
reactExtension,
Button,
Pressable,
Popover,
View,
TextField,
} from '@shopify/ui-extensions-react/customer-account';
export default reactExtension(
'customer-account.order-status.block.render',
() => <Extension />,
);
function Extension() {
return (
<Pressable
overlay={
<Popover>
<View
maxInlineSize={280}
padding="base"
>
<TextField label="Veteran ID" />
<Button>Verify</Button>
</View>
</Popover>
}
>
Verify veteran status
</Pressable>
);
}JS
import {
extension,
Button,
Pressable,
Popover,
View,
TextField,
} from '@shopify/ui-extensions/customer-account';
export default extension(
'customer-account.order-status.block.render',
(root) => {
const popoverFragment = root.createFragment();
const popover = root.createComponent(Popover, {}, [
root.createComponent(
View,
{maxInlineSize: 280, padding: 'base'},
[
root.createComponent(TextField, {label: 'Veteran ID'}),
root.createComponent(Button, {}, 'Verify'),
],
),
]);
popoverFragment.appendChild(popover);
const pressable = root.createComponent(
Pressable,
{overlay: popoverFragment},
'Verify veteran status',
);
root.appendChild(pressable);
},
);Anchor to Display a list of actionsDisplay a list of actions
Present a set of related actions in a compact overlay. This example shows an action list with options for returns, support, and issue reporting.
Display a list of actions
React
import {
reactExtension,
Button,
Popover,
View,
BlockStack,
Link,
} from '@shopify/ui-extensions-react/customer-account';
export default reactExtension(
'customer-account.order-status.block.render',
() => <Extension />,
);
function Extension() {
return (
<Button
overlay={
<Popover>
<View padding="base">
<BlockStack>
<Link to="/account/returns">
Start a return
</Link>
<Link to="/account/support">
Contact support
</Link>
<Link to="/account/report">
Report an issue
</Link>
</BlockStack>
</View>
</Popover>
}
>
Order actions
</Button>
);
}JS
import {
extension,
Button,
Popover,
View,
BlockStack,
Link,
} from '@shopify/ui-extensions/customer-account';
export default extension(
'customer-account.order-status.block.render',
(root) => {
const popoverFragment = root.createFragment();
const popover = root.createComponent(Popover, {}, [
root.createComponent(View, {padding: 'base'}, [
root.createComponent(BlockStack, {}, [
root.createComponent(Link, {to: '/account/returns'}, 'Start a return'),
root.createComponent(Link, {to: '/account/support'}, 'Contact support'),
root.createComponent(Link, {to: '/account/report'}, 'Report an issue'),
]),
]),
]);
popoverFragment.appendChild(popover);
const button = root.createComponent(
Button,
{overlay: popoverFragment},
'Order actions',
);
root.appendChild(button);
},
);Anchor to Best practicesBest practices
- Avoid placing critical information in a popover: Popovers are hidden until triggered, making them unsuitable for essential content that customers need to see immediately.
- Group related actions: Contain actions that share a relationship to each other so the popover feels cohesive.
- Trigger with a clearly labeled activator: The element that opens the popover should clearly indicate what'll appear when activated.
Anchor to LimitationsLimitations
- Popovers can only be opened by user interaction through an activator component, not programmatically on page load.
- The popover position is determined by the activator element and can't be manually overridden.
- Content within the popover doesn't scroll automatically; use a
Viewcomponent for internal scrolling if needed.