create-shopify-firebase-app 2.0.5 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,9 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Components - {{APP_NAME}}</title>
7
7
  <link rel="stylesheet" href="/css/app.css">
8
+ <meta name="shopify-api-key" content="{{API_KEY}}">
8
9
  <script src="https://cdn.shopify.com/shopifycloud/app-bridge.js"></script>
10
+ <script src="https://cdn.shopify.com/shopifycloud/polaris.js"></script>
9
11
  </head>
10
12
  <body>
11
13
  <ui-nav-menu>
@@ -15,785 +17,1034 @@
15
17
  <a href="/polaris">Components</a>
16
18
  </ui-nav-menu>
17
19
 
18
- <ui-title-bar title="Component Reference"></ui-title-bar>
20
+ <s-page heading="Polaris Web Components Reference">
21
+ <s-link slot="breadcrumb-actions" href="/">Dashboard</s-link>
19
22
 
20
- <div class="page page-wide">
21
23
  <!-- Intro banner -->
22
- <div class="card" style="border-left: 4px solid var(--p-color-primary);">
23
- <h2>UI Component Reference</h2>
24
- <p>A catalog of all available UI components styled to match the Shopify admin. Copy code snippets directly into your pages. Each component uses the Polaris-inspired CSS classes from <code>app.css</code>.</p>
25
- </div>
24
+ <s-section>
25
+ <s-banner tone="info">
26
+ <s-text>A comprehensive catalog of <s-text fontWeight="semibold">Shopify Polaris Web Components</s-text> (<code>&lt;s-*&gt;</code> elements). These are the official Shopify admin UI components loaded from <code>polaris.js</code> CDN. Copy code snippets directly into your pages no build step required.</s-text>
27
+ </s-banner>
28
+ </s-section>
26
29
 
27
30
  <!-- Table of contents -->
28
- <div class="card">
29
- <h2>Quick Navigation</h2>
30
- <div class="flex flex-wrap gap-2 mt-3">
31
- <a href="#section-buttons" class="btn btn-sm">Buttons</a>
32
- <a href="#section-badges" class="btn btn-sm">Badges</a>
33
- <a href="#section-cards" class="btn btn-sm">Cards</a>
34
- <a href="#section-forms" class="btn btn-sm">Forms</a>
35
- <a href="#section-tables" class="btn btn-sm">Tables</a>
36
- <a href="#section-banners" class="btn btn-sm">Banners</a>
37
- <a href="#section-empty-state" class="btn btn-sm">Empty State</a>
38
- <a href="#section-loading" class="btn btn-sm">Loading</a>
39
- <a href="#section-modals" class="btn btn-sm">Modals</a>
40
- <a href="#section-toasts" class="btn btn-sm">Toasts</a>
41
- <a href="#section-layout" class="btn btn-sm">Layout</a>
42
- <a href="#section-resource-picker" class="btn btn-sm">Resource Picker</a>
43
- </div>
44
- </div>
31
+ <s-section heading="Quick Navigation">
32
+ <s-stack direction="inline" gap="small-200" wrap>
33
+ <s-button href="#section-page" variant="tertiary">Page</s-button>
34
+ <s-button href="#section-box" variant="tertiary">Box</s-button>
35
+ <s-button href="#section-stack" variant="tertiary">Stack</s-button>
36
+ <s-button href="#section-grid" variant="tertiary">Grid</s-button>
37
+ <s-button href="#section-text" variant="tertiary">Text &amp; Heading</s-button>
38
+ <s-button href="#section-buttons" variant="tertiary">Buttons</s-button>
39
+ <s-button href="#section-badges" variant="tertiary">Badges</s-button>
40
+ <s-button href="#section-banners" variant="tertiary">Banners</s-button>
41
+ <s-button href="#section-forms" variant="tertiary">Forms</s-button>
42
+ <s-button href="#section-switch" variant="tertiary">Switch</s-button>
43
+ <s-button href="#section-select" variant="tertiary">Select</s-button>
44
+ <s-button href="#section-links" variant="tertiary">Links &amp; Clickable</s-button>
45
+ <s-button href="#section-spinner" variant="tertiary">Spinner</s-button>
46
+ <s-button href="#section-section" variant="tertiary">Section</s-button>
47
+ <s-button href="#section-modals" variant="tertiary">Modals</s-button>
48
+ <s-button href="#section-savebar" variant="tertiary">Save Bar</s-button>
49
+ <s-button href="#section-toasts" variant="tertiary">Toasts</s-button>
50
+ <s-button href="#section-navigation" variant="tertiary">Navigation</s-button>
51
+ <s-button href="#section-resource-picker" variant="tertiary">Resource Picker</s-button>
52
+ <s-button href="#section-patterns" variant="tertiary">Patterns</s-button>
53
+ </s-stack>
54
+ </s-section>
45
55
 
46
56
 
47
57
  <!-- ═══════════════════════════════════════════════════════════ -->
48
- <!-- SECTION 1: BUTTONS -->
58
+ <!-- SECTION: PAGE -->
49
59
  <!-- ═══════════════════════════════════════════════════════════ -->
50
- <div class="demo-section" id="section-buttons">
51
- <h2 class="demo-section-title">Buttons</h2>
52
-
53
- <!-- Primary, Secondary, Destructive -->
54
- <div class="demo-block">
55
- <div class="demo-block-title">Button Variants</div>
56
- <p class="demo-description mt-3">Use different button styles to indicate hierarchy and intent.</p>
57
- <div class="demo-preview">
58
- <div class="btn-group">
59
- <button class="btn btn-primary">Primary</button>
60
- <button class="btn">Secondary</button>
61
- <button class="btn btn-destructive">Destructive</button>
62
- <button class="btn btn-outline">Outline</button>
63
- <button class="btn btn-plain">Plain</button>
64
- </div>
65
- </div>
66
- <div class="demo-code">
67
- <div class="code-block-header">
68
- <span>HTML</span>
69
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
70
- </div>
71
- <pre><code>&lt;button class="btn btn-primary"&gt;Primary&lt;/button&gt;
72
- &lt;button class="btn"&gt;Secondary&lt;/button&gt;
73
- &lt;button class="btn btn-destructive"&gt;Destructive&lt;/button&gt;
74
- &lt;button class="btn btn-outline"&gt;Outline&lt;/button&gt;
75
- &lt;button class="btn btn-plain"&gt;Plain&lt;/button&gt;</code></pre>
76
- </div>
77
- </div>
60
+ <div id="section-page">
61
+ <s-section heading="Page">
62
+ <s-text color="subdued">The top-level container for any admin page. Provides heading, breadcrumbs, and primary actions.</s-text>
63
+
64
+ <s-box paddingBlockStart="base">
65
+ <!-- Basic page -->
66
+ <s-box border="base" borderRadius="base" padding="base">
67
+ <s-stack gap="base">
68
+ <s-text variant="headingSm">Basic Page</s-text>
69
+ <s-text color="subdued">Every page starts with <code>&lt;s-page&gt;</code>. Set the <code>heading</code> attribute for the title.</s-text>
70
+ <div class="demo-code">
71
+ <div class="code-block-header">
72
+ <span>HTML</span>
73
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
74
+ </div>
75
+ <pre><code>&lt;s-page heading="My Page Title"&gt;
76
+ &lt;!-- Page content here --&gt;
77
+ &lt;/s-page&gt;</code></pre>
78
+ </div>
79
+ </s-stack>
80
+ </s-box>
81
+ </s-box>
82
+
83
+ <s-box paddingBlockStart="base">
84
+ <!-- Page with breadcrumbs + primary action -->
85
+ <s-box border="base" borderRadius="base" padding="base">
86
+ <s-stack gap="base">
87
+ <s-text variant="headingSm">Page with Breadcrumbs &amp; Actions</s-text>
88
+ <s-text color="subdued">Use <code>slot="breadcrumb-actions"</code> for back navigation and <code>slot="primary-action"</code> for the main CTA.</s-text>
89
+ <div class="demo-code">
90
+ <div class="code-block-header">
91
+ <span>HTML</span>
92
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
93
+ </div>
94
+ <pre><code>&lt;s-page heading="Product Details"&gt;
95
+ &lt;s-link slot="breadcrumb-actions" href="/"&gt;Dashboard&lt;/s-link&gt;
96
+ &lt;s-button slot="primary-action" variant="primary"&gt;Save&lt;/s-button&gt;
97
+
98
+ &lt;s-section heading="Details"&gt;
99
+ &lt;s-text&gt;Page content here.&lt;/s-text&gt;
100
+ &lt;/s-section&gt;
101
+ &lt;/s-page&gt;</code></pre>
102
+ </div>
103
+ </s-stack>
104
+ </s-box>
105
+ </s-box>
106
+
107
+ <s-box paddingBlockStart="base">
108
+ <!-- Page sizes -->
109
+ <s-box border="base" borderRadius="base" padding="base">
110
+ <s-stack gap="base">
111
+ <s-text variant="headingSm">Page Width</s-text>
112
+ <s-text color="subdued">Control page width with the <code>inlineSize</code> attribute.</s-text>
113
+ <div class="demo-code">
114
+ <div class="code-block-header">
115
+ <span>HTML</span>
116
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
117
+ </div>
118
+ <pre><code>&lt;!-- Default width --&gt;
119
+ &lt;s-page heading="Default"&gt;...&lt;/s-page&gt;
120
+
121
+ &lt;!-- Narrow width (for settings/forms) --&gt;
122
+ &lt;s-page heading="Settings" inlineSize="small"&gt;...&lt;/s-page&gt;</code></pre>
123
+ </div>
124
+ </s-stack>
125
+ </s-box>
126
+ </s-box>
127
+ </s-section>
128
+ </div>
78
129
 
79
- <!-- Sizes -->
80
- <div class="demo-block">
81
- <div class="demo-block-title">Button Sizes</div>
82
- <div class="demo-preview">
83
- <div class="btn-group items-center">
84
- <button class="btn btn-primary btn-sm">Small</button>
85
- <button class="btn btn-primary">Default</button>
86
- <button class="btn btn-primary btn-lg">Large</button>
87
- </div>
88
- </div>
89
- <div class="demo-code">
90
- <div class="code-block-header">
91
- <span>HTML</span>
92
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
93
- </div>
94
- <pre><code>&lt;button class="btn btn-primary btn-sm"&gt;Small&lt;/button&gt;
95
- &lt;button class="btn btn-primary"&gt;Default&lt;/button&gt;
96
- &lt;button class="btn btn-primary btn-lg"&gt;Large&lt;/button&gt;</code></pre>
97
- </div>
98
- </div>
99
130
 
100
- <!-- Disabled & Loading -->
101
- <div class="demo-block">
102
- <div class="demo-block-title">Disabled &amp; Loading</div>
103
- <div class="demo-preview">
104
- <div class="btn-group">
105
- <button class="btn btn-primary" disabled>Disabled</button>
106
- <button class="btn btn-primary btn-loading">Loading</button>
107
- <button class="btn btn-loading">Loading</button>
108
- </div>
109
- </div>
110
- <div class="demo-code">
111
- <div class="code-block-header">
112
- <span>HTML</span>
113
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
131
+ <!-- ═══════════════════════════════════════════════════════════ -->
132
+ <!-- SECTION: BOX -->
133
+ <!-- ═══════════════════════════════════════════════════════════ -->
134
+ <div id="section-box">
135
+ <s-section heading="Box">
136
+ <s-text color="subdued">A flexible container with padding, borders, and background. The building block for cards and custom layouts.</s-text>
137
+
138
+ <s-box paddingBlockStart="base">
139
+ <!-- Live demos -->
140
+ <s-stack gap="base">
141
+ <s-box border="base" borderRadius="base" padding="base">
142
+ <s-text>Basic box with border, radius, and padding.</s-text>
143
+ </s-box>
144
+
145
+ <s-box border="base" borderRadius="base" padding="large-400" background="bg-surface-secondary">
146
+ <s-text>Box with secondary background and large padding.</s-text>
147
+ </s-box>
148
+
149
+ <s-grid gridTemplateColumns="1fr 1fr 1fr" gap="base">
150
+ <s-box border="base" borderRadius="base" padding="base">
151
+ <s-text color="subdued">Column 1</s-text>
152
+ </s-box>
153
+ <s-box border="base" borderRadius="base" padding="base">
154
+ <s-text color="subdued">Column 2</s-text>
155
+ </s-box>
156
+ <s-box border="base" borderRadius="base" padding="base">
157
+ <s-text color="subdued">Column 3</s-text>
158
+ </s-box>
159
+ </s-grid>
160
+ </s-stack>
161
+ </s-box>
162
+
163
+ <s-box paddingBlockStart="base">
164
+ <div class="demo-code">
165
+ <div class="code-block-header">
166
+ <span>HTML</span>
167
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
168
+ </div>
169
+ <pre><code>&lt;!-- Basic box --&gt;
170
+ &lt;s-box border="base" borderRadius="base" padding="base"&gt;
171
+ &lt;s-text&gt;Content here.&lt;/s-text&gt;
172
+ &lt;/s-box&gt;
173
+
174
+ &lt;!-- Box with background --&gt;
175
+ &lt;s-box border="base" borderRadius="base" padding="large-400"
176
+ background="bg-surface-secondary"&gt;
177
+ &lt;s-text&gt;Secondary background.&lt;/s-text&gt;
178
+ &lt;/s-box&gt;
179
+
180
+ &lt;!-- Padding options: small-200, base, large-400, large-1200 --&gt;
181
+ &lt;!-- Border: base, none --&gt;
182
+ &lt;!-- borderRadius: base, large, full --&gt;</code></pre>
114
183
  </div>
115
- <pre><code>&lt;button class="btn btn-primary" disabled&gt;Disabled&lt;/button&gt;
116
- &lt;button class="btn btn-primary btn-loading"&gt;Loading&lt;/button&gt;
117
- &lt;button class="btn btn-loading"&gt;Loading&lt;/button&gt;</code></pre>
118
- </div>
119
- </div>
184
+ </s-box>
185
+ </s-section>
120
186
  </div>
