Skip to main content
Migrate to Polaris

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.

Pressable

The Pressable component creates a clickable area around its children without adding any visible button or link styling. It combines the layout capabilities of Box with the navigation and click handling of Link, making it useful for building custom interactive elements like clickable cards or list items.

For standard actions with button styling, use Button.

Support
Targets (46)

Supported targets


Props for the Pressable component, which combines the layout capabilities of Box with the interactive behavior of Link. Use Pressable when you need a custom interactive area that can navigate to a URL or respond to press events while supporting flexible layout and styling options.

Anchor to accessibilityLabel
accessibilityLabel
string

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 label supplied won't be announced to screen readers.

Anchor to accessibilityRole
accessibilityRole
Default: 'generic'

The semantic meaning of the component’s content. When set, the role will be used by assistive technologies to help users navigate the page.

Anchor to blockSize
blockSize
number | `${number}%`

The block size (height in horizontal writing modes) of the element.

  • number: The size in pixels.
  • `${number}%`: The size as a percentage of the parent container's block size.

Learn more about the block-size property.

Anchor to display
display
'auto' | 'none'
Default: 'auto'

Whether the element is rendered and takes up space in the layout.

  • auto: The element is rendered normally and participates in layout.
  • none: The element isn't rendered at all and doesn't take up any space. Use this to conditionally hide content without removing it from the component tree.
string

The URL to link to. If set, the link will navigate to the specified location after executing the onClick callback. Use this prop for standard navigation links within or outside the Shopify admin.

string

A unique identifier for the link. When not set, a globally unique value will be used instead.

Anchor to inlineSize
inlineSize
number | `${number}%`

The inline size (width in horizontal writing modes) of the element.

  • number: The size in pixels.
  • `${number}%`: The size as a percentage of the parent container's inline size.

Learn more about the inline-size property.

string

An alias for language. The language of the link's text content. Use this when the link 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.

Anchor to language
language
string

The language of the link's text content. Use this when the link 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.

Anchor to maxBlockSize
maxBlockSize
number | `${number}%`

The maximum block size (maximum height in horizontal writing modes). The element won't grow taller than this value even if its content is longer.

  • number: The size in pixels.
  • `${number}%`: The size as a percentage of the parent container's block size.

Learn more about the max-block-size property.

Anchor to maxInlineSize
maxInlineSize
number | `${number}%`

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.

Learn more about the max-inline-size property.

Anchor to minBlockSize
minBlockSize
number | `${number}%`

The minimum block size (minimum height in horizontal writing modes). The element won't shrink smaller than this value even if its content is shorter.

  • number: The size in pixels.
  • `${number}%`: The size as a percentage of the parent container's block size.

Learn more about the min-block-size property.

Anchor to minInlineSize
minInlineSize
number | `${number}%`

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.

Learn more about the min-inline-size property.

Anchor to onClick
onClick
() => void

A callback that fires when the link is pressed. If href is set, the callback executes first and then the link navigates to the specified location.

Anchor to onPress
onPress
() => void

An alias for onClick. A callback that fires when the link is pressed. If href is set, the callback executes first and then the link navigates to the specified location.

Anchor to padding
padding
< | boolean>

The padding on all edges of the element, using a shorthand syntax. You can specify one to four values following the CSS shorthand convention.

When set to true, applies a default padding appropriate for the component.

Anchor to paddingBlock
paddingBlock
< | boolean>

The padding on the block-start and block-end edges. When set to true, applies a default block padding appropriate for the component.

Learn more about the padding-block property.

Anchor to paddingBlockEnd
paddingBlockEnd
| boolean

The padding on the block-end edge (the bottom edge in horizontal writing modes). When set to true, applies a default padding appropriate for the component.

Learn more about the padding-block-end property.

Anchor to paddingBlockStart
paddingBlockStart
| boolean

The padding on the block-start edge (the top edge in horizontal writing modes). When set to true, applies a default padding appropriate for the component.

Learn more about the padding-block-start property.

Anchor to paddingInline
paddingInline
< | boolean>

The padding on the inline-start and inline-end edges. When set to true, applies a default inline padding appropriate for the component.

Learn more about the padding-inline property.

Anchor to paddingInlineEnd
paddingInlineEnd
| boolean

The padding on the inline-end edge (the right edge in left-to-right writing modes). When set to true, applies a default padding appropriate for the component.

Learn more about the padding-inline-end property.

Anchor to paddingInlineStart
paddingInlineStart
| boolean

