All Skills

Use this skill when the user asks about "Polaris components", "Shopify UI", "Button", "Card", "Modal", "IndexTable", "BlockStack", "InlineStack", "icons", "Badge", "Banner", or any Shopify Polaris component usage. Provides Polaris v12+ component patterns and best practices.

T
$npx skills add trantuananh-17/product-reviews --skill polaris-components

Shopify Polaris (React) - v12

Version Info

PackageVersionNotes
@shopify/polaris^12.16.0React component library
@shopify/polaris-icons9.3.0Icons v9 (no Minor/Major suffix)
@shopify/polaris-viz^15.1.3Charts and visualizations
@shopify/app-bridge-react^4.1.5Shopify App Bridge

Icons v9 (CRITICAL)

// GOOD: v9 icons (no suffix)
import {
  PlusCircleIcon,
  DeleteIcon,
  EditIcon,
  SearchIcon,
  ChevronRightIcon,
  AlertCircleIcon,
  MenuHorizontalIcon
} from '@shopify/polaris-icons';

// BAD: Old v8 icons (with Minor/Major suffix)
import {SearchMinor, PlusMajor} from '@shopify/polaris-icons';

Common Icon Names

ActionIcon Name
AddPlusIcon, PlusCircleIcon
DeleteDeleteIcon, XIcon
EditEditIcon
SearchSearchIcon
SettingsSettingsIcon
MenuMenuHorizontalIcon, MenuVerticalIcon
ChevronChevronRightIcon, ChevronDownIcon, ChevronUpIcon

Layout Components

Page Structure

import {Page, Layout, Card, BlockStack, Box} from '@shopify/polaris';

function MyPage() {
  return (
    <Page
      title="Page Title"
      subtitle="Optional subtitle"
      primaryAction={{content: 'Save', onAction: handleSave}}
      secondaryActions={[
        {content: 'Export', onAction: handleExport}
      ]}
      backAction={{content: 'Back', onAction: () => history.goBack()}}
    >
      <Layout>
        <Layout.Section>
          <Card>
            <BlockStack gap="400">
              {/* Main content */}
            </BlockStack>
          </Card>
        </Layout.Section>

        <Layout.Section variant="oneThird">
          <Card>
            {/* Sidebar content */}
          </Card>
        </Layout.Section>
      </Layout>
    </Page>
  );
}

BlockStack vs InlineStack

import {BlockStack, InlineStack, Text, Button} from '@shopify/polaris';

// BlockStack: Vertical stacking (column)
<BlockStack gap="400">
  <Text>Item 1</Text>
  <Text>Item 2</Text>
</BlockStack>

// InlineStack: Horizontal stacking (row)
<InlineStack gap="200" align="center" blockAlign="center">
  <Button>Cancel</Button>
  <Button variant="primary">Save</Button>
</InlineStack>

Spacing Tokens

TokenValueUse Case
1004pxTight spacing
2008pxSmall gaps
30012pxMedium-small
40016pxDefault spacing
50020pxMedium-large
60024pxLarge gaps
80032pxSection spacing

Button Patterns

Button Variants

import {Button, ButtonGroup} from '@shopify/polaris';
import {PlusIcon, DeleteIcon} from '@shopify/polaris-icons';

// Primary action
<Button variant="primary" onClick={handleSave}>Save</Button>

// Secondary (default)
<Button onClick={handleCancel}>Cancel</Button>

// Destructive
<Button variant="primary" tone="critical" onClick={handleDelete}>Delete</Button>

// With icon
<Button icon={PlusIcon} onClick={handleAdd}>Add tier</Button>

// Icon only
<Button icon={DeleteIcon} accessibilityLabel="Delete" onClick={handleDelete} />

// Loading state
<Button variant="primary" loading={saving} onClick={handleSave}>
  {saving ? 'Saving...' : 'Save'}
</Button>
// GOOD: Use url prop for navigation
<Button url="/settings">Go to Settings</Button>
<Button url="https://help.shopify.com" external>Help</Button>

// BAD: onClick + window.open
<Button onClick={() => window.open('/settings')}>Settings</Button>

Data Display

Text Variants

import {Text} from '@shopify/polaris';

<Text variant="headingXl" as="h1">Page Title</Text>
<Text variant="headingLg" as="h2">Section Title</Text>
<Text variant="headingMd" as="h3">Card Title</Text>
<Text variant="bodyMd">Regular body text</Text>
<Text variant="bodySm">Small text</Text>

// With tone
<Text tone="subdued">Secondary text</Text>
<Text tone="success">Success message</Text>
<Text tone="critical">Error message</Text>

// Font weight
<Text fontWeight="bold">Bold text</Text>

Badge

import {Badge} from '@shopify/polaris';

<Badge>Default</Badge>
<Badge tone="info">Info</Badge>
<Badge tone="success">Active</Badge>
<Badge tone="warning">Pending</Badge>
<Badge tone="critical">Error</Badge>

// With progress
<Badge progress="incomplete">Draft</Badge>
<Badge progress="complete" tone="success">Complete</Badge>

Feedback Components

import {Banner} from '@shopify/polaris';

// Info
<Banner title="Info" tone="info">
  This is informational content.
</Banner>

// Success
<Banner title="Success" tone="success" onDismiss={() => setShow(false)}>
  Changes saved successfully.
</Banner>

// Warning
<Banner title="Warning" tone="warning">
  This action cannot be undone.
</Banner>

// Critical
<Banner title="Error" tone="critical">
  Failed to save changes.
</Banner>

import {Modal, Text} from '@shopify/polaris';

<Modal
  open={open}
  onClose={() => setOpen(false)}
  title="Confirm action"
  primaryAction={{
    content: 'Confirm',
    onAction: handleConfirm,
    loading: loading
  }}
  secondaryActions={[
    {content: 'Cancel', onAction: () => setOpen(false)}
  ]}
>
  <Modal.Section>
    <Text>Are you sure you want to proceed?</Text>
  </Modal.Section>
</Modal>

Loading States

Skeleton

import {
  SkeletonPage,
  SkeletonBodyText,
  SkeletonDisplayText,
  Card,
  Layout
} from '@shopify/polaris';

function PageSkeleton() {
  return (
    <SkeletonPage primaryAction>
      <Layout>
        <Layout.Section>
          <Card>
            <SkeletonDisplayText size="small" />
            <SkeletonBodyText lines={3} />
          </Card>
        </Layout.Section>
      </Layout>
    </SkeletonPage>
  );
}

Migration Notes (v11 to v12)

Deprecated to New

DeprecatedReplacement
StackBlockStack / InlineStack
TextStyleText with props
HeadingText variant="heading*"
LegacyCardCard + Box
LegacyStackBlockStack / InlineStack

Checklist

- Using Polaris v12+ components (not Legacy*)
- Icons from v9 (no Minor/Major suffix)
- Button navigation uses url prop (not onClick)
- Proper spacing tokens (100-800)
- Text uses variant prop for typography
- Card uses Box/BlockStack for sections
- Modal uses Modal.Section for content
- Loading states with Skeleton components
- Proper accessibility labels on icon buttons