121
187
 
122
188
 
123
189
  <!-- ═══════════════════════════════════════════════════════════ -->
124
- <!-- SECTION 2: BADGES -->
190
+ <!-- SECTION: STACK -->
125
191
  <!-- ═══════════════════════════════════════════════════════════ -->
126
- <div class="demo-section" id="section-badges">
127
- <h2 class="demo-section-title">Badges</h2>
128
-
129
- <div class="demo-block">
130
- <div class="demo-block-title">Badge Variants</div>
131
- <p class="demo-description mt-3">Badges communicate status, labels, and metadata in a compact format.</p>
132
- <div class="demo-preview">
133
- <div class="flex flex-wrap gap-3 items-center">
134
- <span class="badge badge-default">Default</span>
135
- <span class="badge badge-success">Success</span>
136
- <span class="badge badge-warning">Warning</span>
137
- <span class="badge badge-critical">Critical</span>
138
- <span class="badge badge-info">Info</span>
139
- <span class="badge badge-attention">Attention</span>
140
- <span class="badge badge-new">New</span>
141
- </div>
142
- </div>
143
- <div class="demo-code">
144
- <div class="code-block-header">
145
- <span>HTML</span>
146
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
147
- </div>
148
- <pre><code>&lt;span class="badge badge-default"&gt;Default&lt;/span&gt;
149
- &lt;span class="badge badge-success"&gt;Success&lt;/span&gt;
150
- &lt;span class="badge badge-warning"&gt;Warning&lt;/span&gt;
151
- &lt;span class="badge badge-critical"&gt;Critical&lt;/span&gt;
152
- &lt;span class="badge badge-info"&gt;Info&lt;/span&gt;
153
- &lt;span class="badge badge-attention"&gt;Attention&lt;/span&gt;
154
- &lt;span class="badge badge-new"&gt;New&lt;/span&gt;</code></pre>
155
- </div>
156
- </div>
157
-
158
- <div class="demo-block">
159
- <div class="demo-block-title">Badges in Context</div>
160
- <div class="demo-preview">
161
- <ul class="info-list">
162
- <li>
163
- <span class="info-list-label">Order #1001</span>
164
- <span class="badge badge-success">Fulfilled</span>
165
- </li>
166
- <li>
167
- <span class="info-list-label">Order #1002</span>
168
- <span class="badge badge-warning">Pending</span>
169
- </li>
170
- <li>
171
- <span class="info-list-label">Order #1003</span>
172
- <span class="badge badge-critical">Cancelled</span>
173
- </li>
174
- </ul>
175
- </div>
176
- <div class="demo-code">
177
- <div class="code-block-header">
178
- <span>HTML</span>
179
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
192
+ <div id="section-stack">
193
+ <s-section heading="Stack">
194
+ <s-text color="subdued">Flexbox-based layout component. Vertical by default, horizontal with <code>direction="inline"</code>.</s-text>
195
+
196
+ <s-box paddingBlockStart="base">
197
+ <!-- Vertical stack -->
198
+ <s-box border="base" borderRadius="base" padding="base">
199
+ <s-text variant="headingSm">Vertical Stack (default)</s-text>
200
+ <s-box paddingBlockStart="small-200">
201
+ <s-stack gap="base">
202
+ <s-box border="base" borderRadius="base" padding="small-200"><s-text>Item 1</s-text></s-box>
203
+ <s-box border="base" borderRadius="base" padding="small-200"><s-text>Item 2</s-text></s-box>
204
+ <s-box border="base" borderRadius="base" padding="small-200"><s-text>Item 3</s-text></s-box>
205
+ </s-stack>
206
+ </s-box>
207
+ </s-box>
208
+ </s-box>
209
+
210
+ <s-box paddingBlockStart="base">
211
+ <!-- Horizontal stack -->
212
+ <s-box border="base" borderRadius="base" padding="base">
213
+ <s-text variant="headingSm">Inline Stack (horizontal)</s-text>
214
+ <s-box paddingBlockStart="small-200">
215
+ <s-stack direction="inline" gap="base" alignItems="center">
216
+ <s-badge tone="info">Tag 1</s-badge>
217
+ <s-badge tone="success">Tag 2</s-badge>
218
+ <s-badge tone="warning">Tag 3</s-badge>
219
+ <s-button>Action</s-button>
220
+ </s-stack>
221
+ </s-box>
222
+ </s-box>
223
+ </s-box>
224
+
225
+ <s-box paddingBlockStart="base">
226
+ <!-- Wrapping stack -->
227
+ <s-box border="base" borderRadius="base" padding="base">
228
+ <s-text variant="headingSm">Wrapping Stack</s-text>
229
+ <s-box paddingBlockStart="small-200">
230
+ <s-stack direction="inline" gap="small-200" wrap>
231
+ <s-badge>One</s-badge>
232
+ <s-badge>Two</s-badge>
233
+ <s-badge>Three</s-badge>
234
+ <s-badge>Four</s-badge>
235
+ <s-badge>Five</s-badge>
236
+ <s-badge>Six</s-badge>
237
+ <s-badge>Seven</s-badge>
238
+ <s-badge>Eight</s-badge>
239
+ </s-stack>
240
+ </s-box>
241
+ </s-box>
242
+ </s-box>
243
+
244
+ <s-box paddingBlockStart="base">
245
+ <div class="demo-code">
246
+ <div class="code-block-header">
247
+ <span>HTML</span>
248
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
249
+ </div>
250
+ <pre><code>&lt;!-- Vertical (default) --&gt;
251
+ &lt;s-stack gap="base"&gt;
252
+ &lt;s-text&gt;Item 1&lt;/s-text&gt;
253
+ &lt;s-text&gt;Item 2&lt;/s-text&gt;
254
+ &lt;/s-stack&gt;
255
+
256
+ &lt;!-- Horizontal --&gt;
257
+ &lt;s-stack direction="inline" gap="base" alignItems="center"&gt;
258
+ &lt;s-badge&gt;Tag&lt;/s-badge&gt;
259
+ &lt;s-button&gt;Action&lt;/s-button&gt;
260
+ &lt;/s-stack&gt;
261
+
262
+ &lt;!-- Wrapping --&gt;
263
+ &lt;s-stack direction="inline" gap="small-200" wrap&gt;
264
+ &lt;s-badge&gt;Wraps on overflow&lt;/s-badge&gt;
265
+ &lt;/s-stack&gt;
266
+
267
+ &lt;!-- gap: small-200, base, large-400 --&gt;
268
+ &lt;!-- alignItems: center, start, end --&gt;</code></pre>
180
269
  </div>
181
- <pre><code>&lt;ul class="info-list"&gt;
182
- &lt;li&gt;
183
- &lt;span class="info-list-label"&gt;Order #1001&lt;/span&gt;
184
- &lt;span class="badge badge-success"&gt;Fulfilled&lt;/span&gt;
185
- &lt;/li&gt;
186
- &lt;li&gt;
187
- &lt;span class="info-list-label"&gt;Order #1002&lt;/span&gt;
188
- &lt;span class="badge badge-warning"&gt;Pending&lt;/span&gt;
189
- &lt;/li&gt;
190
- &lt;/ul&gt;</code></pre>
191
- </div>
192
- </div>
270
+ </s-box>
271
+ </s-section>
193
272
  </div>
194
273
 
195
274
 
196
275
  <!-- ═══════════════════════════════════════════════════════════ -->
197
- <!-- SECTION 3: CARDS -->
276
+ <!-- SECTION: GRID -->
198
277
  <!-- ═══════════════════════════════════════════════════════════ -->
199
- <div class="demo-section" id="section-cards">
200
- <h2 class="demo-section-title">Cards</h2>
201
-
202
- <!-- Basic card -->
203
- <div class="demo-block">
204
- <div class="demo-block-title">Basic Card</div>
205
- <p class="demo-description mt-3">Cards are the primary container for content. Use them to group related information.</p>
206
- <div class="demo-preview">
207
- <div class="card" style="margin-bottom:0;">
208
- <h2>Card Title</h2>
209
- <p>This is a basic card with a title and body text. Cards automatically get padding, a border, and a subtle shadow.</p>
210
- </div>
211
- </div>
212
- <div class="demo-code">
213
- <div class="code-block-header">
214
- <span>HTML</span>
215
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
216
- </div>
217
- <pre><code>&lt;div class="card"&gt;
218
- &lt;h2&gt;Card Title&lt;/h2&gt;
219
- &lt;p&gt;Card body text goes here.&lt;/p&gt;
220
- &lt;/div&gt;</code></pre>
221
- </div>
222
- </div>
223
-
224
- <!-- Card with sections -->
225
- <div class="demo-block">
226
- <div class="demo-block-title">Card with Sections</div>
227
- <div class="demo-preview">
228
- <div class="card card-flush" style="margin-bottom:0;">
229
- <div class="card-section">
230
- <h3>Section One</h3>
231
- <p>First section content with separated borders.</p>
278
+ <div id="section-grid">
279
+ <s-section heading="Grid">
280
+ <s-text color="subdued">CSS Grid container with responsive column support using container queries.</s-text>
281
+
282
+ <s-box paddingBlockStart="base">
283
+ <!-- 3-column grid -->
284
+ <s-box border="base" borderRadius="base" padding="base">
285
+ <s-text variant="headingSm">Responsive Grid</s-text>
286
+ <s-box paddingBlockStart="small-200">
287
+ <s-grid gridTemplateColumns="@container (inline-size <= 400px) 1fr, 1fr 1fr 1fr" gap="base">
288
+ <s-box border="base" borderRadius="base" padding="base" background="bg-surface-secondary">
289
+ <s-text>Column A</s-text>
290
+ </s-box>
291
+ <s-box border="base" borderRadius="base" padding="base" background="bg-surface-secondary">
292
+ <s-text>Column B</s-text>
293
+ </s-box>
294
+ <s-box border="base" borderRadius="base" padding="base" background="bg-surface-secondary">
295
+ <s-text>Column C</s-text>
296
+ </s-box>
297
+ </s-grid>
298
+ </s-box>
299
+ </s-box>
300
+ </s-box>
301
+
302
+ <s-box paddingBlockStart="base">
303
+ <!-- 2-column with sidebar -->
304
+ <s-box border="base" borderRadius="base" padding="base">
305
+ <s-text variant="headingSm">Sidebar Layout</s-text>
306
+ <s-box paddingBlockStart="small-200">
307
+ <s-grid gridTemplateColumns="@container (inline-size <= 500px) 1fr, 2fr 1fr" gap="base">
308
+ <s-box border="base" borderRadius="base" padding="base">
309
+ <s-text variant="headingSm">Main Content</s-text>
310
+ <s-text color="subdued">Takes up 2/3 of the width.</s-text>
311
+ </s-box>
312
+ <s-box border="base" borderRadius="base" padding="base" background="bg-surface-secondary">
313
+ <s-text variant="headingSm">Sidebar</s-text>
314
+ <s-text color="subdued">Takes up 1/3.</s-text>
315
+ </s-box>
316
+ </s-grid>
317
+ </s-box>
318
+ </s-box>
319
+ </s-box>
320
+
321
+ <s-box paddingBlockStart="base">
322
+ <div class="demo-code">
323
+ <div class="code-block-header">
324
+ <span>HTML</span>
325
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
232
326
  </div>
233
- <div class="card-section">
234
- <h3>Section Two</h3>
235
- <p>Second section, visually separated from the first.</p>
236
- </div>
237
- <div class="card-section">
238
- <h3>Section Three</h3>
239
- <p>Third section with its own content area.</p>
240
- </div>
241
- </div>
242
- </div>
243
- <div class="demo-code">
244
- <div class="code-block-header">
245
- <span>HTML</span>
246
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
327
+ <pre><code>&lt;!-- Responsive 3-column grid (stacks on small) --&gt;
328
+ &lt;s-grid gridTemplateColumns="@container (inline-size &lt;= 400px) 1fr, 1fr 1fr 1fr" gap="base"&gt;
329
+ &lt;s-box&gt;Col 1&lt;/s-box&gt;
330
+ &lt;s-box&gt;Col 2&lt;/s-box&gt;
331
+ &lt;s-box&gt;Col 3&lt;/s-box&gt;
332
+ &lt;/s-grid&gt;
333
+
334
+ &lt;!-- Sidebar layout --&gt;
335
+ &lt;s-grid gridTemplateColumns="@container (inline-size &lt;= 500px) 1fr, 2fr 1fr" gap="base"&gt;
336
+ &lt;s-box&gt;Main content&lt;/s-box&gt;
337
+ &lt;s-box&gt;Sidebar&lt;/s-box&gt;
338
+ &lt;/s-grid&gt;
339
+
340
+ &lt;!-- Static columns --&gt;
341
+ &lt;s-grid gridTemplateColumns="1fr 1fr" gap="base"&gt;
342
+ &lt;s-box&gt;Left&lt;/s-box&gt;
343
+ &lt;s-box&gt;Right&lt;/s-box&gt;
344
+ &lt;/s-grid&gt;</code></pre>
247
345
  </div>
248
- <pre><code>&lt;div class="card card-flush"&gt;
249
- &lt;div class="card-section"&gt;
250
- &lt;h3&gt;Section One&lt;/h3&gt;
251
- &lt;p&gt;First section content.&lt;/p&gt;
252
- &lt;/div&gt;
253
- &lt;div class="card-section"&gt;
254
- &lt;h3&gt;Section Two&lt;/h3&gt;
255
- &lt;p&gt;Second section content.&lt;/p&gt;
256
- &lt;/div&gt;
257
- &lt;/div&gt;</code></pre>
258
- </div>
259
- </div>
346
+ </s-box>
347
+ </s-section>
348
+ </div>
349
+
260
350
 
