shopify-polaris-design

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
This skill ensures that interfaces are built using Shopify's Polaris Design System, guaranteeing a native, accessible, and professional look and feel for Shopify Merchants.
本技能确保界面采用Shopify的Polaris设计系统构建,为Shopify商家提供原生、可访问且专业的视觉与使用体验。

Core Principles

核心原则

  1. Merchant-Focused: Design for efficiency and clarity. Merchants use these tools to run their business.
  2. Native Feel: The app should feel like a natural extension of the Shopify Admin. Do not introduce foreign design patterns (e.g. Material Design shadows, distinct bootstappy buttons) unless absolutely necessary.
  3. Accessibility: Polaris is built with accessibility in mind. Maintain this by using semantic components (e.g.,
    Button
    ,
    Link
    ,
    TextField
    ) rather than custom
    div
    implementations.
  4. Predictability: Follow standard Shopify patterns. Save buttons go in the Contextual Save Bar. Page actions go in the top right. Primary content is centered.
  1. 以商家为中心:设计注重效率与清晰性。商家使用这些工具来运营业务。
  2. 原生体验:应用应作为Shopify Admin的自然延伸。除非绝对必要,请勿引入外来设计模式(如Material Design阴影、独特的Bootstrap风格按钮)。
  3. 可访问性:Polaris在设计时就考虑了可访问性。通过使用语义化组件(如
    Button
    Link
    TextField
    )而非自定义
    div
    实现来维持这一特性。
  4. 可预测性:遵循Shopify标准模式。保存按钮应放在Contextual Save Bar中。页面操作位于右上角。主要内容居中显示。

Technical Implementation

技术实现

Dependencies

依赖项

  • @shopify/polaris
  • @shopify/polaris-icons
  • @shopify/app-bridge-react
    (for navigation, title bar, toasts, save bar)
  • @shopify/polaris
  • @shopify/polaris-icons
  • @shopify/app-bridge-react
    (用于导航、标题栏、提示框、保存栏)

Fundamental Components

基础组件

  • AppProvider: All Polaris apps must be wrapped in
    <AppProvider i18n={enTranslations}>
    .
  • Page: The top-level container for a route. Always set
    title
    and
    primaryAction
    (if applicable).
    jsx
    <Page title="Products" primaryAction={{content: 'Add product', onAction: handleAdd}}>
  • Layout: Use
    Layout
    and
    Layout.Section
    to structure content.
    • Layout.AnnotatedSection
      : For settings pages (Title/Description on left, Card on right).
    • Layout.Section
      : Standard Full (default), 1/2 (
      variant="oneHalf"
      ), or 1/3 (
      variant="oneThird"
      ) width columns.
  • Card: The primary container for content pieces. Group related information in a Card.
    • Use
      BlockStack
      (vertical) or
      InlineStack
      (horizontal) for internal layout within a Card.
    • Do not use
      Card.Section
      as it is deprecated in newer versions; use
      BlockStack
      with
      gap
      .
  • AppProvider:所有Polaris应用必须包裹在
    <AppProvider i18n={enTranslations}>
    中。
  • Page:路由的顶级容器。务必设置
    title
    primaryAction
    (如有需要)。
    jsx
    <Page title="Products" primaryAction={{content: 'Add product', onAction: handleAdd}}>
  • Layout:使用
    Layout
    Layout.Section
    来组织内容结构。
    • Layout.AnnotatedSection
      :用于设置页面(左侧为标题/描述,右侧为卡片)。
    • Layout.Section
      :标准全宽(默认)、半宽(
      variant="oneHalf"
      )或三分之一宽(
      variant="oneThird"
      )列。
  • Card:内容块的主要容器。将相关信息分组到Card中。
    • 使用
      BlockStack
      (垂直)或
      InlineStack
      (水平)来实现Card内部的布局。
    • 请勿使用
      Card.Section
      ,因为它在新版本中已被弃用;请使用带
      gap
      属性的
      BlockStack

Data Display

数据展示

  • IndexTable: For lists of objects (Products, Orders) with bulk actions and filtering. It replaces the older
    ResourceList
    for complex table cases.
  • LegacyCard + ResourceList: Still valid for simple lists where table headers aren't needed.
  • DataTable: For simple, non-interactive data grids (e.g., analytics data).
  • Text: Use
    <Text as="h2" variant="headingMd">
    instead of
    <h2>
    . Strict typography control is key.
  • IndexTable:用于展示带批量操作和筛选功能的对象列表(如产品、订单)。在复杂表格场景中,它替代了旧版的
    ResourceList
  • LegacyCard + ResourceList:在不需要表头的简单列表场景中仍然适用。
  • DataTable:用于简单的非交互式数据网格(如分析数据)。
  • Text:使用
    <Text as="h2" variant="headingMd">
    而非
    <h2>
    。严格的排版控制是关键。

Form Design

