app-shopify-polaris-web-components

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Shopify Polaris Web Components

Shopify Polaris Web Components

Use this skill when building UI for Shopify App Home surfaces using Polaris Web Components.
当使用Polaris Web Components为Shopify App Home页面构建界面时,可使用本技能。

When to Use

适用场景

  • Building App Home pages (the app surface outside of Shopify Admin iframe)
  • Creating UI with
    s-*
    custom elements
  • Designing layouts with s-section, s-stack, s-box
  • Building forms, modals, or lists for App Home
Important: App Home uses Polaris Web Components (
s-*
elements), NOT Polaris React (
@shopify/polaris
). These are different technologies.
  • 开发App Home页面(Shopify Admin iframe之外的应用页面)
  • 使用
    s-*
    自定义元素创建界面
  • 使用s-section、s-stack、s-box设计布局
  • 为App Home构建表单、模态框或列表
重要提示:App Home使用Polaris Web Components
s-*
元素),而非Polaris React(
@shopify/polaris
)。这是两种不同的技术。

Polaris React vs Web Components

Polaris React 与 Web Components 对比

FeaturePolaris ReactPolaris Web Components
Use forEmbedded admin appsApp Home surfaces
Import
@shopify/polaris
No import (native elements)
Syntax
<Button>
<s-button>
FrameworkReact componentsCustom HTML elements
特性Polaris ReactPolaris Web Components
适用场景嵌入式管理后台应用App Home页面
引入方式
@shopify/polaris
无需引入(原生元素)
语法
<Button>
<s-button>
技术框架React组件自定义HTML元素

Core Components

核心组件

Page Structure

页面结构

html
<s-page heading="Dashboard">
  <s-section heading="Overview">
    <!-- Content -->
  </s-section>
  
  <s-section heading="Settings">
    <!-- More content -->
  </s-section>
</s-page>
html
<s-page heading="Dashboard">
  <s-section heading="Overview">
    <!-- Content -->
  </s-section>
  
  <s-section heading="Settings">
    <!-- More content -->
  </s-section>
</s-page>

Layout with Stack

堆叠布局

html
<!-- Vertical stack (default) -->
<s-stack direction="block" gap="large">
  <s-text>Item 1</s-text>
  <s-text>Item 2</s-text>
</s-stack>

<!-- Horizontal stack -->
<s-stack direction="inline" gap="medium" alignItems="center">
  <s-button>Cancel</s-button>
  <s-button variant="primary">Save</s-button>
</s-stack>

<!-- Stack with justification -->
<s-stack 
  direction="inline" 
  justifyContent="space-between"
  alignItems="center"
>
  <s-text variant="headingMd">Title</s-text>
  <s-button>Action</s-button>
</s-stack>
html
<!-- 垂直堆叠(默认) -->
<s-stack direction="block" gap="large">
  <s-text>Item 1</s-text>
  <s-text>Item 2</s-text>
</s-stack>

<!-- 水平堆叠 -->
<s-stack direction="inline" gap="medium" alignItems="center">
  <s-button>Cancel</s-button>
  <s-button variant="primary">Save</s-button>
</s-stack>

<!-- 带对齐方式的堆叠 -->
<s-stack 
  direction="inline" 
  justifyContent="space-between"
  alignItems="center"
>
  <s-text variant="headingMd">Title</s-text>
  <s-button>Action</s-button>
</s-stack>

Section (Card-like Container)

区块(类卡片容器)

Use
s-section
for grouped content with optional heading:
html
<!-- Section with heading -->
<s-section heading="Chat Widget Settings">
  <s-stack direction="block" gap="medium">
    <s-text>Configure your widget appearance.</s-text>
    <!-- Form fields -->
  </s-stack>
</s-section>

<!-- Section without heading -->
<s-section>
  <s-text>Simple content block</s-text>
</s-section>
使用
s-section
来分组内容,可选择添加标题:
html
<!-- 带标题的区块 -->
<s-section heading="Chat Widget Settings">
  <s-stack direction="block" gap="medium">
    <s-text>Configure your widget appearance.</s-text>
    <!-- Form fields -->
  </s-stack>