261
- <!-- Card with header actions -->
262
- <div class="demo-block">
263
- <div class="demo-block-title">Card with Header Actions</div>
264
- <div class="demo-preview">
265
- <div class="card" style="margin-bottom:0;">
266
- <div class="card-header">
267
- <h2>Recent Orders</h2>
268
- <button class="btn btn-sm btn-plain">View all</button>
351
+ <!-- ═══════════════════════════════════════════════════════════ -->
352
+ <!-- SECTION: TEXT & HEADING -->
353
+ <!-- ═══════════════════════════════════════════════════════════ -->
354
+ <div id="section-text">
355
+ <s-section heading="Text &amp; Heading">
356
+ <s-text color="subdued">Typography components for headings, body text, and paragraphs.</s-text>
357
+
358
+ <s-box paddingBlockStart="base">
359
+ <s-box border="base" borderRadius="base" padding="base">
360
+ <s-stack gap="base">
361
+ <s-text variant="heading2xl">Heading 2XL</s-text>
362
+ <s-text variant="headingXl">Heading XL</s-text>
363
+ <s-text variant="headingLg">Heading Lg</s-text>
364
+ <s-text variant="headingMd">Heading Md</s-text>
365
+ <s-text variant="headingSm">Heading Sm</s-text>
366
+ <s-text variant="headingXs">Heading Xs</s-text>
367
+ <s-text variant="bodyLg">Body Large text</s-text>
368
+ <s-text variant="bodyMd">Body Medium text (default)</s-text>
369
+ <s-text variant="bodySm">Body Small text</s-text>
370
+ </s-stack>
371
+ </s-box>
372
+ </s-box>
373
+
374
+ <s-box paddingBlockStart="base">
375
+ <!-- Text colors & weights -->
376
+ <s-box border="base" borderRadius="base" padding="base">
377
+ <s-text variant="headingSm">Colors &amp; Weights</s-text>
378
+ <s-box paddingBlockStart="small-200">
379
+ <s-stack gap="small-200">
380
+ <s-text>Default color</s-text>
381
+ <s-text color="subdued">Subdued color</s-text>
382
+ <s-text color="success">Success color</s-text>
383
+ <s-text color="critical">Critical color</s-text>
384
+ <s-text color="warning">Warning color</s-text>
385
+ <s-text fontWeight="bold">Bold weight</s-text>
386
+ <s-text fontWeight="semibold">Semibold weight</s-text>
387
+ <s-text fontWeight="medium">Medium weight</s-text>
388
+ </s-stack>
389
+ </s-box>
390
+ </s-box>
391
+ </s-box>
392
+
393
+ <s-box paddingBlockStart="base">
394
+ <!-- Heading & Paragraph -->
395
+ <s-box border="base" borderRadius="base" padding="base">
396
+ <s-text variant="headingSm">Heading &amp; Paragraph Elements</s-text>
397
+ <s-box paddingBlockStart="small-200">
398
+ <s-stack gap="base">
399
+ <s-heading>This is an &lt;s-heading&gt;</s-heading>
400
+ <s-paragraph>This is an &lt;s-paragraph&gt;. Use it for longer blocks of body text. Paragraphs automatically apply proper spacing and line height for readability.</s-paragraph>
401
+ <s-paragraph color="subdued">A subdued paragraph for secondary information.</s-paragraph>
402
+ </s-stack>
403
+ </s-box>
404
+ </s-box>
405
+ </s-box>
406
+
407
+ <s-box paddingBlockStart="base">
408
+ <div class="demo-code">
409
+ <div class="code-block-header">
410
+ <span>HTML</span>
411
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
269
412
  </div>
270
- <ul class="info-list">
271
- <li>
272
- <span class="info-list-label">Order #1234</span>
273
- <span class="info-list-value">$149.00</span>
274
- </li>
275
- <li>
276
- <span class="info-list-label">Order #1235</span>
277
- <span class="info-list-value">$89.50</span>
278
- </li>
279
- </ul>
280
- </div>
281
- </div>
282
- <div class="demo-code">
283
- <div class="code-block-header">
284
- <span>HTML</span>
285
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
413
+ <pre><code>&lt;!-- Heading variants --&gt;
414
+ &lt;s-text variant="headingLg"&gt;Large Heading&lt;/s-text&gt;
415
+ &lt;s-text variant="headingMd"&gt;Medium Heading&lt;/s-text&gt;
416
+ &lt;s-text variant="headingSm"&gt;Small Heading&lt;/s-text&gt;
417
+
418
+ &lt;!-- Body text --&gt;
419
+ &lt;s-text&gt;Default body text&lt;/s-text&gt;
420
+ &lt;s-text variant="bodySm"&gt;Small body text&lt;/s-text&gt;
421
+
422
+ &lt;!-- Colors --&gt;
423
+ &lt;s-text color="subdued"&gt;Muted text&lt;/s-text&gt;
424
+ &lt;s-text color="success"&gt;Success&lt;/s-text&gt;
425
+ &lt;s-text color="critical"&gt;Error&lt;/s-text&gt;
426
+
427
+ &lt;!-- Font weight --&gt;
428
+ &lt;s-text fontWeight="bold"&gt;Bold text&lt;/s-text&gt;
429
+ &lt;s-text fontWeight="semibold"&gt;Semibold text&lt;/s-text&gt;
430
+
431
+ &lt;!-- Block elements --&gt;
432
+ &lt;s-heading&gt;Section heading&lt;/s-heading&gt;
433
+ &lt;s-paragraph&gt;A paragraph of text.&lt;/s-paragraph&gt;
434
+ &lt;s-paragraph color="subdued"&gt;Muted paragraph.&lt;/s-paragraph&gt;</code></pre>
286
435
  </div>
287
- <pre><code>&lt;div class="card"&gt;
288
- &lt;div class="card-header"&gt;
289
- &lt;h2&gt;Recent Orders&lt;/h2&gt;
290
- &lt;button class="btn btn-sm btn-plain"&gt;View all&lt;/button&gt;
291
- &lt;/div&gt;
292
- &lt;ul class="info-list"&gt;
293
- &lt;li&gt;
294
- &lt;span class="info-list-label"&gt;Order #1234&lt;/span&gt;
295
- &lt;span class="info-list-value"&gt;$149.00&lt;/span&gt;
296
- &lt;/li&gt;
297
- &lt;/ul&gt;
298
- &lt;/div&gt;</code></pre>
299
- </div>
300
- </div>
436
+ </s-box>
437
+ </s-section>
438
+ </div>
301
439
 
302
- <!-- Card grid -->
303
- <div class="demo-block">
304
- <div class="demo-block-title">Card Grid</div>
305
- <div class="demo-preview">
306
- <div class="card-grid">
307
- <div class="card" style="margin-bottom:0;">
308
- <h3>Card A</h3>
309
- <p>Responsive grid layout for multiple cards.</p>
310
- </div>
311
- <div class="card" style="margin-bottom:0;">
312
- <h3>Card B</h3>
313
- <p>Cards automatically wrap on smaller screens.</p>
314
- </div>
315
- <div class="card" style="margin-bottom:0;">
316
- <h3>Card C</h3>
317
- <p>Use <code>card-grid</code> for equal-width columns.</p>
440
+
441
+ <!-- ═══════════════════════════════════════════════════════════ -->
442
+ <!-- SECTION: BUTTONS -->
443
+ <!-- ═══════════════════════════════════════════════════════════ -->
444
+ <div id="section-buttons">
445
+ <s-section heading="Buttons">
446
+ <s-text color="subdued">Interactive buttons with variants, tones, loading, and disabled states.</s-text>
447
+
448
+ <s-box paddingBlockStart="base">
449
+ <!-- Button variants -->
450
+ <s-box border="base" borderRadius="base" padding="base">
451
+ <s-text variant="headingSm">Button Variants</s-text>
452
+ <s-box paddingBlockStart="small-200">
453
+ <s-stack direction="inline" gap="small-200" wrap>
454
+ <s-button variant="primary">Primary</s-button>
455
+ <s-button>Secondary (default)</s-button>
456
+ <s-button variant="tertiary">Tertiary</s-button>
457
+ <s-button variant="primary" tone="critical">Critical Primary</s-button>
458
+ <s-button tone="critical">Critical</s-button>
459
+ </s-stack>
460
+ </s-box>
461
+ </s-box>
462
+ </s-box>
463
+
464
+ <s-box paddingBlockStart="base">
465
+ <!-- States -->
466
+ <s-box border="base" borderRadius="base" padding="base">
467
+ <s-text variant="headingSm">States</s-text>
468
+ <s-box paddingBlockStart="small-200">
469
+ <s-stack direction="inline" gap="small-200" wrap>
470
+ <s-button variant="primary" disabled>Disabled Primary</s-button>
471
+ <s-button disabled>Disabled</s-button>
472
+ <s-button variant="primary" loading>Loading</s-button>
473
+ <s-button loading>Loading</s-button>
474
+ </s-stack>
475
+ </s-box>
476
+ </s-box>
477
+ </s-box>
478
+
479
+ <s-box paddingBlockStart="base">
480
+ <!-- Button as link -->
481
+ <s-box border="base" borderRadius="base" padding="base">
482
+ <s-text variant="headingSm">Button as Link</s-text>
483
+ <s-box paddingBlockStart="small-200">
484
+ <s-stack direction="inline" gap="small-200">
485
+ <s-button variant="primary" href="/products">Navigate to Products</s-button>
486
+ <s-button href="https://polaris.shopify.com" target="_blank">Polaris Docs (external)</s-button>
487
+ </s-stack>
488
+ </s-box>
489
+ </s-box>
490
+ </s-box>
491
+
492
+ <s-box paddingBlockStart="base">
493
+ <div class="demo-code">
494
+ <div class="code-block-header">
495
+ <span>HTML</span>
496
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
318
497
  </div>
498
+ <pre><code>&lt;!-- Variants --&gt;
499
+ &lt;s-button variant="primary"&gt;Primary&lt;/s-button&gt;
500
+ &lt;s-button&gt;Secondary&lt;/s-button&gt;
501
+ &lt;s-button variant="tertiary"&gt;Tertiary&lt;/s-button&gt;
502
+
503
+ &lt;!-- Destructive --&gt;
504
+ &lt;s-button variant="primary" tone="critical"&gt;Delete&lt;/s-button&gt;
505
+ &lt;s-button tone="critical"&gt;Remove&lt;/s-button&gt;
506
+
507
+ &lt;!-- States --&gt;
508
+ &lt;s-button disabled&gt;Disabled&lt;/s-button&gt;
509
+ &lt;s-button loading&gt;Loading&lt;/s-button&gt;
510
+
511
+ &lt;!-- As link --&gt;
512
+ &lt;s-button href="/page"&gt;Navigate&lt;/s-button&gt;
513
+ &lt;s-button href="https://example.com" target="_blank"&gt;External&lt;/s-button&gt;</code></pre>
319
514
  </div>
320
- </div>
321
- <div class="demo-code">
322
- <div class="code-block-header">
323
- <span>HTML</span>
324
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
325
- </div>
326
- <pre><code>&lt;div class="card-grid"&gt;
327
- &lt;div class="card"&gt;
328
- &lt;h3&gt;Card A&lt;/h3&gt;
329
- &lt;p&gt;Content here.&lt;/p&gt;
330
- &lt;/div&gt;
331
- &lt;div class="card"&gt;
332
- &lt;h3&gt;Card B&lt;/h3&gt;
333
- &lt;p&gt;Content here.&lt;/p&gt;
334
- &lt;/div&gt;
335
- &lt;/div&gt;</code></pre>
336
- </div>
337
- </div>
515
+ </s-box>
516
+ </s-section>
338
517
  </div>
339
518
 
340
519
 
341
520
  <!-- ═══════════════════════════════════════════════════════════ -->
342
- <!-- SECTION 4: FORMS -->
521
+ <!-- SECTION: BADGES -->
343
522
  <!-- ═══════════════════════════════════════════════════════════ -->