The padding on the inline-start edge (the left edge in left-to-right writing modes). When set to true, applies a default padding appropriate for the component.

Learn more about the padding-inline-start property.

Anchor to target
target
'_blank' | '_self'
Default: '_self'

The browsing context for opening the linked URL.

  • _blank: Opens the link in a new tab or window.
  • _self: Opens the link in the current page (default behavior).
string

An alias for href. If set, the link will navigate to the specified location after executing the onClick callback.

'default' | 'inherit' | 'critical'
Default: 'default'

The color of the link text.

  • default: Uses the standard link color to indicate an interactive element.
  • inherit: Takes the color value from its parent, giving the link a monochrome appearance. Pair this with another stylistic treatment, like an underline, to differentiate the link from normal text.
  • critical: Uses a critical (destructive) color to indicate a potentially dangerous action, such as deleting a resource.

Anchor to Build custom action rowsBuild custom action rows

Trigger an inventory sync or a data export from icon-labeled action rows. This example uses Pressable with onPress callbacks and Icon labels to create clickable rows that call backend APIs without visible button styling.

Build custom action rows

Trigger an inventory sync or a data export from icon-labeled action rows. This example uses `Pressable` with `onPress` callbacks and [Icon](/docs/api/admin-extensions/2025-07/ui-components/media-and-visuals/icon) labels to create clickable rows that call backend APIs without visible button styling.

Build custom action rows

import {reactExtension, useApi, Pressable, Text, Icon, InlineStack, BlockStack} from '@shopify/ui-extensions-react/admin';

function App() {
const {data} = useApi('admin.product-details.block.render');
const productId = data.selected[0]?.id;

return (
<BlockStack gap>
<Text fontWeight="bold">Quick actions</Text>
<Pressable
padding="base"
onPress={async () => {
await fetch('/api/products/sync', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId}),
});
}}
>
<InlineStack gap blockAlignment="center">
<Icon name="RefreshMajor" accessibilityLabel="" />
<Text>Sync inventory now</Text>
</InlineStack>
</Pressable>
<Pressable
padding="base"
onPress={async () => {
await fetch('/api/products/export', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId}),
});
}}
>
<InlineStack gap blockAlignment="center">
<Icon name="ExportMinor" accessibilityLabel="" />
<Text>Export product data</Text>
</InlineStack>
</Pressable>
</BlockStack>
);
}

export default reactExtension(
'admin.product-details.block.render',
() => <App />,
);
import {extension, Pressable, Text, Icon, InlineStack, BlockStack} 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 stack = root.createComponent(BlockStack, {gap: true});

const heading = root.createComponent(Text, {fontWeight: 'bold'}, 'Quick actions');

const syncAction = root.createComponent(Pressable, {
padding: 'base',
onPress: async () => {
await fetch('/api/products/sync', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId}),
});
},
});
const syncRow = root.createComponent(InlineStack, {gap: true, blockAlignment: 'center'});
const syncIcon = root.createComponent(Icon, {name: 'RefreshMajor', accessibilityLabel: ''});
const syncText = root.createComponent(Text, {}, 'Sync inventory now');
syncRow.appendChild(syncIcon);
syncRow.appendChild(syncText);
syncAction.appendChild(syncRow);

const exportAction = root.createComponent(Pressable, {
padding: 'base',
onPress: async () => {
await fetch('/api/products/export', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({productId}),
});
},
});
const exportRow = root.createComponent(InlineStack, {gap: true, blockAlignment: 'center'});
const exportIcon = root.createComponent(Icon, {name: 'ExportMinor', accessibilityLabel: ''});
const exportText = root.createComponent(Text, {}, 'Export product data');
exportRow.appendChild(exportIcon);
exportRow.appendChild(exportText);
exportAction.appendChild(exportRow);

stack.appendChild(heading);
stack.appendChild(syncAction);
stack.appendChild(exportAction);
root.appendChild(stack);
},
);

Anchor to Create a clickable product cardCreate a clickable product card

Use href and target props to make a Pressable behave as a link, wrapping rich content like Image and text. This example creates a clickable card that opens the product's storefront page in a new tab.

Create a clickable product card

import {reactExtension, useApi, Pressable, Text, Image, BlockStack} 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 gap>
<Pressable
href={`https://your-store.myshopify.com/products/${numericId}`}
target="_blank"
padding="base"
>
<Image
source="https://cdn.shopify.com/s/files/placeholder-images/product.png"
accessibilityLabel="Product preview"
/>
<Text fontWeight="bold">View on storefront</Text>
<Text>Opens the live product page in a new tab</Text>
</Pressable>
</BlockStack>
);
}