</s-section>

<!-- 无标题的区块 -->
<s-section>
  <s-text>Simple content block</s-text>
</s-section>

Box (Generic Layout Container)

容器(通用布局容器)

Use
s-box
for padding, borders, and spacing - NOT for cards:
html
<!-- Box with padding -->
<s-box padding="large">
  <s-text>Padded content</s-text>
</s-box>

<!-- Box with border -->
<s-box 
  padding="medium" 
  borderWidth="base" 
  borderRadius="base"
>
  <s-text>Bordered content</s-text>
</s-box>

<!-- Box for spacing -->
<s-box paddingBlockStart="large">
  <s-text>Content with top margin</s-text>
</s-box>
Rule: Use
s-section
for card-like containers,
s-box
for layout/spacing only.
使用
s-box
来设置内边距、边框和间距——请勿用于卡片
html
<!-- 带内边距的容器 -->
<s-box padding="large">
  <s-text>Padded content</s-text>
</s-box>

<!-- 带边框的容器 -->
<s-box 
  padding="medium" 
  borderWidth="base" 
  borderRadius="base"
>
  <s-text>Bordered content</s-text>
</s-box>

<!-- 用于间距的容器 -->
<s-box paddingBlockStart="large">
  <s-text>Content with top margin</s-text>
</s-box>
规则:使用
s-section
作为类卡片容器,
s-box
仅用于布局/间距设置。

Buttons

按钮

html
<!-- Primary action -->
<s-button variant="primary" type="submit">
  Save Settings
</s-button>

<!-- Default button -->
<s-button>Cancel</s-button>

<!-- Destructive -->
<s-button variant="primary" tone="critical">
  Delete
</s-button>

<!-- Disabled -->
<s-button disabled>Unavailable</s-button>

<!-- With click handler (in JS) -->
<s-button id="save-btn">Save</s-button>
<script>
  document.getElementById('save-btn').addEventListener('click', handleSave);
</script>
html
<!-- 主要操作按钮 -->
<s-button variant="primary" type="submit">
  Save Settings
</s-button>

<!-- 默认按钮 -->
<s-button>Cancel</s-button>

<!-- 危险操作按钮 -->
<s-button variant="primary" tone="critical">
  Delete
</s-button>

<!-- 禁用状态按钮 -->
<s-button disabled>Unavailable</s-button>

<!-- 带点击事件的按钮(JS中) -->
<s-button id="save-btn">Save</s-button>
<script>
  document.getElementById('save-btn').addEventListener('click', handleSave);
</script>

Text

文本

html
<!-- Headings -->
<s-text variant="headingLg">Large Heading</s-text>
<s-text variant="headingMd">Medium Heading</s-text>
<s-text variant="headingSm">Small Heading</s-text>

<!-- Body text -->
<s-text>Default body text</s-text>
<s-text variant="bodySm">Small body text</s-text>

<!-- Tones -->
<s-text tone="subdued">Muted text</s-text>
<s-text tone="critical">Error text</s-text>
<s-text tone="success">Success text</s-text>
html
<!-- 标题 -->
<s-text variant="headingLg">Large Heading</s-text>
<s-text variant="headingMd">Medium Heading</s-text>
<s-text variant="headingSm">Small Heading</s-text>

<!-- 正文 -->
<s-text>Default body text</s-text>
<s-text variant="bodySm">Small body text</s-text>

<!-- 文本色调 -->
<s-text tone="subdued">Muted text</s-text>
<s-text tone="critical">Error text</s-text>
<s-text tone="success">Success text</s-text>

Banner

横幅

html
<!-- Info banner -->
<s-banner>
  <p>This is an informational message.</p>
</s-banner>

<!-- Critical banner -->
<s-banner tone="critical">
  <p>Something went wrong. Please try again.</p>
</s-banner>

<!-- Success banner -->
<s-banner tone="success">
  <p>Settings saved successfully!</p>