344
- <div class="demo-section" id="section-forms">
345
- <h2 class="demo-section-title">Forms</h2>
346
-
347
- <!-- Text input -->
348
- <div class="demo-block">
349
- <div class="demo-block-title">Text Inputs</div>
350
- <p class="demo-description mt-3">Standard form inputs with labels, hints, and validation states.</p>
351
- <div class="demo-preview">
352
- <div class="form-group">
353
- <label for="demo-name">Store name</label>
354
- <input type="text" class="form-input" id="demo-name" placeholder="My Awesome Store" value="">
355
- <p class="form-hint">The public-facing name of your store.</p>
356
- </div>
357
- <div class="form-group">
358
- <label for="demo-email">Email (error state)</label>
359
- <input type="email" class="form-input form-input-error" id="demo-email" value="not-valid">
360
- <p class="form-error">Please enter a valid email address.</p>
361
- </div>
362
- </div>
363
- <div class="demo-code">
364
- <div class="code-block-header">
365
- <span>HTML</span>
366
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
523
+ <div id="section-badges">
524
+ <s-section heading="Badges">
525
+ <s-text color="subdued">Compact status indicators and labels.</s-text>
526
+
527
+ <s-box paddingBlockStart="base">
528
+ <s-box border="base" borderRadius="base" padding="base">
529
+ <s-text variant="headingSm">Badge Tones</s-text>
530
+ <s-box paddingBlockStart="small-200">
531
+ <s-stack direction="inline" gap="small-200" wrap>
532
+ <s-badge>Default</s-badge>
533
+ <s-badge tone="info">Info</s-badge>
534
+ <s-badge tone="success">Success</s-badge>
535
+ <s-badge tone="warning">Warning</s-badge>
536
+ <s-badge tone="critical">Critical</s-badge>
537
+ <s-badge tone="attention">Attention</s-badge>
538
+ <s-badge tone="new">New</s-badge>
539
+ <s-badge tone="read-only">Read Only</s-badge>
540
+ <s-badge tone="enabled">Enabled</s-badge>
541
+ </s-stack>
542
+ </s-box>
543
+ </s-box>
544
+ </s-box>
545
+
546
+ <s-box paddingBlockStart="base">
547
+ <!-- Badges in context -->
548
+ <s-box border="base" borderRadius="base" padding="base">
549
+ <s-text variant="headingSm">Badges in Context</s-text>
550
+ <s-box paddingBlockStart="small-200">
551
+ <s-stack gap="small-200">
552
+ <s-stack direction="inline" gap="base" alignItems="center">
553
+ <s-text>Order #1001</s-text>
554
+ <s-badge tone="success">Fulfilled</s-badge>
555
+ </s-stack>
556
+ <s-stack direction="inline" gap="base" alignItems="center">
557
+ <s-text>Order #1002</s-text>
558
+ <s-badge tone="warning">Pending</s-badge>
559
+ </s-stack>
560
+ <s-stack direction="inline" gap="base" alignItems="center">
561
+ <s-text>Order #1003</s-text>
562
+ <s-badge tone="critical">Cancelled</s-badge>
563
+ </s-stack>
564
+ </s-stack>
565
+ </s-box>
566
+ </s-box>
567
+ </s-box>
568
+
569
+ <s-box paddingBlockStart="base">
570
+ <div class="demo-code">
571
+ <div class="code-block-header">
572
+ <span>HTML</span>
573
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
574
+ </div>
575
+ <pre><code>&lt;s-badge&gt;Default&lt;/s-badge&gt;
576
+ &lt;s-badge tone="info"&gt;Info&lt;/s-badge&gt;
577
+ &lt;s-badge tone="success"&gt;Success&lt;/s-badge&gt;
578
+ &lt;s-badge tone="warning"&gt;Warning&lt;/s-badge&gt;
579
+ &lt;s-badge tone="critical"&gt;Critical&lt;/s-badge&gt;
580
+ &lt;s-badge tone="attention"&gt;Attention&lt;/s-badge&gt;
581
+ &lt;s-badge tone="new"&gt;New&lt;/s-badge&gt;
582
+ &lt;s-badge tone="read-only"&gt;Read Only&lt;/s-badge&gt;
583
+ &lt;s-badge tone="enabled"&gt;Enabled&lt;/s-badge&gt;</code></pre>
367
584
  </div>
368
- <pre><code>&lt;div class="form-group"&gt;
369
- &lt;label for="name"&gt;Store name&lt;/label&gt;
370
- &lt;input type="text" class="form-input" id="name"
371
- placeholder="My Awesome Store"&gt;
372
- &lt;p class="form-hint"&gt;Help text here.&lt;/p&gt;
373
- &lt;/div&gt;
585
+ </s-box>
586
+ </s-section>
587
+ </div>
374
588
 
375
- &lt;!-- Error state --&gt;
376
- &lt;div class="form-group"&gt;
377
- &lt;label for="email"&gt;Email&lt;/label&gt;
378
- &lt;input type="email" class="form-input form-input-error"
379
- id="email" value="not-valid"&gt;
380
- &lt;p class="form-error"&gt;Please enter a valid email.&lt;/p&gt;
381
- &lt;/div&gt;</code></pre>
382
- </div>
383
- </div>
384
589
 
385
- <!-- Select -->
386
- <div class="demo-block">
387
- <div class="demo-block-title">Select</div>
388
- <div class="demo-preview">
389
- <div class="form-group">
390
- <label for="demo-country">Country</label>
391
- <select class="form-select" id="demo-country">
392
- <option value="">Select a country</option>
393
- <option value="us">United States</option>
394
- <option value="ca">Canada</option>
395
- <option value="gb">United Kingdom</option>
396
- <option value="au">Australia</option>
397
- </select>
398
- </div>
399
- </div>
400
- <div class="demo-code">
401
- <div class="code-block-header">
402
- <span>HTML</span>
403
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
404
- </div>
405
- <pre><code>&lt;div class="form-group"&gt;
406
- &lt;label for="country"&gt;Country&lt;/label&gt;
407
- &lt;select class="form-select" id="country"&gt;
408
- &lt;option value=""&gt;Select a country&lt;/option&gt;
409
- &lt;option value="us"&gt;United States&lt;/option&gt;
410
- &lt;option value="ca"&gt;Canada&lt;/option&gt;
411
- &lt;/select&gt;
412
- &lt;/div&gt;</code></pre>
413
- </div>
414
- </div>
590
+ <!-- ═══════════════════════════════════════════════════════════ -->
591
+ <!-- SECTION: BANNERS -->
592
+ <!-- ═══════════════════════════════════════════════════════════ -->
593
+ <div id="section-banners">
594
+ <s-section heading="Banners">
595
+ <s-text color="subdued">Alert banners for status messages, errors, and announcements.</s-text>
596
+
597
+ <s-box paddingBlockStart="base">
598
+ <s-stack gap="base">
599
+ <s-banner tone="info">
600
+ <s-text><s-text fontWeight="semibold">Information:</s-text> This is an informational banner. Use for tips and neutral messages.</s-text>
601
+ </s-banner>
602
+
603
+ <s-banner tone="success">
604
+ <s-text><s-text fontWeight="semibold">Success:</s-text> The operation completed successfully. Your changes have been saved.</s-text>
605
+ </s-banner>
606
+
607
+ <s-banner tone="warning">
608
+ <s-text><s-text fontWeight="semibold">Warning:</s-text> This action may have unintended consequences. Please review before proceeding.</s-text>
609
+ </s-banner>
610
+
611
+ <s-banner tone="critical">
612
+ <s-text><s-text fontWeight="semibold">Error:</s-text> Something went wrong. Please try again or contact support.</s-text>
613
+ </s-banner>
614
+ </s-stack>
615
+ </s-box>
616
+
617
+ <s-box paddingBlockStart="base">
618
+ <div class="demo-code">
619
+ <div class="code-block-header">
620
+ <span>HTML</span>
621
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
622
+ </div>
623
+ <pre><code>&lt;s-banner tone="info"&gt;
624
+ &lt;s-text&gt;Informational message.&lt;/s-text&gt;
625
+ &lt;/s-banner&gt;
415
626
 
416
- <!-- Checkbox & Radio -->
417
- <div class="demo-block">
418
- <div class="demo-block-title">Checkboxes &amp; Radios</div>
419
- <div class="demo-preview">
420
- <div class="form-group">
421
- <label class="form-checkbox">
422
- <input type="checkbox" checked>
423
- <span>Enable email notifications</span>
424
- </label>
425
- </div>
426
- <div class="form-group">
427
- <label class="form-checkbox">
428
- <input type="checkbox">
429
- <span>Subscribe to newsletter</span>
430
- </label>
431
- </div>
432
- <hr class="divider">
433
- <div class="form-group">
434
- <label class="form-checkbox">
435
- <input type="radio" name="demo-radio" value="option1" checked>
436
- <span>Option A</span>
437
- </label>
438
- </div>
439
- <div class="form-group">
440
- <label class="form-checkbox">
441
- <input type="radio" name="demo-radio" value="option2">
442
- <span>Option B</span>
443
- </label>
444
- </div>
445
- </div>
446
- <div class="demo-code">
447
- <div class="code-block-header">
448
- <span>HTML</span>
449
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
450
- </div>
451
- <pre><code>&lt;label class="form-checkbox"&gt;
452
- &lt;input type="checkbox" checked&gt;
453
- &lt;span&gt;Enable notifications&lt;/span&gt;
454
- &lt;/label&gt;
455
-
456
- &lt;label class="form-checkbox"&gt;
457
- &lt;input type="radio" name="group" value="a" checked&gt;
458
- &lt;span&gt;Option A&lt;/span&gt;
459
- &lt;/label&gt;</code></pre>
460
- </div>
461
- </div>
627
+ &lt;s-banner tone="success"&gt;
628
+ &lt;s-text&gt;Success message.&lt;/s-text&gt;
629
+ &lt;/s-banner&gt;
462
630
 
463
- <!-- Textarea -->
464
- <div class="demo-block">
465
- <div class="demo-block-title">Textarea</div>
466
- <div class="demo-preview">
467
- <div class="form-group">
468
- <label for="demo-notes">Order notes</label>
469
- <textarea class="form-textarea" id="demo-notes" rows="4" placeholder="Add any notes about this order..."></textarea>
470
- </div>
471
- </div>
472
- <div class="demo-code">
473
- <div class="code-block-header">
474
- <span>HTML</span>
475
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
631
+ &lt;s-banner tone="warning"&gt;
632
+ &lt;s-text&gt;Warning message.&lt;/s-text&gt;
633
+ &lt;/s-banner&gt;
634
+
635
+ &lt;s-banner tone="critical"&gt;
636
+ &lt;s-text&gt;Error message.&lt;/s-text&gt;
637
+ &lt;/s-banner&gt;</code></pre>
476
638
  </div>
477
- <pre><code>&lt;div class="form-group"&gt;
478
- &lt;label for="notes"&gt;Order notes&lt;/label&gt;
479
- &lt;textarea class="form-textarea" id="notes"
480
- rows="4" placeholder="Add notes..."&gt;&lt;/textarea&gt;
481
- &lt;/div&gt;</code></pre>
482
- </div>
483
- </div>
639
+ </s-box>
640
+ </s-section>
484
641
  </div>
485
642
 
486
643
 
487
644
  <!-- ═══════════════════════════════════════════════════════════ -->
488
- <!-- SECTION 5: TABLES -->
645
+ <!-- SECTION: FORMS -->
489
646
  <!-- ═══════════════════════════════════════════════════════════ -->
490
- <div class="demo-section" id="section-tables">
491
- <h2 class="demo-section-title">Tables</h2>
492
-
493
- <div class="demo-block">
494
- <div class="demo-block-title">Data Table</div>
495
- <p class="demo-description mt-3">Tables display structured data with alternating row hover and action buttons.</p>
496
- <div class="demo-preview">
497
- <div class="table-container">
498
- <table>
499
- <thead>
500
- <tr>
501
- <th>Product</th>
502
- <th>SKU</th>
503
- <th>Price</th>
504
- <th>Status</th>
505
- <th>Actions</th>
506
- </tr>
507
- </thead>
508
- <tbody>
509
- <tr>
510
- <td><strong>Classic Leather Jacket</strong></td>
511
- <td><code>CLJ-001</code></td>
512
- <td>$249.00</td>
513
- <td><span class="badge badge-success">Active</span></td>
514
- <td><div class="table-actions"><button class="btn btn-sm">Edit</button><button class="btn btn-sm btn-plain">Delete</button></div></td>
515
- </tr>
516
- <tr>
517
- <td><strong>Wool Scarf</strong></td>
518
- <td><code>WS-042</code></td>
519
- <td>$59.00</td>
520
- <td><span class="badge badge-success">Active</span></td>
521
- <td><div class="table-actions"><button class="btn btn-sm">Edit</button><button class="btn btn-sm btn-plain">Delete</button></div></td>
522
- </tr>
523
- <tr>
524
- <td><strong>Running Shoes</strong></td>
525
- <td><code>RS-118</code></td>
526
- <td>$129.00</td>
527
- <td><span class="badge badge-warning">Draft</span></td>
528
- <td><div class="table-actions"><button class="btn btn-sm">Edit</button><button class="btn btn-sm btn-plain">Delete</button></div></td>
529
- </tr>
530
- </tbody>
531
- </table>
532
- </div>
533
- </div>
534
- <div class="demo-code">
535
- <div class="code-block-header">
536
- <span>HTML</span>
537
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
538
- </div>
539
- <pre><code>&lt;div class="table-container"&gt;
540
- &lt;table&gt;
541
- &lt;thead&gt;
542
- &lt;tr&gt;
543
- &lt;th&gt;Product&lt;/th&gt;
544
- &lt;th&gt;SKU&lt;/th&gt;
545
- &lt;th&gt;Price&lt;/th&gt;
546
- &lt;th&gt;Status&lt;/th&gt;
547
- &lt;th&gt;Actions&lt;/th&gt;
548
- &lt;/tr&gt;
549
- &lt;/thead&gt;
550
- &lt;tbody&gt;
551
- &lt;tr&gt;
552
- &lt;td&gt;&lt;strong&gt;Product Name&lt;/strong&gt;&lt;/td&gt;
553
- &lt;td&gt;&lt;code&gt;SKU-001&lt;/code&gt;&lt;/td&gt;
554
- &lt;td&gt;$99.00&lt;/td&gt;
555
- &lt;td&gt;&lt;span class="badge badge-success"&gt;Active&lt;/span&gt;&lt;/td&gt;
556
- &lt;td&gt;
557
- &lt;div class="table-actions"&gt;
558
- &lt;button class="btn btn-sm"&gt;Edit&lt;/button&gt;
559
- &lt;/div&gt;
560
- &lt;/td&gt;
561
- &lt;/tr&gt;
562
- &lt;/tbody&gt;
563
- &lt;/table&gt;
564
- &lt;/div&gt;</code></pre>
565
- </div>
566
- </div>
647
+ <div id="section-forms">
648
+ <s-section heading="Form Fields">
649
+ <s-text color="subdued">Text fields with labels, placeholders, help text, error states, and multiline support.</s-text>
650
+
651
+ <s-box paddingBlockStart="base">
652
+ <s-box border="base" borderRadius="base" padding="base">
653
+ <s-stack gap="base">
654
+ <s-text-field
655
+ label="Store name"
656
+ placeholder="My Awesome Store"
657
+ helpText="The public-facing name of your store."
658
+ ></s-text-field>
659
+
660
+ <s-text-field
661
+ label="Email address"
662
+ type="email"
663
+ placeholder="merchant@example.com"
664
+ ></s-text-field>
665
+
666
+ <s-text-field
667
+ label="Password"
668
+ type="password"
669
+ placeholder="Enter password"
670
+ ></s-text-field>
671
+
672
+ <s-text-field
673
+ label="Product count"
674
+ type="number"
675
+ placeholder="0"
676
+ min="0"
677
+ max="10000"
678
+ ></s-text-field>
679
+
680
+ <s-text-field
681
+ label="Description"
682
+ multiline="4"
683
+ placeholder="Enter a detailed description..."
684
+ helpText="Supports multiline input."
685
+ ></s-text-field>
686
+
687
+ <s-text-field
688
+ label="Invalid field"
689
+ value="bad-value"
690
+ error="This value is not valid. Please correct it."
691
+ ></s-text-field>
692
+ </s-stack>
693
+ </s-box>
694
+ </s-box>
695
+
696
+ <s-box paddingBlockStart="base">
697
+ <!-- URL field -->
698
+ <s-box border="base" borderRadius="base" padding="base">
699
+ <s-text variant="headingSm">URL Field</s-text>
700
+ <s-box paddingBlockStart="small-200">
701
+ <s-url-field
702
+ label="Website URL"
703
+ placeholder="https://example.com"
704
+ helpText="Enter a valid URL."
705
+ ></s-url-field>
706
+ </s-box>
707
+ </s-box>
708
+ </s-box>
709
+
710
+ <s-box paddingBlockStart="base">
711
+ <!-- Color field -->
712
+ <s-box border="base" borderRadius="base" padding="base">
713
+ <s-text variant="headingSm">Color Field</s-text>
714
+ <s-box paddingBlockStart="small-200">
715
+ <s-color-field
716
+ label="Brand color"
717
+ value="#008060"
718
+ helpText="Pick your brand's primary color."
719
+ ></s-color-field>
720
+ </s-box>
721
+ </s-box>
722
+ </s-box>
723
+
724
+ <s-box paddingBlockStart="base">
725
+ <div class="demo-code">
726
+ <div class="code-block-header">
727
+ <span>HTML</span>
728
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
729
+ </div>
730
+ <pre><code>&lt;!-- Text field --&gt;
731
+ &lt;s-text-field
732
+ label="Store name"
733
+ placeholder="My Store"
734
+ helpText="Help text below."
735
+ &gt;&lt;/s-text-field&gt;
567
736
 
