Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:54:03 +08:00
commit 958dd5e6bc
10 changed files with 2112 additions and 0 deletions

View File

@@ -0,0 +1,422 @@
---
name: polaris-compositions
description: Polaris composition patterns and page templates for common Shopify app layouts. Provides index tables, settings pages, dashboards, and resource management patterns. Auto-invoked when building page layouts.
allowed-tools: [Read, Grep, Glob]
documentation_path: ../../../polaris-web-components/patterns
---
# Polaris Compositions Skill
## Purpose
Provides complete page templates and composition patterns for common Shopify app layouts using Polaris Web Components.
## When This Skill Activates
- Creating new pages or views
- Building index/list pages
- Implementing settings interfaces
- Designing dashboards
- Creating resource management UIs
## Available Patterns
Reference: `polaris-web-components/patterns/compositions/`
### Composition Patterns
1. **App Card** - Application summary cards with actions
2. **Resource List** - Filterable, sortable resource lists
3. **Settings** - Settings page layouts with sections
4. **Callout Card** - Promotional or informational cards
5. **Account Connection** - Third-party service integrations
6. **Details** - Detailed information displays
7. **Index Table** - Data tables with bulk actions
8. **Metrics Card** - Statistics and KPI displays
9. **Setup Guide** - Onboarding checklists
10. **Homepage** - App homepage/dashboard layouts
11. **Sticky Pagination** - Persistent pagination controls
12. **Interstitial Nav** - Multi-step navigation flows
13. **Footer Help** - Contextual help sections
14. **Media Card** - Rich media content cards
15. **Empty State** - No content placeholders
## Complete Page Templates
### Index/List Page Template
**Use for**: Products, Orders, Customers, Collections
```tsx
<s-page
heading="Products"
primaryAction={{ content: "Add Product", url: "/products/new" }}
>
{/* Stats Cards */}
<s-section>
<s-grid columns="1" md-columns="3" gap="400">
<s-box border="base" borderRadius="base" padding="400">
<s-stack gap="200" direction="vertical">
<s-text variant="headingMd">Total Products</s-text>
<s-text variant="heading2xl">{stats.total}</s-text>
</s-stack>
</s-box>
<s-box border="base" borderRadius="base" padding="400">
<s-stack gap="200" direction="vertical">
<s-text variant="headingMd">Active</s-text>
<s-text variant="heading2xl">{stats.active}</s-text>
<s-badge tone="success">+12%</s-badge>
</s-stack>
</s-box>
<s-box border="base" borderRadius="base" padding="400">
<s-stack gap="200" direction="vertical">
<s-text variant="headingMd">Draft</s-text>
<s-text variant="heading2xl">{stats.draft}</s-text>
</s-stack>
</s-box>
</s-grid>
</s-section>
{/* Filters */}
<s-section>
<s-card>
<s-stack gap="300" alignment="space-between">
<s-search-field
placeholder="Search products..."
value={searchQuery}
/>
<s-select
label="Status"
options={[
{ label: "All", value: "all" },
{ label: "Active", value: "active" },
{ label: "Draft", value: "draft" },
]}
/>
</s-stack>
</s-card>
</s-section>
{/* Data Table */}
<s-section>
{products.length === 0 ? (
<s-card>
<s-empty-state
heading="No products found"
image="https://cdn.shopify.com/..."
>
<s-text>Try adjusting your filters or add a new product</s-text>
<s-button variant="primary" url="/products/new">
Add Product
</s-button>
</s-empty-state>
</s-card>
) : (
<s-card>
<s-table>
<s-table-head>
<s-table-row>
<s-table-cell as="th">Product</s-table-cell>
<s-table-cell as="th">Status</s-table-cell>
<s-table-cell as="th">Inventory</s-table-cell>
<s-table-cell as="th">Price</s-table-cell>
<s-table-cell as="th">Actions</s-table-cell>
</s-table-row>
</s-table-head>
<s-table-body>
{products.map(product => (
<s-table-row key={product.id}>
<s-table-cell>
<s-stack gap="200">
<s-thumbnail source={product.image} size="small" />
<s-text>{product.title}</s-text>
</s-stack>
</s-table-cell>
<s-table-cell>
<s-badge tone={product.active ? "success" : undefined}>
{product.active ? "Active" : "Draft"}
</s-badge>
</s-table-cell>
<s-table-cell>{product.inventory} in stock</s-table-cell>
<s-table-cell>${product.price}</s-table-cell>
<s-table-cell>
<s-button-group>
<s-button variant="plain" url={`/products/${product.id}`}>
Edit
</s-button>
<s-button variant="plain" tone="critical">
Delete
</s-button>
</s-button-group>
</s-table-cell>
</s-table-row>
))}
</s-table-body>
</s-table>
{/* Pagination */}
<s-box padding="400">
<s-stack gap="200" alignment="center">
<s-button disabled={page === 1}>Previous</s-button>
<s-text>Page {page} of {totalPages}</s-text>
<s-button disabled={page === totalPages}>Next</s-button>
</s-stack>
</s-box>
</s-card>
)}
</s-section>
</s-page>
```
### Settings Page Template
```tsx
<s-page heading="Settings">
{/* General Settings */}
<s-section>
<s-card>
<s-stack gap="400" direction="vertical">
<s-heading>General</s-heading>
<s-text-field
label="Store Name"
value={settings.storeName}
helpText="This appears in your emails and online store"
/>
<s-text-field
label="Contact Email"
type="email"
value={settings.contactEmail}
/>
<s-text-field
label="Customer Support Email"
type="email"
value={settings.supportEmail}
/>
</s-stack>
</s-card>
</s-section>
{/* Notifications */}
<s-section>
<s-card>
<s-stack gap="400" direction="vertical">
<s-heading>Notifications</s-heading>
<s-text tone="subdued">
Choose which notifications you want to receive
</s-text>
<s-divider />
<s-checkbox
label="Email notifications"
checked={settings.emailNotifications}
helpText="Receive updates via email"
/>
<s-checkbox
label="Order notifications"
checked={settings.orderNotifications}
helpText="Get notified about new orders"
/>
<s-checkbox
label="Customer messages"
checked={settings.customerMessages}
helpText="Receive customer inquiries"
/>
</s-stack>
</s-card>
</s-section>
{/* Advanced Settings */}
<s-section>
<s-card>
<s-stack gap="400" direction="vertical">
<s-heading>Advanced</s-heading>
<s-banner tone="warning">
<s-text>
These settings can affect your store's functionality.
Change with caution.
</s-text>
</s-banner>
<s-divider />
<s-checkbox
label="Enable API access"
checked={settings.apiEnabled}
/>
<s-checkbox
label="Debug mode"
checked={settings.debugMode}
/>
</s-stack>
</s-card>
</s-section>
{/* Save Section */}
<s-section>
<s-stack gap="300" alignment="trailing">
<s-button>Reset to Defaults</s-button>
<s-button variant="primary">Save Settings</s-button>
</s-stack>
</s-section>
</s-page>
```
### Dashboard/Homepage Template
```tsx
<s-page heading="Dashboard">
{/* Welcome Message */}
<s-section>
<s-banner tone="info">
<s-stack gap="200" direction="vertical">
<s-text variant="headingMd">Welcome back!</s-text>
<s-text>
You have 3 orders to fulfill and 2 customer messages.
</s-text>
</s-stack>
</s-banner>
</s-section>
{/* Key Metrics */}
<s-section>
<s-grid columns="1" md-columns="2" lg-columns="4" gap="400">
<s-box border="base" borderRadius="base" padding="400">
<s-stack gap="200" direction="vertical">
<s-text variant="headingMd">Today's Sales</s-text>
<s-text variant="heading2xl">$2,453</s-text>
<s-badge tone="success">+15% from yesterday</s-badge>
</s-stack>
</s-box>
<s-box border="base" borderRadius="base" padding="400">
<s-stack gap="200" direction="vertical">
<s-text variant="headingMd">Orders</s-text>
<s-text variant="heading2xl">34</s-text>
<s-badge>5 pending</s-badge>
</s-stack>
</s-box>
<s-box border="base" borderRadius="base" padding="400">
<s-stack gap="200" direction="vertical">
<s-text variant="headingMd">Conversion Rate</s-text>
<s-text variant="heading2xl">3.2%</s-text>
<s-badge tone="success">+0.3%</s-badge>
</s-stack>
</s-box>
<s-box border="base" borderRadius="base" padding="400">
<s-stack gap="200" direction="vertical">
<s-text variant="headingMd">Average Order</s-text>
<s-text variant="heading2xl">$72.15</s-text>
<s-badge tone="warning">-2%</s-badge>
</s-stack>
</s-box>
</s-grid>
</s-section>
{/* Quick Actions */}
<s-section>
<s-grid columns="1" md-columns="3" gap="400">
<s-card>
<s-stack gap="300" direction="vertical">
<s-heading>Orders</s-heading>
<s-text tone="subdued">5 orders need fulfillment</s-text>
<s-button url="/orders">Manage Orders</s-button>
</s-stack>
</s-card>
<s-card>
<s-stack gap="300" direction="vertical">
<s-heading>Products</s-heading>
<s-text tone="subdued">3 products low in stock</s-text>
<s-button url="/products">View Inventory</s-button>
</s-stack>
</s-card>
<s-card>
<s-stack gap="300" direction="vertical">
<s-heading>Customers</s-heading>
<s-text tone="subdued">2 messages waiting</s-text>
<s-button url="/customers">View Messages</s-button>
</s-stack>
</s-card>
</s-grid>
</s-section>
{/* Recent Activity */}
<s-section>
<s-card>
<s-stack gap="400" direction="vertical">
<s-heading>Recent Orders</s-heading>
<s-table>
<s-table-head>
<s-table-row>
<s-table-cell as="th">Order</s-table-cell>
<s-table-cell as="th">Customer</s-table-cell>
<s-table-cell as="th">Total</s-table-cell>
<s-table-cell as="th">Status</s-table-cell>
</s-table-row>
</s-table-head>
<s-table-body>
{recentOrders.map(order => (
<s-table-row key={order.id}>
<s-table-cell>#{order.number}</s-table-cell>
<s-table-cell>{order.customer}</s-table-cell>
<s-table-cell>${order.total}</s-table-cell>
<s-table-cell>
<s-badge tone={order.fulfilled ? "success" : "warning"}>
{order.fulfilled ? "Fulfilled" : "Pending"}
</s-badge>
</s-table-cell>
</s-table-row>
))}
</s-table-body>
</s-table>
</s-stack>
</s-card>
</s-section>
</s-page>
```
## Pattern Components Reference
For detailed pattern documentation, see:
- `polaris-web-components/patterns/compositions/` - All composition patterns
- `polaris-web-components/patterns/templates/` - Complete page templates
### Quick Pattern Reference
| Pattern | File | Use Case |
|---------|------|----------|
| Index Table | `index-table.md` | Product lists, order lists |
| Settings | `settings.md` | App configuration pages |
| Homepage | `homepage.md` | Dashboard layouts |
| Empty State | `empty-state.md` | No content states |
| Metrics Card | `metrics-card.md` | KPI displays |
| Resource List | `resource-list.md` | Filterable lists |
| Setup Guide | `setup-guide.md` | Onboarding flows |
## Best Practices
1. **Follow Templates** - Use established templates for common pages
2. **Consistent Layout** - Maintain consistent structure across pages
3. **Progressive Disclosure** - Show advanced options only when needed
4. **Clear Hierarchy** - Use sections to organize content logically
5. **Actionable CTAs** - Make primary actions obvious
6. **Empty States** - Always provide guidance when no data exists
7. **Loading States** - Show skeletons during data fetch
8. **Error Handling** - Display clear, actionable error messages
9. **Mobile Responsive** - All patterns work on mobile devices
10. **Accessibility** - Ensure keyboard navigation and screen readers work
---
**Remember**: Using established patterns improves UX consistency and reduces development time.