表单设计

  • Use
    FormLayout
    to automatically handle spacing and alignment of form fields.
  • Use
    TextField
    ,
    Select
    ,
    Checkbox
    ,
    RadioButton
    .
  • Validation: Pass
    error
    prop (string or boolean) to form fields to show validation messages inline.
  • ContextualSaveBar: For forms that edit existing data, use the App Bridge
    useSaveBar
    or
    <ContextualSaveBar>
    component to show the specialized top bar for saving/discarding changes.
  • 使用
    FormLayout
    自动处理表单字段的间距与对齐。
  • 使用
    TextField
    Select
    Checkbox
    RadioButton
  • 验证:为表单字段传递
    error
    属性(字符串或布尔值),以在字段内联显示验证消息。
  • ContextualSaveBar:对于编辑现有数据的表单,使用App Bridge的
    useSaveBar
    <ContextualSaveBar>
    组件,在视口顶部显示用于保存/放弃更改的专用栏。

Design Tokens & CSS

设计令牌与CSS

  • Avoid Custom CSS: 95% of styling should be handled by Polaris props (
    gap
    ,
    padding
    ,
    align
    ,
    justify
    ).
  • Design Tokens: If you MUST use custom CSS, use Polaris CSS Custom Properties (Tokens).
    • Backgrounds:
      var(--p-color-bg-surface)
    • Text:
      var(--p-color-text-default)
    • Spacing:
      var(--p-space-400)
      (16px)
    • Borders:
      var(--p-border-radius-200)
  • 避免自定义CSS:95%的样式应通过Polaris的props(如
    gap
    padding
    align
    justify
    )来处理。
  • 设计令牌:如果必须使用自定义CSS,请使用Polaris CSS自定义属性(令牌)。
    • 背景:
      var(--p-color-bg-surface)
    • 文本:
      var(--p-color-text-default)
    • 间距:
      var(--p-space-400)
      (16px)
    • 边框:
      var(--p-border-radius-200)

Code Style Example

代码风格示例

jsx
import { Page, Layout, Card, BlockStack, Text, Button, InlineStack, Badge } from '@shopify/polaris';

export default function Dashboard() {
  return (
    <Page 
        title="Dashboard" 
        primaryAction={{content: 'Create Campaign', onAction: () => {}}}
        secondaryActions={[{content: 'View Logs', onAction: () => {}}]}
    >
      <Layout>
        <Layout.Section>
          <Card>
            <BlockStack gap="400">
              <InlineStack align="space-between">
                <Text as="h2" variant="headingMd">Recent Activity</Text>
                <Badge tone="success">Active</Badge>
              </InlineStack>
              <Text as="p" tone="subdued">Everything is running smoothly.</Text>
            </BlockStack>
          </Card>
        </Layout.Section>
        
        <Layout.Section variant="oneThird">
            <Card>
                <BlockStack gap="200">
                    <Text as="h3" variant="headingSm">Quick Helper</Text>
                    <Button variant="plain">Read Documentation</Button>
                </BlockStack>
            </Card>
        </Layout.Section>
      </Layout>
    </Page>
  );
}
jsx
import { Page, Layout, Card, BlockStack, Text, Button, InlineStack, Badge } from '@shopify/polaris';

export default function Dashboard() {
  return (
    <Page 
        title="Dashboard" 
        primaryAction={{content: 'Create Campaign', onAction: () => {}}}
        secondaryActions={[{content: 'View Logs', onAction: () => {}}]}
    >
      <Layout>
        <Layout.Section>
          <Card>
            <BlockStack gap="400">
              <InlineStack align="space-between">
                <Text as="h2" variant="headingMd">Recent Activity</Text>
                <Badge tone="success">Active</Badge>
              </InlineStack>
              <Text as="p" tone="subdued">Everything is running smoothly.</Text>
            </BlockStack>
          </Card>
        </Layout.Section>
        
        <Layout.Section variant="oneThird">
            <Card>
                <BlockStack gap="200">
                    <Text as="h3" variant="headingSm">Quick Helper</Text>
                    <Button variant="plain">Read Documentation</Button>
                </BlockStack>
            </Card>
        </Layout.Section>
      </Layout>
    </Page>
  );
}

Anti-Patterns to AVOID

需避免的反模式

  • DO NOT use Shadows or Borders manually. Cards handle this.
  • DO NOT use
    style={{ margin: 10 }}
    . Use
    <Box padding="400">
    or
    <BlockStack gap="400">
    .
  • DO NOT create a "Save" button at the bottom of a form. Use the
    ContextualSaveBar
    at the top of the viewport.
  • DO NOT use generic loading spinners. Use
    <SkeletonPage>
    or
    <SkeletonBodyText>
    for loading states.
  • 请勿手动使用阴影或边框。Card组件会处理这些样式。
  • 请勿使用
    style={{ margin: 10 }}
    。请使用
    <Box padding="400">
    <BlockStack gap="400">
  • 请勿在表单底部创建“保存”按钮。请使用视口顶部的
    ContextualSaveBar
  • 请勿使用通用加载动画。请使用
    <SkeletonPage>
    <SkeletonBodyText>
    来实现加载状态。