568
- <!-- Sortable headers -->
569
- <div class="demo-block">
570
- <div class="demo-block-title">Sortable Table Headers</div>
571
- <div class="demo-preview">
572
- <div class="table-container">
573
- <table>
574
- <thead>
575
- <tr>
576
- <th class="sortable">Name</th>
577
- <th class="sortable">Date</th>
578
- <th class="sortable">Amount</th>
579
- </tr>
580
- </thead>
581
- <tbody>
582
- <tr><td>Alice Johnson</td><td>Mar 15, 2026</td><td>$1,240.00</td></tr>
583
- <tr><td>Bob Smith</td><td>Mar 12, 2026</td><td>$890.50</td></tr>
584
- <tr><td>Carol White</td><td>Mar 10, 2026</td><td>$2,100.00</td></tr>
585
- </tbody>
586
- </table>
587
- </div>
588
- </div>
589
- <div class="demo-code">
590
- <div class="code-block-header">
591
- <span>HTML</span>
592
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
737
+ &lt;!-- Email / Password / Number --&gt;
738
+ &lt;s-text-field label="Email" type="email"&gt;&lt;/s-text-field&gt;
739
+ &lt;s-text-field label="Password" type="password"&gt;&lt;/s-text-field&gt;
740
+ &lt;s-text-field label="Count" type="number" min="0"&gt;&lt;/s-text-field&gt;
741
+
742
+ &lt;!-- Multiline (textarea) --&gt;
743
+ &lt;s-text-field label="Notes" multiline="4"&gt;&lt;/s-text-field&gt;
744
+
745
+ &lt;!-- Error state --&gt;
746
+ &lt;s-text-field label="Field"
747
+ error="Validation error message."
748
+ &gt;&lt;/s-text-field&gt;
749
+
750
+ &lt;!-- URL field (with validation) --&gt;
751
+ &lt;s-url-field label="Website" placeholder="https://..."&gt;&lt;/s-url-field&gt;
752
+
753
+ &lt;!-- Color picker --&gt;
754
+ &lt;s-color-field label="Color" value="#008060"&gt;&lt;/s-color-field&gt;
755
+
756
+ &lt;!-- Hidden label --&gt;
757
+ &lt;s-text-field label="Search" labelHidden
758
+ placeholder="Search..."&gt;&lt;/s-text-field&gt;
759
+
760
+ &lt;!-- Clear button --&gt;
761
+ &lt;s-text-field label="Search" clearButton&gt;&lt;/s-text-field&gt;</code></pre>
593
762
  </div>
594
- <pre><code>&lt;th class="sortable"&gt;Name&lt;/th&gt;
595
- &lt;th class="sortable"&gt;Date&lt;/th&gt;
596
- &lt;th class="sortable"&gt;Amount&lt;/th&gt;</code></pre>
597
- </div>
598
- </div>
763
+ </s-box>
764
+ </s-section>
599
765
  </div>
600
766
 
601
767
 
602
768
  <!-- ═══════════════════════════════════════════════════════════ -->
603
- <!-- SECTION 6: BANNERS -->
769
+ <!-- SECTION: SWITCH -->
604
770
  <!-- ═══════════════════════════════════════════════════════════ -->
605
- <div class="demo-section" id="section-banners">
606
- <h2 class="demo-section-title">Banners</h2>
607
-
608
- <div class="demo-block">
609
- <div class="demo-block-title">Banner Variants</div>
610
- <p class="demo-description mt-3">Use banners to communicate important information, status, or errors.</p>
611
- <div class="demo-preview" id="banners-preview">
612
- <div class="banner banner-info">
613
- <div class="banner-icon">&#8505;</div>
614
- <div class="banner-content">
615
- <p><strong>Information</strong></p>
616
- <p>This is an informational banner. Use it for tips or neutral messages.</p>
771
+ <div id="section-switch">
772
+ <s-section heading="Switch (Toggle)">
773
+ <s-text color="subdued">Toggle switches for boolean settings. Replaces checkboxes in Polaris.</s-text>
774
+
775
+ <s-box paddingBlockStart="base">
776
+ <s-box border="base" borderRadius="base" padding="base">
777
+ <s-stack gap="base">
778
+ <s-switch label="Enable feature" checked></s-switch>
779
+ <s-switch label="Disabled feature (off)"></s-switch>
780
+ <s-switch label="Disabled toggle" disabled></s-switch>
781
+ <s-switch label="With help text" helpText="This setting controls notification preferences." checked></s-switch>
782
+ </s-stack>
783
+ </s-box>
784
+ </s-box>
785
+
786
+ <s-box paddingBlockStart="base">
787
+ <div class="demo-code">
788
+ <div class="code-block-header">
789
+ <span>HTML</span>
790
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
617
791
  </div>
618
- <button class="banner-dismiss" onclick="this.closest('.banner').remove()">&times;</button>
792
+ <pre><code>&lt;s-switch label="Enable feature" checked&gt;&lt;/s-switch&gt;
793
+ &lt;s-switch label="Feature off"&gt;&lt;/s-switch&gt;
794
+ &lt;s-switch label="Cannot change" disabled&gt;&lt;/s-switch&gt;
795
+ &lt;s-switch label="With help"
796
+ helpText="Description text."
797
+ checked&gt;&lt;/s-switch&gt;</code></pre>
619
798
  </div>
799
+ </s-box>
800
+ </s-section>
801
+ </div>
620
802
 
621
- <div class="banner banner-success">
622
- <div class="banner-icon">&#10003;</div>
623
- <div class="banner-content">
624
- <p><strong>Success</strong></p>
625
- <p>The operation completed successfully. Your changes have been saved.</p>
626
- </div>
627
- <button class="banner-dismiss" onclick="this.closest('.banner').remove()">&times;</button>
628
- </div>
629
803
 
630
- <div class="banner banner-warning">
631
- <div class="banner-icon">&#9888;</div>
632
- <div class="banner-content">
633
- <p><strong>Warning</strong></p>
634
- <p>This action may have unintended consequences. Please review before proceeding.</p>
804
+ <!-- ═══════════════════════════════════════════════════════════ -->
805
+ <!-- SECTION: SELECT -->
806
+ <!-- ═══════════════════════════════════════════════════════════ -->
807
+ <div id="section-select">
808
+ <s-section heading="Select (Dropdown)">
809
+ <s-text color="subdued">Dropdown selection with <code>&lt;s-select&gt;</code> and <code>&lt;s-option&gt;</code> elements.</s-text>
810
+
811
+ <s-box paddingBlockStart="base">
812
+ <s-box border="base" borderRadius="base" padding="base">
813
+ <s-stack gap="base">
814
+ <s-select label="Country" helpText="Select your country.">
815
+ <s-option value="">Select a country</s-option>
816
+ <s-option value="us">United States</s-option>
817
+ <s-option value="ca">Canada</s-option>
818
+ <s-option value="gb">United Kingdom</s-option>
819
+ <s-option value="au">Australia</s-option>
820
+ <s-option value="in">India</s-option>
821
+ </s-select>
822
+
823
+ <s-select label="Sort by">
824
+ <s-option value="newest" selected>Newest first</s-option>
825
+ <s-option value="oldest">Oldest first</s-option>
826
+ <s-option value="price-asc">Price: Low to High</s-option>
827
+ <s-option value="price-desc">Price: High to Low</s-option>
828
+ </s-select>
829
+ </s-stack>
830
+ </s-box>
831
+ </s-box>
832
+
833
+ <s-box paddingBlockStart="base">
834
+ <div class="demo-code">
835
+ <div class="code-block-header">
836
+ <span>HTML</span>
837
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
635
838
  </div>
636
- <button class="banner-dismiss" onclick="this.closest('.banner').remove()">&times;</button>
839
+ <pre><code>&lt;s-select label="Country" helpText="Select country."&gt;
840
+ &lt;s-option value=""&gt;Select a country&lt;/s-option&gt;
841
+ &lt;s-option value="us"&gt;United States&lt;/s-option&gt;
842
+ &lt;s-option value="ca"&gt;Canada&lt;/s-option&gt;
843
+ &lt;s-option value="gb"&gt;United Kingdom&lt;/s-option&gt;
844
+ &lt;/s-select&gt;</code></pre>
637
845
  </div>
846
+ </s-box>
847
+ </s-section>
848
+ </div>
638
849
 
639
- <div class="banner banner-critical">
640
- <div class="banner-icon">&#10006;</div>
641
- <div class="banner-content">
642
- <p><strong>Error</strong></p>
643
- <p>Something went wrong. Please try again or contact support.</p>
644
- </div>
645
- <button class="banner-dismiss" onclick="this.closest('.banner').remove()">&times;</button>
646
- </div>
647
850
 
648
- <button class="btn btn-sm mt-3" onclick="resetBanners()">Reset banners</button>
649
- </div>
650
- <div class="demo-code">
651
- <div class="code-block-header">
652
- <span>HTML</span>
653
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
851
+ <!-- ═══════════════════════════════════════════════════════════ -->
852
+ <!-- SECTION: LINKS & CLICKABLE -->
853
+ <!-- ═══════════════════════════════════════════════════════════ -->
854
+ <div id="section-links">
855
+ <s-section heading="Links &amp; Clickable">
856
+ <s-text color="subdued">Navigation links and clickable wrappers for making containers interactive.</s-text>
857
+
858
+ <s-box paddingBlockStart="base">
859
+ <s-box border="base" borderRadius="base" padding="base">
860
+ <s-stack gap="base">
861
+ <s-text variant="headingSm">Links</s-text>
862
+ <s-stack direction="inline" gap="base">
863
+ <s-link href="/">Internal link</s-link>
864
+ <s-link href="https://polaris.shopify.com" target="_blank">External link</s-link>
865
+ </s-stack>
866
+ </s-stack>
867
+ </s-box>
868
+ </s-box>
869
+
870
+ <s-box paddingBlockStart="base">
871
+ <s-box border="base" borderRadius="base" padding="base">
872
+ <s-text variant="headingSm">Clickable Card</s-text>
873
+ <s-text color="subdued">Wrap any content in <code>&lt;s-clickable&gt;</code> to make the entire area interactive.</s-text>
874
+ <s-box paddingBlockStart="small-200">
875
+ <s-grid gridTemplateColumns="1fr 1fr" gap="base">
876
+ <s-box border="base" borderRadius="base" padding="base">
877
+ <s-clickable href="/products">
878
+ <s-stack gap="small-200">
879
+ <s-text variant="headingSm">Products</s-text>
880
+ <s-text color="subdued">Click anywhere in this card</s-text>
881
+ </s-stack>
882
+ </s-clickable>
883
+ </s-box>
884
+ <s-box border="base" borderRadius="base" padding="base">
885
+ <s-clickable href="/settings">
886
+ <s-stack gap="small-200">
887
+ <s-text variant="headingSm">Settings</s-text>
888
+ <s-text color="subdued">Entire box is clickable</s-text>
889
+ </s-stack>
890
+ </s-clickable>
891
+ </s-box>
892
+ </s-grid>
893
+ </s-box>
894
+ </s-box>
895
+ </s-box>
896
+
897
+ <s-box paddingBlockStart="base">
898
+ <div class="demo-code">
899
+ <div class="code-block-header">
900
+ <span>HTML</span>
901
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
902
+ </div>
903
+ <pre><code>&lt;!-- Standard link --&gt;
904
+ &lt;s-link href="/"&gt;Internal link&lt;/s-link&gt;
905
+ &lt;s-link href="https://..." target="_blank"&gt;External&lt;/s-link&gt;
906
+
907
+ &lt;!-- Clickable wrapper (makes entire area tappable) --&gt;
908
+ &lt;s-box border="base" borderRadius="base" padding="base"&gt;
909
+ &lt;s-clickable href="/page"&gt;
910
+ &lt;s-text variant="headingSm"&gt;Card Title&lt;/s-text&gt;
911
+ &lt;s-text color="subdued"&gt;Click anywhere&lt;/s-text&gt;
912
+ &lt;/s-clickable&gt;
913
+ &lt;/s-box&gt;</code></pre>
654
914
  </div>