</s-banner>

<!-- Dismissible banner -->
<s-banner tone="warning" onDismiss="handleDismiss">
  <p>Your trial ends in 3 days.</p>
</s-banner>
html
<!-- 信息横幅 -->
<s-banner>
  <p>This is an informational message.</p>
</s-banner>

<!-- 错误横幅 -->
<s-banner tone="critical">
  <p>Something went wrong. Please try again.</p>
</s-banner>

<!-- 成功横幅 -->
<s-banner tone="success">
  <p>Settings saved successfully!</p>
</s-banner>

<!-- 可关闭的横幅 -->
<s-banner tone="warning" onDismiss="handleDismiss">
  <p>Your trial ends in 3 days.</p>
</s-banner>

Link

链接

html
<s-link href="/settings">Go to Settings</s-link>

<s-link href="https://shopify.dev" external>
  Documentation
</s-link>
html
<s-link href="/settings">Go to Settings</s-link>

<s-link href="https://shopify.dev" external>
  Documentation
</s-link>

Form Elements

表单元素

html
<!-- Text field -->
<s-text-field 
  label="Store name"
  value="My Store"
  helpText="This appears in your widget"
></s-text-field>

<!-- Select -->
<s-select label="Language">
  <option value="en">English</option>
  <option value="es">Spanish</option>
</s-select>

<!-- Checkbox -->
<s-checkbox label="Enable notifications" checked></s-checkbox>
html
<!-- 文本输入框 -->
<s-text-field 
  label="Store name"
  value="My Store"
  helpText="This appears in your widget"
></s-text-field>

<!-- 下拉选择框 -->
<s-select label="Language">
  <option value="en">English</option>
  <option value="es">Spanish</option>
</s-select>

<!-- 复选框 -->
<s-checkbox label="Enable notifications" checked></s-checkbox>

Common Patterns

常见模式

Settings Page

设置页面

html
<s-page heading="Settings">
  <s-stack direction="block" gap="large">
    
    <s-section heading="General">
      <s-stack direction="block" gap="medium">
        <s-text-field 
          label="Welcome message"
          value="Hello! How can we help?"
        ></s-text-field>
        <s-checkbox label="Enable auto-reply"></s-checkbox>
      </s-stack>
    </s-section>
    
    <s-section heading="Appearance">
      <s-stack direction="block" gap="medium">
        <s-select label="Theme">
          <option value="light">Light</option>
          <option value="dark">Dark</option>
        </s-select>
      </s-stack>
    </s-section>
    
    <s-box paddingBlockStart="large">
      <s-stack direction="inline" gap="medium" justifyContent="flex-end">
        <s-button>Cancel</s-button>
        <s-button variant="primary">Save</s-button>
      </s-stack>
    </s-box>
    
  </s-stack>
</s-page>
html
<s-page heading="Settings">
  <s-stack direction="block" gap="large">
    
    <s-section heading="General">
      <s-stack direction="block" gap="medium">
        <s-text-field 
          label="Welcome message"
          value="Hello! How can we help?"
        ></s-text-field>
        <s-checkbox label="Enable auto-reply"></s-checkbox>
      </s-stack>
    </s-section>
    
    <s-section heading="Appearance">
      <s-stack direction="block" gap="medium">
        <s-select label="Theme">
          <option value="light">Light</option>
          <option value="dark">Dark</option>
        </s-select>
      </s-stack>
    </s-section>
    
    <s-box paddingBlockStart="large">
      <s-stack direction="inline" gap="medium" justifyContent="flex-end">
        <s-button>Cancel</s-button>
        <s-button variant="primary">Save</s-button>
      </s-stack>
    </s-box>
    
  </s-stack>
</s-page>

Empty State

空状态页面

html
<s-section>
  <s-stack direction="block" gap="medium" alignItems="center">
    <s-text variant="headingMd">No campaigns yet</s-text>
    <s-text tone="subdued">
      Create your first campaign to get started.
    </s-text>
    <s-button variant="primary">Create Campaign</s-button>
  </s-stack>