View File

@@ -0,0 +1,315 @@
---
name: polaris-fundamentals
description: Core Polaris Web Components fundamentals including component library structure, design tokens, responsive patterns, and SSR compatibility. Auto-invoked when working with Polaris components.
allowed-tools: [Read, Grep, Glob]
documentation_path: ../../../polaris-web-components
---
# Polaris Fundamentals Skill
## Purpose
Provides foundational knowledge of Polaris Web Components, including setup, component categories, design tokens, and best practices.
## When This Skill Activates
- Working with Polaris Web Components
- Building Shopify app UIs
- Implementing design system patterns
- Choosing components for specific use cases
## Core Concepts
### Component Categories
Polaris Web Components are organized into six categories:
**1. Actions** - Interactive elements that trigger actions
- Buttons, links, icon buttons, button groups
**2. Forms** - Input and selection components
- Text fields, checkboxes, selects, file uploads, color pickers
**3. Feedback** - Status and notification components
- Banners, toasts, progress bars, spinners, skeletons
**4. Media** - Visual content components
- Avatars, icons, thumbnails, video thumbnails
**5. Structure** - Layout and organization components
- Pages, cards, sections, boxes, grids, stacks, tables
**6. Titles and Text** - Typography components
- Headings, text, paragraphs, badges, chips
### Design Tokens
#### Spacing Scale
```tsx
gap="050" // 2px
gap="100" // 4px
gap="200" // 8px
gap="300" // 12px
gap="400" // 16px (default)
gap="500" // 20px
gap="600" // 24px
gap="800" // 32px
gap="1000" // 40px
gap="1600" // 64px
```
#### Background Colors
```tsx
background="bg-surface" // Default surface
background="bg-surface-secondary" // Secondary surface
background="bg-surface-tertiary" // Tertiary surface
background="bg-surface-success" // Success state
background="bg-surface-warning" // Warning state
background="bg-surface-critical" // Error state
```
#### Border Options
```tsx
border="base" // Default border
border="success" // Success border
border="warning" // Warning border
border="critical" // Error border
```
#### Border Radius
```tsx
borderRadius="base" // 4px
borderRadius="large" // 8px
borderRadius="full" // 50% (circular)
```
#### Text Tones
```tsx
tone="subdued" // Secondary text
tone="success" // Success message
tone="warning" // Warning message
tone="critical" // Error message
```
### Typography Variants
```tsx
variant="heading3xl" // Page titles
variant="heading2xl" // Section headers
variant="headingXl" // Card titles
variant="headingLg" // Subsection headers
variant="headingMd" // Card headers
variant="headingSm" // Small headers
variant="bodyLg" // Large body text
variant="bodyMd" // Default body text (default)
variant="bodySm" // Small body text
```
### Responsive Breakpoints
```tsx
// Mobile first approach
columns="1" // Mobile (default)
sm-columns="2" // Small devices (≥577px)
md-columns="3" // Medium devices (≥769px)
lg-columns="4" // Large devices (≥1025px)
// Example usage
<s-grid columns="1" md-columns="2" lg-columns="4">
<div>Column 1</div>
<div>Column 2</div>
<div>Column 3</div>
<div>Column 4</div>
</s-grid>
```
## React Hydration (SSR Apps)
### ⚠️ CRITICAL: Event Handler Pattern
**NEVER use inline event handlers** - they cause hydration mismatches in SSR apps.
```tsx
// ❌ WRONG - Hydration mismatch
<s-button onclick={handleClick}>Click</s-button>
// ✅ CORRECT - Use data attributes + useEffect
<s-button data-my-button>Click</s-button>
useEffect(() => {
const button = document.querySelector('[data-my-button]');
if (button) {
button.addEventListener('click', handleClick);
}
return () => button?.removeEventListener('click', handleClick);
}, []);
```
## Common Component Patterns
### Button Variants
```tsx
<s-button>Default</s-button>
<s-button variant="primary">Primary</s-button>
<s-button variant="destructive">Delete</s-button>
<s-button variant="plain">Plain</s-button>
<s-button size="slim">Small</s-button>
<s-button loading>Loading</s-button>
<s-button disabled>Disabled</s-button>
```
### Text Field States
```tsx
<s-text-field
label="Product Title"
value={title}
error={errors.title} // Show error
disabled={isDisabled} // Disable input
required // Mark required
helpText="Customer-facing" // Help text
placeholder="Enter title" // Placeholder
/>
```
### Card Structure
```tsx
<s-card>
<s-stack gap="400" direction="vertical">
<s-heading>Card Title</s-heading>
<s-divider />
<s-text>Card content</s-text>
<s-divider />
<s-button-group>
<s-button variant="primary">Save</s-button>
<s-button>Cancel</s-button>
</s-button-group>
</s-stack>
</s-card>
```
### Loading Pattern
```tsx
{isLoading ? (
<s-card>
<s-stack gap="400" direction="vertical">
<s-skeleton-display-text />
<s-skeleton-display-text />
<s-skeleton-display-text />
</s-stack>
</s-card>
) : (
<s-card>{/* Actual content */}</s-card>
)}
```
### Empty State Pattern
```tsx
{items.length === 0 ? (
<s-empty-state
heading="No items yet"
image="https://cdn.shopify.com/..."
>
<s-text>Get started by adding your first item</s-text>
<s-button variant="primary">Add Item</s-button>
</s-empty-state>
) : (
// Item list
)}
```
## Page Structure
### Standard Page Layout
```tsx
<s-page heading="Page Title">
<s-section>
{/* First section */}
</s-section>
<s-section>
{/* Second section */}
</s-section>
</s-page>
```
### Page with Primary Action
```tsx
<s-page
heading="Products"
primaryAction={{
content: "Add Product",
url: "/products/new"
}}
>
{/* Page content */}
</s-page>
```
## Accessibility
### Semantic HTML
```tsx
<s-heading as="h1">Main Title</s-heading>
<s-heading as="h2">Section Title</s-heading>
<s-text as="p">Paragraph text</s-text>
```
### ARIA Labels
```tsx
<s-icon-button
icon="delete"
aria-label="Delete product"
/>
<s-search-field
aria-label="Search products"
placeholder="Search..."
/>
```
### Keyboard Navigation
- All interactive elements are keyboard accessible
- Use Tab to navigate
- Enter/Space to activate buttons
- Escape to close modals
## Best Practices
1. **Use Design Tokens** - Never hardcode colors, spacing, or typography
2. **Mobile First** - Start with mobile layout, enhance for desktop
3. **Semantic HTML** - Use the `as` prop for proper HTML elements
4. **Loading States** - Always show skeleton loaders during data fetch
5. **Empty States** - Provide guidance when no data exists
6. **Error Handling** - Use inline errors for form validation
7. **Accessibility** - Ensure keyboard navigation and ARIA labels
8. **Consistent Spacing** - Use Polaris spacing scale (gap="400")
9. **SSR Compatible** - Use data attributes for event handlers
10. **Follow Patterns** - Use established Polaris patterns
## Component Selection Guide
| Need | Component | Example |
|------|-----------|---------|
| Primary action | `<s-button variant="primary">` | Save, Submit |
| Secondary action | `<s-button>` | Cancel, Back |
| Destructive action | `<s-button variant="destructive">` | Delete, Remove |
| Page container | `<s-page>` | All pages |
| Content container | `<s-card>` | Forms, data displays |
| Text input | `<s-text-field>` | Title, description |
| Selection | `<s-select>` | Category, status |
| Multiple choices | `<s-checkbox>` | Features, options |
| Success message | `<s-banner tone="success">` | Saved successfully |
| Error message | `<s-banner tone="critical">` | Failed to save |
| Status indicator | `<s-badge>` | Active, Draft |
| Data table | `<s-table>` | Products, orders |
| Vertical spacing | `<s-stack direction="vertical">` | Form fields |
| Horizontal layout | `<s-grid>` | Dashboard cards |
## Documentation Reference
For complete component documentation, see:
- `polaris-web-components/components/` - All component docs
- `polaris-web-components/patterns/` - Composition patterns
- `polaris-web-components/using-polaris-web-components.md` - Setup guide
---
**Remember**: Polaris ensures your app matches Shopify's design system and provides a consistent, accessible user experience.