655
- <pre><code>&lt;div class="banner banner-info"&gt;
656
- &lt;div class="banner-icon"&gt;&amp;#8505;&lt;/div&gt;
657
- &lt;div class="banner-content"&gt;
658
- &lt;p&gt;&lt;strong&gt;Information&lt;/strong&gt;&lt;/p&gt;
659
- &lt;p&gt;Your message here.&lt;/p&gt;
660
- &lt;/div&gt;
661
- &lt;button class="banner-dismiss"
662
- onclick="this.closest('.banner').remove()"&gt;&amp;times;&lt;/button&gt;
663
- &lt;/div&gt;
664
-
665
- &lt;!-- Variants: banner-info, banner-success,
666
- banner-warning, banner-critical --&gt;</code></pre>
667
- </div>
668
- </div>
915
+ </s-box>
916
+ </s-section>
669
917
  </div>
670
918
 
671
919
 
672
920
  <!-- ═══════════════════════════════════════════════════════════ -->
673
- <!-- SECTION 7: EMPTY STATE -->
921
+ <!-- SECTION: SPINNER -->
674
922
  <!-- ═══════════════════════════════════════════════════════════ -->
675
- <div class="demo-section" id="section-empty-state">
676
- <h2 class="demo-section-title">Empty State</h2>
677
-
678
- <div class="demo-block">
679
- <div class="demo-block-title">Empty State with CTA</div>
680
- <p class="demo-description mt-3">Show an empty state when there is no data to display. Include a clear call to action.</p>
681
- <div class="demo-preview">
682
- <div class="empty-state">
683
- <div class="empty-state-icon">&#128230;</div>
684
- <h3>No orders yet</h3>
685
- <p>When customers place orders, they will appear here. Start by adding products to your store.</p>
686
- <button class="btn btn-primary">Add product</button>
687
- </div>
688
- </div>
689
- <div class="demo-code">
690
- <div class="code-block-header">
691
- <span>HTML</span>
692
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
923
+ <div id="section-spinner">
924
+ <s-section heading="Spinner">
925
+ <s-text color="subdued">Loading indicator for async operations.</s-text>
926
+
927
+ <s-box paddingBlockStart="base">
928
+ <s-box border="base" borderRadius="base" padding="base">
929
+ <s-stack direction="inline" gap="large-400" alignItems="center">
930
+ <s-stack alignItems="center" gap="small-200">
931
+ <s-spinner></s-spinner>
932
+ <s-text color="subdued" variant="bodySm">Default</s-text>
933
+ </s-stack>
934
+ <s-stack alignItems="center" gap="small-200">
935
+ <s-spinner size="large"></s-spinner>
936
+ <s-text color="subdued" variant="bodySm">Large</s-text>
937
+ </s-stack>
938
+ </s-stack>
939
+ </s-box>
940
+ </s-box>
941
+
942
+ <s-box paddingBlockStart="base">
943
+ <!-- Full loading pattern -->
944
+ <s-box border="base" borderRadius="base" padding="large-400">
945
+ <s-stack alignItems="center" gap="base">
946
+ <s-spinner></s-spinner>
947
+ <s-text color="subdued">Loading content...</s-text>
948
+ </s-stack>
949
+ </s-box>
950
+ </s-box>
951
+
952
+ <s-box paddingBlockStart="base">
953
+ <div class="demo-code">
954
+ <div class="code-block-header">
955
+ <span>HTML</span>
956
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
957
+ </div>
958
+ <pre><code>&lt;!-- Default spinner --&gt;
959
+ &lt;s-spinner&gt;&lt;/s-spinner&gt;
960
+
961
+ &lt;!-- Large spinner --&gt;
962
+ &lt;s-spinner size="large"&gt;&lt;/s-spinner&gt;
963
+
964
+ &lt;!-- Full loading state pattern --&gt;
965
+ &lt;s-box padding="large-400"&gt;
966
+ &lt;s-stack alignItems="center" gap="base"&gt;
967
+ &lt;s-spinner&gt;&lt;/s-spinner&gt;
968
+ &lt;s-text color="subdued"&gt;Loading...&lt;/s-text&gt;
969
+ &lt;/s-stack&gt;
970
+ &lt;/s-box&gt;</code></pre>
693
971
  </div>
694
- <pre><code>&lt;div class="empty-state"&gt;
695
- &lt;div class="empty-state-icon"&gt;&amp;#128230;&lt;/div&gt;
696
- &lt;h3&gt;No orders yet&lt;/h3&gt;
697
- &lt;p&gt;Your description text here.&lt;/p&gt;
698
- &lt;button class="btn btn-primary"&gt;Add product&lt;/button&gt;
699
- &lt;/div&gt;</code></pre>
700
- </div>
701
- </div>
972
+ </s-box>
973
+ </s-section>
702
974
  </div>
703
975
 
704
976
 
705
977
  <!-- ═══════════════════════════════════════════════════════════ -->
706
- <!-- SECTION 8: LOADING -->
978
+ <!-- SECTION: SECTION -->
707
979
  <!-- ═══════════════════════════════════════════════════════════ -->
708
- <div class="demo-section" id="section-loading">
709
- <h2 class="demo-section-title">Loading</h2>
710
-
711
- <!-- Spinner -->
712
- <div class="demo-block">
713
- <div class="demo-block-title">Spinners</div>
714
- <p class="demo-description mt-3">Animated spinners indicate an ongoing process.</p>
715
- <div class="demo-preview">
716
- <div class="flex items-center gap-5">
717
- <div>
718
- <div class="spinner"></div>
719
- <p class="text-sm text-secondary mt-2">Default</p>
720
- </div>
721
- <div>
722
- <div class="spinner spinner-lg"></div>
723
- <p class="text-sm text-secondary mt-2">Large</p>
724
- </div>
725
- <div class="loading-state" style="padding: 20px;">
726
- <div class="spinner"></div>
727
- <p>Loading content...</p>
980
+ <div id="section-section">
981
+ <s-section heading="Section">
982
+ <s-text color="subdued">Content sections within a page, with optional headings and padding.</s-text>
983
+
984
+ <s-box paddingBlockStart="base">
985
+ <div class="demo-code">
986
+ <div class="code-block-header">
987
+ <span>HTML</span>
988
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
728
989
  </div>
990
+ <pre><code>&lt;s-page heading="My Page"&gt;
991
+ &lt;!-- Section with heading --&gt;
992
+ &lt;s-section heading="General Settings"&gt;
993
+ &lt;s-text&gt;Content here...&lt;/s-text&gt;
994
+ &lt;/s-section&gt;
995
+
996
+ &lt;!-- Section without heading --&gt;
997
+ &lt;s-section&gt;
998
+ &lt;s-text&gt;More content...&lt;/s-text&gt;
999
+ &lt;/s-section&gt;
1000
+
1001
+ &lt;!-- Section with padding --&gt;
1002
+ &lt;s-section padding="base"&gt;
1003
+ &lt;s-text&gt;Padded content.&lt;/s-text&gt;
1004
+ &lt;/s-section&gt;
1005
+ &lt;/s-page&gt;</code></pre>
729
1006
  </div>
730
- </div>
731
- <div class="demo-code">
732
- <div class="code-block-header">
733
- <span>HTML</span>
734
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
735
- </div>
736
- <pre><code>&lt;div class="spinner"&gt;&lt;/div&gt;
737
- &lt;div class="spinner spinner-lg"&gt;&lt;/div&gt;
738
-
739
- &lt;!-- Full loading state --&gt;
740
- &lt;div class="loading-state"&gt;
741
- &lt;div class="spinner"&gt;&lt;/div&gt;
742
- &lt;p&gt;Loading content...&lt;/p&gt;
743
- &lt;/div&gt;</code></pre>
744
- </div>
745
- </div>
746
-
747
- <!-- Skeleton -->
748
- <div class="demo-block">
749
- <div class="demo-block-title">Skeleton Loaders</div>
750
- <p class="demo-description mt-3">Skeleton loaders provide a placeholder preview of content while it loads.</p>
751
- <div class="demo-preview">
752
- <div class="card" style="margin-bottom:0;">
753
- <div class="skeleton skeleton-heading"></div>
754
- <div class="skeleton skeleton-text"></div>
755
- <div class="skeleton skeleton-text"></div>
756
- <div class="skeleton skeleton-text" style="width: 40%;"></div>
757
- </div>
758
- </div>
759
- <div class="demo-code">
760
- <div class="code-block-header">
761
- <span>HTML</span>
762
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
763
- </div>
764
- <pre><code>&lt;div class="skeleton skeleton-heading"&gt;&lt;/div&gt;
765
- &lt;div class="skeleton skeleton-text"&gt;&lt;/div&gt;
766
- &lt;div class="skeleton skeleton-text"&gt;&lt;/div&gt;
767
- &lt;div class="skeleton skeleton-text"
768
- style="width: 40%;"&gt;&lt;/div&gt;
769
-
770
- &lt;!-- Image skeleton --&gt;
771
- &lt;div class="skeleton skeleton-image"&gt;&lt;/div&gt;</code></pre>
772
- </div>
773
- </div>
1007
+ </s-box>
1008
+ </s-section>
774
1009
  </div>
775
1010
 
776
1011
 
777
1012
  <!-- ═══════════════════════════════════════════════════════════ -->
778
- <!-- SECTION 9: MODALS -->
1013
+ <!-- SECTION: MODALS -->
779
1014
  <!-- ═══════════════════════════════════════════════════════════ -->
780
- <div class="demo-section" id="section-modals">
781
- <h2 class="demo-section-title">Modals</h2>
782
-
783
- <div class="demo-block">
784
- <div class="demo-block-title">Basic Modal</div>
785
- <p class="demo-description mt-3">App Bridge modals are rendered by Shopify outside your iframe for a native feel. Use <code>&lt;ui-modal&gt;</code>.</p>
786
- <div class="demo-preview">
787
- <button class="btn btn-primary" onclick="document.getElementById('demo-modal-basic').show()">Open Modal</button>
788
- </div>
789
- <div class="demo-code">
790
- <div class="code-block-header">
791
- <span>HTML</span>
792
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
793
- </div>
794
- <pre><code>&lt;ui-modal id="my-modal"&gt;
1015
+ <div id="section-modals">
1016
+ <s-section heading="Modals">
1017
+ <s-text color="subdued">App Bridge modals rendered by Shopify outside your iframe for a native feel. Uses <code>&lt;ui-modal&gt;</code>.</s-text>
1018
+
1019
+ <s-box paddingBlockStart="base">
1020
+ <s-box border="base" borderRadius="base" padding="base">
1021
+ <s-text variant="headingSm">Basic Modal</s-text>
1022
+ <s-box paddingBlockStart="small-200">
1023
+ <s-button variant="primary" onclick="document.getElementById('demo-modal-basic').show()">Open Modal</s-button>
1024
+ </s-box>
1025
+ </s-box>
1026
+ </s-box>
1027
+
1028
+ <s-box paddingBlockStart="base">
1029
+ <s-box border="base" borderRadius="base" padding="base">
1030
+ <s-text variant="headingSm">Confirmation Dialog</s-text>
1031
+ <s-text color="subdued">Use before destructive actions like deleting records.</s-text>
1032
+ <s-box paddingBlockStart="small-200">
1033
+ <s-button tone="critical" onclick="document.getElementById('demo-modal-confirm').show()">Delete Item</s-button>
1034
+ </s-box>
1035
+ </s-box>
1036
+ </s-box>
1037
+
1038
+ <s-box paddingBlockStart="base">
1039
+ <div class="demo-code">
1040
+ <div class="code-block-header">
1041
+ <span>HTML</span>
1042
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
1043
+ </div>
1044
+ <pre><code>&lt;!-- Basic modal --&gt;
1045
+ &lt;ui-modal id="my-modal"&gt;
795
1046
  &lt;div style="padding: 16px;"&gt;
796
- &lt;p&gt;Modal content goes here.&lt;/p&gt;
1047
+ &lt;s-text&gt;Modal content here.&lt;/s-text&gt;
797
1048
  &lt;/div&gt;
798
1049
  &lt;ui-title-bar title="Modal Title"&gt;
799
1050
  &lt;button variant="primary"
@@ -804,28 +1055,14 @@
804
1055
  &lt;/ui-modal&gt;
805
1056
 
806
1057
  &lt;!-- Trigger --&gt;
807
- &lt;button onclick="document.getElementById('my-modal').show()"&gt;
1058
+ &lt;s-button onclick="document.getElementById('my-modal').show()"&gt;
808
1059
  Open Modal
809
- &lt;/button&gt;</code></pre>
810
- </div>
811
- </div>
1060
+ &lt;/s-button&gt;
812
1061
 
813
- <!-- Confirmation dialog -->
814
- <div class="demo-block">
815
- <div class="demo-block-title">Confirmation Dialog</div>
816
- <p class="demo-description mt-3">Use a confirmation modal before destructive actions like deleting records.</p>
817
- <div class="demo-preview">
818
- <button class="btn btn-destructive" onclick="document.getElementById('demo-modal-confirm').show()">Delete Item</button>
819
- </div>
820
- <div class="demo-code">
821
- <div class="code-block-header">
822
- <span>HTML</span>
823
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
824
- </div>
825
- <pre><code>&lt;ui-modal id="confirm-delete"&gt;
1062
+ &lt;!-- Confirmation dialog --&gt;
1063
+ &lt;ui-modal id="confirm-delete"&gt;
826
1064
  &lt;div style="padding: 16px;"&gt;