</s-section>
html
<s-section>
  <s-stack direction="block" gap="medium" alignItems="center">
    <s-text variant="headingMd">No campaigns yet</s-text>
    <s-text tone="subdued">
      Create your first campaign to get started.
    </s-text>
    <s-button variant="primary">Create Campaign</s-button>
  </s-stack>
</s-section>

List with Actions

带操作的列表

html
<s-section heading="Campaigns">
  <s-stack direction="block" gap="none">
    
    <s-box padding="medium" borderBlockEnd="base">
      <s-stack direction="inline" justifyContent="space-between" alignItems="center">
        <s-stack direction="block" gap="extraSmall">
          <s-text variant="headingSm">Welcome Series</s-text>
          <s-text tone="subdued">Active • 1,234 sent</s-text>
        </s-stack>
        <s-button>Edit</s-button>
      </s-stack>
    </s-box>
    
    <s-box padding="medium" borderBlockEnd="base">
      <s-stack direction="inline" justifyContent="space-between" alignItems="center">
        <s-stack direction="block" gap="extraSmall">
          <s-text variant="headingSm">Abandoned Cart</s-text>
          <s-text tone="subdued">Paused • 567 sent</s-text>
        </s-stack>
        <s-button>Edit</s-button>
      </s-stack>
    </s-box>
    
  </s-stack>
</s-section>
html
<s-section heading="Campaigns">
  <s-stack direction="block" gap="none">
    
    <s-box padding="medium" borderBlockEnd="base">
      <s-stack direction="inline" justifyContent="space-between" alignItems="center">
        <s-stack direction="block" gap="extraSmall">
          <s-text variant="headingSm">Welcome Series</s-text>
          <s-text tone="subdued">Active • 1,234 sent</s-text>
        </s-stack>
        <s-button>Edit</s-button>
      </s-stack>
    </s-box>
    
    <s-box padding="medium" borderBlockEnd="base">
      <s-stack direction="inline" justifyContent="space-between" alignItems="center">
        <s-stack direction="block" gap="extraSmall">
          <s-text variant="headingSm">Abandoned Cart</s-text>
          <s-text tone="subdued">Paused • 567 sent</s-text>
        </s-stack>
        <s-button>Edit</s-button>
      </s-stack>
    </s-box>
    
  </s-stack>
</s-section>

TypeScript Support

TypeScript 支持

Add types for s-* components in your
tsconfig.json
:
json
{
  "compilerOptions": {
    "types": ["@shopify/polaris-types"]
  }
}
tsconfig.json
中添加s-*组件的类型声明:
json
{
  "compilerOptions": {
    "types": ["@shopify/polaris-types"]
  }
}

Best Practices

最佳实践

  1. Use s-section for cards - Not s-box
  2. Use s-box for layout only - Padding, borders, spacing
  3. Prefer s- over custom divs* - Only use div when s-* can't achieve the layout
  4. Use semantic structure - s-page > s-section > content
  5. Consistent spacing - Use gap props, not manual margins
  6. Check the docs - Components have many props not shown here
  1. 使用s-section作为卡片容器——而非s-box
  2. 仅将s-box用于布局——设置内边距、边框、间距
  3. *优先使用s-组件而非自定义div——仅当s-*组件无法实现所需布局时才使用div
  4. 使用语义化结构——遵循s-page > s-section > 内容的层级
  5. 保持间距一致——使用gap属性,而非手动设置外边距
  6. 查阅官方文档——组件还有许多未在此展示的属性

When to Use Custom Styles

自定义样式的适用场景

Only use plain
div
and inline styles when:
  • The user explicitly requests it
  • After trying s-* components and they can't achieve the required layout
  • For very specific visual effects not supported by Polaris
仅在以下情况使用普通
div
和内联样式:
  • 用户明确要求时
  • 尝试使用s-*组件后仍无法实现所需布局时
  • 用于Polaris不支持的特殊视觉效果时

References

参考资料