export default reactExtension(
'admin.product-details.block.render',
() => <App />,
);
import {extension, Pressable, Text, Image, BlockStack} 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, {gap: true});

const card = root.createComponent(Pressable, {
href: `https://your-store.myshopify.com/products/${numericId}`,
target: '_blank',
padding: 'base',
});

const image = root.createComponent(Image, {
source: 'https://cdn.shopify.com/s/files/placeholder-images/product.png',
accessibilityLabel: 'Product preview',
});
const title = root.createComponent(Text, {fontWeight: 'bold'}, 'View on storefront');
const description = root.createComponent(Text, {}, 'Opens the live product page in a new tab');

card.appendChild(image);
card.appendChild(title);
card.appendChild(description);

stack.appendChild(card);
root.appendChild(stack);
},
);

Anchor to Add accessible interactive regionsAdd accessible interactive regions

Label custom tappable areas for screen readers using accessibilityLabel. This example renders warehouse location rows with Badge indicators, where each row announces its stock level and location name to assistive technology.

Add accessible interactive regions

import {reactExtension, Pressable, Text, Badge, InlineStack, BlockStack} from '@shopify/ui-extensions-react/admin';

function App() {

return (
<BlockStack gap>
<Text fontWeight="bold">Warehouse locations</Text>
<Pressable
padding="base"
accessibilityLabel="View New York warehouse details — 142 units in stock"
onPress={() => console.log('Card pressed')}
>
<InlineStack gap blockAlignment="center">
<Text>New York</Text>
<Badge tone="success">142 units</Badge>
</InlineStack>
</Pressable>
<Pressable
padding="base"
accessibilityLabel="View Los Angeles warehouse details — 3 units in stock, low stock"
onPress={() => console.log('Card pressed')}
>
<InlineStack gap blockAlignment="center">
<Text>Los Angeles</Text>
<Badge tone="warning">3 units</Badge>
</InlineStack>
</Pressable>
</BlockStack>
);
}

export default reactExtension(
'admin.product-details.block.render',
() => <App />,
);
import {extension, Pressable, Text, Badge, InlineStack, BlockStack} from '@shopify/ui-extensions/admin';

export default extension(
'admin.product-details.block.render',
(root) => {

const stack = root.createComponent(BlockStack, {gap: true});

const heading = root.createComponent(Text, {fontWeight: 'bold'}, 'Warehouse locations');

const location1 = root.createComponent(Pressable, {
padding: 'base',
accessibilityLabel: 'View New York warehouse details — 142 units in stock',
onPress: () => console.log('Card pressed'),
});
const row1 = root.createComponent(InlineStack, {gap: true, blockAlignment: 'center'});
const name1 = root.createComponent(Text, {}, 'New York');
const badge1 = root.createComponent(Badge, {tone: 'success'}, '142 units');
row1.appendChild(name1);
row1.appendChild(badge1);
location1.appendChild(row1);

const location2 = root.createComponent(Pressable, {
padding: 'base',
accessibilityLabel: 'View Los Angeles warehouse details — 3 units in stock, low stock',
onPress: () => console.log('Card pressed'),
});
const row2 = root.createComponent(InlineStack, {gap: true, blockAlignment: 'center'});
const name2 = root.createComponent(Text, {}, 'Los Angeles');
const badge2 = root.createComponent(Badge, {tone: 'warning'}, '3 units');
row2.appendChild(name2);
row2.appendChild(badge2);
location2.appendChild(row2);

stack.appendChild(heading);
stack.appendChild(location1);
stack.appendChild(location2);
root.appendChild(stack);
},
);

  • Use for custom interactive layouts: Pressable is ideal when you need to make a group of elements clickable as a single unit, such as a card that navigates to a detail page. For standard actions, prefer Button or Link.
  • Pair with visual hover cues: Pressable changes the cursor on hover, but consider combining it with other visual feedback so the interactive area is obvious to all users.
  • Avoid nesting interactive elements: Don't place Button or Link components inside a Pressable. Nesting interactive elements creates confusing behavior for keyboard and screen reader users and can lead to unexpected click handling.

  • Pressable doesn't render any visual styling beyond a cursor change on hover. All visual feedback, such as background color changes or borders, must be handled by the child components.
  • Pressable doesn't support form submission or reset behavior. Use a Button to submit or reset forms.
  • When using href for navigation, the onClick callback fires before navigation. You can't conditionally prevent navigation from within the callback.

Was this page helpful?