827
- &lt;p&gt;Are you sure you want to delete this item?
828
- This action cannot be undone.&lt;/p&gt;
1065
+ &lt;s-text&gt;Are you sure? This cannot be undone.&lt;/s-text&gt;
829
1066
  &lt;/div&gt;
830
1067
  &lt;ui-title-bar title="Confirm Deletion"&gt;
831
1068
  &lt;button onclick="document.getElementById('confirm-delete').hide()"&gt;
@@ -836,17 +1073,23 @@
836
1073
  Delete
837
1074
  &lt;/button&gt;
838
1075
  &lt;/ui-title-bar&gt;
839
- &lt;/ui-modal&gt;</code></pre>
840
- </div>
841
- </div>
1076
+ &lt;/ui-modal&gt;
1077
+
1078
+ &lt;!-- Large variant --&gt;
1079
+ &lt;ui-modal id="my-modal" variant="large"&gt;...&lt;/ui-modal&gt;</code></pre>
1080
+ </div>
1081
+ </s-box>
1082
+ </s-section>
842
1083
  </div>
843
1084
 
844
- <!-- Demo modals (rendered outside the demo blocks) -->
1085
+ <!-- Demo modals -->
845
1086
  <ui-modal id="demo-modal-basic">
846
1087
  <div style="padding: 16px;">
847
- <h3 style="margin-bottom: 12px;">Hello from a modal!</h3>
848
- <p>This is an App Bridge modal rendered by Shopify. It appears outside your app's iframe for a seamless, native experience.</p>
849
- <p style="margin-top: 12px; color: var(--p-color-text-secondary);">Modals are great for forms, confirmations, and displaying details without navigating away.</p>
1088
+ <s-stack gap="base">
1089
+ <s-text variant="headingMd">Hello from a modal!</s-text>
1090
+ <s-text>This is an App Bridge modal rendered by Shopify. It appears outside your app's iframe for a seamless, native experience.</s-text>
1091
+ <s-text color="subdued">Modals are great for forms, confirmations, and displaying details without navigating away.</s-text>
1092
+ </s-stack>
850
1093
  </div>
851
1094
  <ui-title-bar title="Basic Modal">
852
1095
  <button variant="primary" onclick="document.getElementById('demo-modal-basic').hide()">Done</button>
@@ -855,7 +1098,7 @@
855
1098
 
856
1099
  <ui-modal id="demo-modal-confirm">
857
1100
  <div style="padding: 16px;">
858
- <p>Are you sure you want to delete this item? This action cannot be undone.</p>
1101
+ <s-text>Are you sure you want to delete this item? This action cannot be undone.</s-text>
859
1102
  </div>
860
1103
  <ui-title-bar title="Confirm Deletion">
861
1104
  <button onclick="document.getElementById('demo-modal-confirm').hide()">Cancel</button>
@@ -865,259 +1108,268 @@
865
1108
 
866
1109
 
867
1110
  <!-- ═══════════════════════════════════════════════════════════ -->
868
- <!-- SECTION 10: TOASTS -->
1111
+ <!-- SECTION: SAVE BAR -->
869
1112
  <!-- ═══════════════════════════════════════════════════════════ -->
870
- <div class="demo-section" id="section-toasts">
871
- <h2 class="demo-section-title">Toasts</h2>
872
-
873
- <div class="demo-block">
874
- <div class="demo-block-title">Toast Notifications</div>
875
- <p class="demo-description mt-3">Toasts provide brief, non-blocking feedback. In embedded admin, they use App Bridge. Outside, a CSS fallback renders.</p>
876
- <div class="demo-preview">
877
- <div class="btn-group">
878
- <button class="btn btn-primary" onclick="showToast('Product saved successfully')">Success Toast</button>
879
- <button class="btn btn-destructive" onclick="showToast('Failed to save product', true)">Error Toast</button>
880
- </div>
881
- </div>
882
- <div class="demo-code">
883
- <div class="code-block-header">
884
- <span>JavaScript</span>
885
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
1113
+ <div id="section-savebar">
1114
+ <s-section heading="Save Bar (data-save-bar)">
1115
+ <s-text color="subdued">Shopify's native save/discard bar appears automatically when a <code>&lt;form data-save-bar&gt;</code> detects changes.</s-text>
1116
+
1117
+ <s-box paddingBlockStart="base">
1118
+ <s-banner tone="info">
1119
+ <s-text>The save bar is demonstrated on the <s-link href="/settings">Settings page</s-link>. Change any field and the save/discard bar appears automatically.</s-text>
1120
+ </s-banner>
1121
+ </s-box>
1122
+
1123
+ <s-box paddingBlockStart="base">
1124
+ <div class="demo-code">
1125
+ <div class="code-block-header">
1126
+ <span>HTML</span>
1127
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
1128
+ </div>
1129
+ <pre><code>&lt;!-- Wrap your page in a form with data-save-bar --&gt;
1130
+ &lt;form data-save-bar id="settings-form"&gt;
1131
+ &lt;s-page heading="Settings"&gt;
1132
+ &lt;s-section heading="General"&gt;
1133
+ &lt;s-text-field id="name" label="Name"&gt;&lt;/s-text-field&gt;
1134
+ &lt;s-switch id="enabled" label="Enabled"&gt;&lt;/s-switch&gt;
1135
+ &lt;/s-section&gt;
1136
+ &lt;/s-page&gt;
1137
+ &lt;/form&gt;
1138
+
1139
+ &lt;script&gt;
1140
+ // Handle form submit (save)
1141
+ document.getElementById("settings-form")
1142
+ .addEventListener("submit", async (e) =&gt; {
1143
+ e.preventDefault();
1144
+ // Save logic here...
1145
+ shopify.toast.show("Saved!");
1146
+ });
1147
+
1148
+ // Handle form reset (discard)
1149
+ document.getElementById("settings-form")
1150
+ .addEventListener("reset", () =&gt; {
1151
+ // Reload original values
1152
+ });
1153
+ &lt;/script&gt;</code></pre>
886
1154
  </div>
887
- <pre><code>// Success toast
1155
+ </s-box>
1156
+ </s-section>
1157
+ </div>
1158
+
1159
+
1160
+ <!-- ═══════════════════════════════════════════════════════════ -->
1161
+ <!-- SECTION: TOASTS -->
1162
+ <!-- ═══════════════════════════════════════════════════════════ -->
1163
+ <div id="section-toasts">
1164
+ <s-section heading="Toasts">
1165
+ <s-text color="subdued">Brief, non-blocking feedback notifications using App Bridge.</s-text>
1166
+
1167
+ <s-box paddingBlockStart="base">
1168
+ <s-box border="base" borderRadius="base" padding="base">
1169
+ <s-stack direction="inline" gap="small-200">
1170
+ <s-button variant="primary" onclick="showToast('Product saved successfully')">Success Toast</s-button>
1171
+ <s-button tone="critical" onclick="showToast('Failed to save product', true)">Error Toast</s-button>
1172
+ </s-stack>
1173
+ </s-box>
1174
+ </s-box>
1175
+
1176
+ <s-box paddingBlockStart="base">
1177
+ <div class="demo-code">
1178
+ <div class="code-block-header">
1179
+ <span>JavaScript</span>
1180
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
1181
+ </div>
1182
+ <pre><code>// Success toast (uses App Bridge in embedded admin)
888
1183
  showToast("Product saved successfully");
889
1184
 
890
1185
  // Error toast
891
1186
  showToast("Failed to save product", true);
892
1187
 
893
- // App Bridge native API (also works)
894
- shopify.toast.show("Message", { duration: 5000 });</code></pre>
895
- </div>
896
- </div>
1188
+ // Direct App Bridge API
1189
+ shopify.toast.show("Message", { duration: 5000 });
1190
+ shopify.toast.show("Error!", { isError: true });</code></pre>
1191
+ </div>
1192
+ </s-box>
1193
+ </s-section>
897
1194
  </div>
898
1195
 
899
1196
 
900
1197
  <!-- ═══════════════════════════════════════════════════════════ -->
901
- <!-- SECTION 11: LAYOUT -->
1198
+ <!-- SECTION: NAVIGATION -->
902
1199
  <!-- ═══════════════════════════════════════════════════════════ -->
903
- <div class="demo-section" id="section-layout">
904
- <h2 class="demo-section-title">Layout</h2>
905
-
906
- <!-- Page layout -->
907
- <div class="demo-block">
908
- <div class="demo-block-title">Page Widths</div>
909
- <p class="demo-description mt-3">Three page width options to match your content needs.</p>
910
- <div class="demo-preview">
911
- <div style="font-size: 13px; display: flex; flex-direction: column; gap: 8px;">
912
- <div style="background: var(--p-color-bg-info); padding: 8px 12px; border-radius: 6px; max-width: 720px; margin: 0 auto; width: 100%; text-align: center;">
913
- <code>.page-narrow</code> - 720px max
1200
+ <div id="section-navigation">
1201
+ <s-section heading="Navigation">
1202
+ <s-text color="subdued">App navigation in the Shopify admin sidebar. Uses <code>&lt;ui-nav-menu&gt;</code> (App Bridge) or <code>&lt;s-app-nav&gt;</code> (Polaris).</s-text>
1203
+
1204
+ <s-box paddingBlockStart="base">
1205
+ <div class="demo-code">
1206
+ <div class="code-block-header">
1207
+ <span>HTML</span>
1208
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
914
1209
  </div>
915
- <div style="background: var(--p-color-bg-success); padding: 8px 12px; border-radius: 6px; max-width: 960px; margin: 0 auto; width: 100%; text-align: center;">
916
- <code>.page</code> - 960px max (default)
917
- </div>
918
- <div style="background: var(--p-color-bg-warning); padding: 8px 12px; border-radius: 6px; max-width: 100%; text-align: center;">
919
- <code>.page-wide</code> - 1200px max
920
- </div>
921
- </div>
922
- </div>
923
- <div class="demo-code">
924
- <div class="code-block-header">
925
- <span>HTML</span>
926
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
927
- </div>
928
- <pre><code>&lt;div class="page"&gt;Default width (960px)&lt;/div&gt;
929
- &lt;div class="page-narrow"&gt;Narrow (720px)&lt;/div&gt;
930
- &lt;div class="page-wide"&gt;Wide (1200px)&lt;/div&gt;</code></pre>
931
- </div>
932
- </div>
933
-
934
- <!-- Stats grid -->
935
- <div class="demo-block">
936
- <div class="demo-block-title">Stats Grid</div>
937
- <div class="demo-preview">
938
- <div class="stats-grid" style="margin-bottom: 0;">
939
- <div class="stat-card" style="margin-bottom:0;">
940
- <div class="stat-label">Total Sales</div>
941
- <div class="stat-value">$12,450</div>
942
- <div class="stat-change stat-change-positive">+12.5%</div>
943
- </div>
944
- <div class="stat-card" style="margin-bottom:0;">
945
- <div class="stat-label">Orders</div>
946
- <div class="stat-value">156</div>
947
- <div class="stat-change stat-change-positive">+8.2%</div>
948
- </div>
949
- <div class="stat-card" style="margin-bottom:0;">
950
- <div class="stat-label">Visitors</div>
951
- <div class="stat-value">3,842</div>
952
- <div class="stat-change stat-change-negative">-2.1%</div>
953
- </div>
954
- <div class="stat-card" style="margin-bottom:0;">
955
- <div class="stat-label">Conversion</div>
956
- <div class="stat-value">4.1%</div>
957
- <div class="stat-change stat-change-positive">+0.3%</div>
958
- </div>
959
- </div>
960
- </div>
961
- <div class="demo-code">
962
- <div class="code-block-header">
963
- <span>HTML</span>
964
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
1210
+ <pre><code>&lt;!-- Option 1: App Bridge nav (used in this template) --&gt;
1211
+ &lt;ui-nav-menu&gt;
1212
+ &lt;a href="/" rel="home"&gt;Dashboard&lt;/a&gt;
1213
+ &lt;a href="/products"&gt;Products&lt;/a&gt;
1214
+ &lt;a href="/settings"&gt;Settings&lt;/a&gt;
1215
+ &lt;/ui-nav-menu&gt;
1216
+
1217
+ &lt;!-- Option 2: Polaris nav --&gt;
1218
+ &lt;s-app-nav&gt;
1219
+ &lt;s-link href="/" rel="home"&gt;Dashboard&lt;/s-link&gt;
1220
+ &lt;s-link href="/products"&gt;Products&lt;/s-link&gt;
1221
+ &lt;s-link href="/settings"&gt;Settings&lt;/s-link&gt;
1222
+ &lt;/s-app-nav&gt;</code></pre>
965
1223
  </div>
