| name | Shopify Polaris Design System |
| description | Build merchant admin interfaces with Shopify Polaris—a React-based design system optimized for eCommerce efficiency, data richness, and action-driven workflows. Trigger this skill when designing admin dashboards, product tables, order management UIs, or responsive merchant-facing tools. |
What Is Polaris?
Polaris is Shopify's design system built for merchant admin interfaces. It prioritizes merchant efficiency and data richness—helping sellers accomplish complex tasks quickly. Every component is WCAG compliant and responsive by default. Polaris uses React as its foundation, with semantic HTML and accessible patterns built-in.
Core Design Principles
1. Efficiency Over Aesthetics
Merchants need to complete tasks fast. Polaris favors scannable layouts, clear action buttons, and minimal friction. Data tables expose many rows; modals open quickly.
2. Action-Driven
Every interface guides users toward primary actions. Primary buttons are prominent; secondary actions recede. Forms and tables highlight next steps.
3. Clarity Through Constraint
A restrained color palette (primarily navy, teal, and red for actions) reduces cognitive load. Consistent spacing (4px, 8px, 12px, 16px grids) creates predictable rhythm.
4. Mobile-First Responsive
Polaris components adapt seamlessly to small screens. Stacked layouts, touch-friendly targets (48px minimum), hidden overflow patterns.
Visual Language
Colors:
- Primary: Teal (#0080FF) for primary actions
- Secondary: Light gray (#F5F5F5) for containers, (#E8E8E8) for borders
- Text: Dark navy (#212121) for body, (#595959) for secondary
- Status: Success (#229159), Warning (#FFAA47), Critical (#E81E1E)
Typography:
- Body: 14px / 20px line-height (1.5)
- Headings: Weights 500/600, sizes 12px–24px
- Use system fonts (SF Pro, -apple-system, sans-serif)
Spacing:
- Margins/padding: 4, 8, 12, 16, 20, 24, 32px (multiples of 4)
- Gap between grid items: 16px
- Card padding: 16px or 20px
Elevation & Shadows:
- No shadow on base; light shadow on elevated surfaces:
0 1px 3px rgba(0,0,0,0.1)
- Modals:
0 5px 15px rgba(0,0,0,0.15) (stronger focus)
Component Patterns
ResourceList
A flexible list for showing items (products, orders). Renders rows with thumbnail, title, metadata.
<ResourceList
resourceName={{ singular: 'product', plural: 'products' }}
items={products}
renderItem={(item) => (
<ResourceItem
id={item.id}
media={<Thumbnail source={item.image} />}
accessibilityLabel={item.title}
>
<Text variant="bodyMd" fontWeight="bold">{item.title}</Text>
<Text variant="bodySm" color="subdued">${item.price}</Text>
</ResourceItem>
)}
/>
IndexTable
Data table for large, sortable datasets. Supports row selection, sticky headers.
<IndexTable
selectable={true}
headings={[
{ title: 'Order' },
{ title: 'Date' },
{ title: 'Customer', alignment: 'start' },
{ title: 'Total', alignment: 'end' }
]}
rows={orders.map(order => ({
id: order.id,
cells: [order.number, order.date, order.customer, `$${order.total}`]
}))}
/>
Page + Card Layout
Page is the top container; Card groups content.
<Page
title="Products"
primaryAction={{ content: 'Add product', onAction: () => {} }}
secondaryActions={[{ content: 'Export' }]}
>
<Layout>
<Layout.Section>
<Card title="Inventory">
<Box padding="400">{/* content */}</Box>
</Card>
</Layout.Section>
</Layout>
</Page>
Code Generation Guidance
Use Polaris when:
- Building merchant/admin interfaces (Shopify, similar platforms)
- Displaying data tables with sorting, filtering, batch actions
- Creating forms with validation feedback
- Building responsive, accessible interfaces
React patterns:
- Import from
@shopify/polaris: Button, Card, Page, IndexTable, ResourceList, Form, TextField, Select, Modal, Banner
- Always wrap in
<PolarisProvider> for theming
- Use
Stack for layout (direction: "vertical" or "horizontal")
- Use
Box for spacing with padding/margin tokens
CSS (if extending):
- Spacing:
padding: 16px 20px, gap: 16px
- Text:
font-size: 14px; line-height: 20px; color: #212121
- Borders:
1px solid #E8E8E8
- Buttons:
background: #0080FF; color: white; padding: 10px 16px; border-radius: 4px
Accessibility
- Color contrast: All text meets WCAG AA (4.5:1 ratio minimum)
- Focus states: Always visible, 2px teal outline, 2px offset
- ARIA labels: Every interactive element has
aria-label or associated <label>
- Keyboard nav: Tab through buttons/inputs; use arrow keys for lists
- Semantic HTML: Use
<button>, <input>, <table>, not <div> + click handlers
Examples
Example 1: Product Listing with Bulk Actions
Input: "Create a product list UI with a bulk delete button for merchants"
import { Page, ResourceList, ResourceItem, Button, Box } from '@shopify/polaris';
export default function ProductListPage() {
const [selected, setSelected] = useState([]);
return (
<Page
title="Products"
primaryAction={{ content: 'Add product' }}
>
<Box marginBlockEnd="400">
{selected.length > 0 && (
<Button destructive onClick={() => deleteProducts(selected)}>
Delete {selected.length} products
</Button>
)}
</Box>
<ResourceList
resourceName={{ singular: 'product', plural: 'products' }}
items={products}
selectable={true}
selectedItems={selected}
onSelectionChange={setSelected}
renderItem={(item) => (
<ResourceItem id={item.id} selected={selected.includes(item.id)}>
<Text fontWeight="bold">{item.title}</Text>
</ResourceItem>
)}
/>
</Page>
);
}
Example 2: Order Detail with Data Table
Input: "Design an order detail page showing line items in a table with status badges"
import { Page, Card, IndexTable, Badge, Text } from '@shopify/polaris';
export default function OrderDetail({ orderId }) {
const order = fetchOrder(orderId);
return (
<Page title={`Order ${order.number}`} backAction={{ onAction: () => {} }}>
<Card title="Line items">
<IndexTable
headings={[
{ title: 'Product' },
{ title: 'SKU' },
{ title: 'Qty' },
{ title: 'Status', alignment: 'center' },
{ title: 'Price', alignment: 'end' }
]}
rows={order.items.map(item => ({
id: item.id,
cells: [
item.title,
item.sku,
item.quantity,
<Badge status={item.status}>{item.status}</Badge>,
`$${item.price}`
]
}))}
/>
</Card>
</Page>
);
}