966
- <pre><code>&lt;div class="stats-grid"&gt;
967
- &lt;div class="stat-card"&gt;
968
- &lt;div class="stat-label"&gt;Total Sales&lt;/div&gt;
969
- &lt;div class="stat-value"&gt;$12,450&lt;/div&gt;
970
- &lt;div class="stat-change stat-change-positive"&gt;
971
- +12.5%
972
- &lt;/div&gt;
973
- &lt;/div&gt;
974
- &lt;!-- More stat cards... --&gt;
975
- &lt;/div&gt;</code></pre>
976
- </div>
977
- </div>
978
-
979
- <!-- Flex utilities -->
980
- <div class="demo-block">
981
- <div class="demo-block-title">Flex Utilities</div>
982
- <div class="demo-preview">
983
- <div class="flex items-center justify-between p-3" style="background: var(--p-color-bg-surface-hover); border-radius: 8px; margin-bottom: 8px;">
984
- <span>justify-between</span>
985
- <button class="btn btn-sm">Action</button>
986
- </div>
987
- <div class="flex items-center justify-center gap-3 p-3" style="background: var(--p-color-bg-surface-hover); border-radius: 8px; margin-bottom: 8px;">
988
- <span>justify-center + gap-3</span>
989
- <span class="badge badge-info">Centered</span>
990
- </div>
991
- <div class="flex flex-wrap gap-2 p-3" style="background: var(--p-color-bg-surface-hover); border-radius: 8px;">
992
- <span class="badge badge-default">flex-wrap</span>
993
- <span class="badge badge-default">gap-2</span>
994
- <span class="badge badge-default">wraps</span>
995
- <span class="badge badge-default">on</span>
996
- <span class="badge badge-default">smaller</span>
997
- <span class="badge badge-default">screens</span>
998
- </div>
999
- </div>
1000
- <div class="demo-code">
1001
- <div class="code-block-header">
1002
- <span>HTML</span>
1003
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
1004
- </div>
1005
- <pre><code>&lt;div class="flex items-center justify-between"&gt;
1006
- &lt;span&gt;Label&lt;/span&gt;
1007
- &lt;button class="btn btn-sm"&gt;Action&lt;/button&gt;
1008
- &lt;/div&gt;
1009
-
1010
- &lt;!-- Available: flex, flex-col, flex-wrap,
1011
- items-center, items-start,
1012
- justify-between, justify-center, justify-end,
1013
- gap-1 through gap-5 --&gt;</code></pre>
1014
- </div>
1015
- </div>
1016
-
1017
- <!-- Quick Links -->
1018
- <div class="demo-block">
1019
- <div class="demo-block-title">Quick Links</div>
1020
- <div class="demo-preview">
1021
- <div class="quick-links">
1022
- <a class="quick-link" href="#">
1023
- <div class="quick-link-icon">&#128722;</div>
1024
- <div class="quick-link-text">
1025
- <h4>Products</h4>
1026
- <p>Manage inventory</p>
1027
- </div>
1028
- </a>
1029
- <a class="quick-link" href="#">
1030
- <div class="quick-link-icon">&#128176;</div>
1031
- <div class="quick-link-text">
1032
- <h4>Orders</h4>
1033
- <p>View recent orders</p>
1034
- </div>
1035
- </a>
1036
- <a class="quick-link" href="#">
1037
- <div class="quick-link-icon">&#9881;</div>
1038
- <div class="quick-link-text">
1039
- <h4>Settings</h4>
1040
- <p>Configure your app</p>
1041
- </div>
1042
- </a>
1043
- </div>
1044
- </div>
1045
- <div class="demo-code">
1046
- <div class="code-block-header">
1047
- <span>HTML</span>
1048
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
1049
- </div>
1050
- <pre><code>&lt;div class="quick-links"&gt;
1051
- &lt;a class="quick-link" href="/products"&gt;
1052
- &lt;div class="quick-link-icon"&gt;&amp;#128722;&lt;/div&gt;
1053
- &lt;div class="quick-link-text"&gt;
1054
- &lt;h4&gt;Products&lt;/h4&gt;
1055
- &lt;p&gt;Manage inventory&lt;/p&gt;
1056
- &lt;/div&gt;
1057
- &lt;/a&gt;
1058
- &lt;/div&gt;</code></pre>
1059
- </div>
1060
- </div>
1224
+ </s-box>
1225
+ </s-section>
1061
1226
  </div>
1062
1227
 
1063
1228
 
1064
1229
  <!-- ═══════════════════════════════════════════════════════════ -->
1065
- <!-- SECTION 12: RESOURCE PICKER -->
1230
+ <!-- SECTION: RESOURCE PICKER -->
1066
1231
  <!-- ═══════════════════════════════════════════════════════════ -->
1067
- <div class="demo-section" id="section-resource-picker">
1068
- <h2 class="demo-section-title">Resource Picker</h2>
1069
-
1070
- <div class="demo-block">
1071
- <div class="demo-block-title">Product Resource Picker</div>
1072
- <p class="demo-description mt-3">App Bridge provides a native product picker. Only available when running inside the Shopify admin.</p>
1073
- <div class="demo-preview">
1074
- <button class="btn btn-primary" onclick="demoResourcePicker()">Open Product Picker</button>
1075
- <div id="picker-demo-result" class="mt-4"></div>
1076
- </div>
1077
- <div class="demo-code">
1078
- <div class="code-block-header">
1079
- <span>JavaScript</span>
1080
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
1081
- </div>
1082
- <pre><code>// Open the product resource picker
1232
+ <div id="section-resource-picker">
1233
+ <s-section heading="Resource Picker">
1234
+ <s-text color="subdued">App Bridge provides a native product/collection picker. Only available inside the Shopify admin.</s-text>
1235
+
1236
+ <s-box paddingBlockStart="base">
1237
+ <s-box border="base" borderRadius="base" padding="base">
1238
+ <s-stack gap="base">
1239
+ <s-button variant="primary" onclick="demoResourcePicker()">Open Product Picker</s-button>
1240
+ <div id="picker-demo-result"></div>
1241
+ </s-stack>
1242
+ </s-box>
1243
+ </s-box>
1244
+
1245
+ <s-box paddingBlockStart="base">
1246
+ <div class="demo-code">
1247
+ <div class="code-block-header">
1248
+ <span>JavaScript</span>
1249
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
1250
+ </div>
1251
+ <pre><code>// Open the product resource picker
1083
1252
  const selected = await shopify.resourcePicker({
1084
1253
  type: "product",
1085
- // Optional: allow multiple selection
1086
1254
  // multiple: true,
1087
- // Optional: filter
1088
1255
  // filter: { query: "shirt" },
1089
1256
  });
1090
1257
 
1091
1258
  if (selected &amp;&amp; selected.length &gt; 0) {
1092
- console.log("Selected:", selected);
1093
1259
  selected.forEach(product =&gt; {
1094
1260
  console.log(product.title, product.id);
1095
1261
  });
1096
1262
  }</code></pre>
1097
- </div>
1098
- </div>
1099
-
1100
- <!-- API fetch pattern -->
1101
- <div class="demo-block">
1102
- <div class="demo-block-title">API Fetch Pattern</div>
1103
- <p class="demo-description mt-3">Use the <code>apiFetch()</code> helper for all API calls. It handles session tokens automatically.</p>
1104
- <div class="demo-preview">
1105
- <button class="btn" onclick="demoApiFetch()">Test API Call</button>
1106
- </div>
1107
- <div class="demo-code">
1108
- <div class="code-block-header">
1109
- <span>JavaScript</span>
1110
- <button class="btn-copy" onclick="copyCode(this)">Copy</button>
1111
1263
  </div>
1112
- <pre><code>// GET request
1113
- const shopData = await apiFetch("/api/shop");
1264
+ </s-box>
1265
+ </s-section>
1266
+ </div>
1114
1267
 
1115
- // POST request with body
1268
+
1269
+ <!-- ═══════════════════════════════════════════════════════════ -->
1270
+ <!-- SECTION: COMMON PATTERNS -->
1271
+ <!-- ═══════════════════════════════════════════════════════════ -->
1272
+ <div id="section-patterns">
1273
+ <s-section heading="Common Patterns">
1274
+ <s-text color="subdued">Reusable UI patterns combining multiple Polaris components.</s-text>
1275
+
1276
+ <!-- Pattern: Stat cards -->
1277
+ <s-box paddingBlockStart="base">
1278
+ <s-box border="base" borderRadius="base" padding="base">
1279
+ <s-text variant="headingSm">Metric Cards</s-text>
1280
+ <s-box paddingBlockStart="small-200">
1281
+ <s-grid gridTemplateColumns="@container (inline-size <= 400px) 1fr 1fr, 1fr 1fr 1fr 1fr" gap="base">
1282
+ <s-box border="base" borderRadius="base" padding="base">
1283
+ <s-stack gap="small-200">
1284
+ <s-text color="subdued">Total Sales</s-text>
1285
+ <s-text variant="headingLg">$12,450</s-text>
1286
+ <s-text color="success" variant="bodySm">+12.5%</s-text>
1287
+ </s-stack>
1288
+ </s-box>
1289
+ <s-box border="base" borderRadius="base" padding="base">
1290
+ <s-stack gap="small-200">
1291
+ <s-text color="subdued">Orders</s-text>
1292
+ <s-text variant="headingLg">156</s-text>
1293
+ <s-text color="success" variant="bodySm">+8.2%</s-text>
1294
+ </s-stack>
1295
+ </s-box>
1296
+ <s-box border="base" borderRadius="base" padding="base">
1297
+ <s-stack gap="small-200">
1298
+ <s-text color="subdued">Visitors</s-text>
1299
+ <s-text variant="headingLg">3,842</s-text>
1300
+ <s-text color="critical" variant="bodySm">-2.1%</s-text>
1301
+ </s-stack>
1302
+ </s-box>
1303
+ <s-box border="base" borderRadius="base" padding="base">
1304
+ <s-stack gap="small-200">
1305
+ <s-text color="subdued">Conversion</s-text>
1306
+ <s-text variant="headingLg">4.1%</s-text>
1307
+ <s-text color="success" variant="bodySm">+0.3%</s-text>
1308
+ </s-stack>
1309
+ </s-box>
1310
+ </s-grid>
1311
+ </s-box>
1312
+ </s-box>
1313
+ </s-box>
1314
+
1315
+ <!-- Pattern: Info list -->
1316
+ <s-box paddingBlockStart="base">
1317
+ <s-box border="base" borderRadius="base" padding="base">
1318
+ <s-text variant="headingSm">Info List (Key-Value)</s-text>
1319
+ <s-box paddingBlockStart="small-200">
1320
+ <s-stack gap="small-200">
1321
+ <s-grid gridTemplateColumns="1fr 1fr" gap="small-200">
1322
+ <s-text color="subdued">Store name</s-text>
1323
+ <s-text>My Awesome Store</s-text>
1324
+ </s-grid>
1325
+ <s-grid gridTemplateColumns="1fr 1fr" gap="small-200">
1326
+ <s-text color="subdued">Plan</s-text>
1327
+ <s-text>Shopify Plus</s-text>
1328
+ </s-grid>
1329
+ <s-grid gridTemplateColumns="1fr 1fr" gap="small-200">
1330
+ <s-text color="subdued">Status</s-text>
1331
+ <s-badge tone="success">Active</s-badge>
1332
+ </s-grid>
1333
+ </s-stack>
1334
+ </s-box>
1335
+ </s-box>
1336
+ </s-box>
1337
+
1338
+ <!-- Pattern: Empty state -->
1339
+ <s-box paddingBlockStart="base">
1340
+ <s-box border="base" borderRadius="base" padding="large-1200">
1341
+ <s-stack alignItems="center" gap="base">
1342
+ <s-text variant="headingMd">No orders yet</s-text>
1343
+ <s-text color="subdued">When customers place orders, they will appear here.</s-text>
1344
+ <s-button variant="primary">Add product</s-button>
1345
+ </s-stack>
1346
+ </s-box>
1347
+ </s-box>
1348
+
1349
+ <!-- Pattern: API fetch -->
1350
+ <s-box paddingBlockStart="base">
1351
+ <s-box border="base" borderRadius="base" padding="base">
1352
+ <s-stack gap="base">
1353
+ <s-text variant="headingSm">API Fetch Pattern</s-text>
1354
+ <s-text color="subdued">Use <code>apiFetch()</code> for all API calls. It handles session tokens automatically.</s-text>
1355
+ <s-button onclick="demoApiFetch()">Test API Call</s-button>
1356
+ </s-stack>
1357
+ </s-box>
1358
+ </s-box>
1359
+
1360
+ <s-box paddingBlockStart="base">
1361
+ <div class="demo-code">
1362
+ <div class="code-block-header">
1363
+ <span>JavaScript</span>
1364
+ <button class="btn-copy" onclick="copyCode(this)">Copy</button>
1365
+ </div>
1366
+ <pre><code>// GET request
1367
+ const data = await apiFetch("/api/shop");
1368
+
1369
+ // POST request
1116
1370
  await apiFetch("/api/settings", {
1117
1371
  method: "POST",
1118
- body: JSON.stringify({
1119
- settings: { greeting: "Hello!" }
1120
- }),
1372
+ body: JSON.stringify({ greeting: "Hello!" }),
1121
1373
  });
1122
1374
 
1123
1375
  // Search with query params
@@ -1131,17 +1383,36 @@ try {
1131
1383
  showToast("Success!");
1132
1384
  } catch (err) {
1133
1385
  showToast("Error: " + err.message, true);
1386
+ }
1387
+
1388
+ // Loading pattern
1389
+ const loading = document.getElementById("my-loading");
1390
+ const content = document.getElementById("my-content");
1391
+ loading.style.display = "";
1392
+ content.style.display = "none";
1393
+ try {
1394
+ const data = await apiFetch("/api/data");
1395
+ // Render data...
1396
+ loading.style.display = "none";
1397
+ content.style.display = "";
1398
+ } catch (err) {
1399
+ loading.innerHTML = '&lt;s-banner tone="critical"&gt;' +
1400
+ '&lt;s-text&gt;' + err.message + '&lt;/s-text&gt;&lt;/s-banner&gt;';
1134
1401
  }</code></pre>
1135
- </div>
1136
- </div>
1402
+ </div>
1403
+ </s-box>
1404
+ </s-section>
1137
1405
  </div>
1138
1406
 
1139
1407
 
1140
1408
  <!-- Footer -->
1141
- <div class="card text-center" style="margin-top: 32px;">
1142
- <p class="text-secondary text-sm">Built with the Shopify App Bridge + Firebase Hosting scaffold. Edit <code>web/css/app.css</code> to customize these components.</p>
1143
- </div>
1144
- </div>
1409
+ <s-section>
1410
+ <s-stack alignItems="center">
1411
+ <s-text color="subdued">Built with Shopify Polaris Web Components + App Bridge + Firebase Hosting. See <s-link href="https://polaris.shopify.com" target="_blank">polaris.shopify.com</s-link> for full documentation.</s-text>
1412
+ </s-stack>
1413
+ </s-section>
1414
+
1415
+ </s-page>
1145
1416
 
1146
1417
  <script src="/js/app.js"></script>
1147
1418
  <script src="/js/pages/polaris-demo.js"></script>