@zohofinance/commerce 1.0.0 → 1.0.1
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.
- package/README.md +61 -0
- package/package.json +2 -2
- package/ts-dist/mocks/init-theme/.claude/CLAUDE.md +6 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/SKILL.md +242 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/figma.md +81 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/screenshot.md +54 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/url.md +88 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/spec-table.md +102 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/accessibility.md +110 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/performance.md +127 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/tokens.md +87 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/visual-diff.md +123 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/SKILL.md +605 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/design-tokens.md +105 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/page-json-contract.md +58 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/qa-accessibility.md +35 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/reference-lookup.md +94 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/section-anatomy.md +109 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/SKILL.md +313 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/agent-hierarchy.md +142 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/ask-developer.md +113 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/bootstrap.md +260 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/build-metrics.md +89 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/code-quality.md +186 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/common-pages-agent.md +97 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/dev-server-and-urls.md +127 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/exemplars.md +79 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/figma-discovery.md +138 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/figma-extraction.md +132 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/image-sources.md +84 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/inputs/guidelines-frame.md +178 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/page-builder.md +322 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/page-orchestrator.md +199 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/parallel-fanout.md +152 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/a11y.mjs +129 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/lint-section.mjs +502 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/perf.mjs +134 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/pixel-diff.mjs +206 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/record-build-metrics.mjs +118 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/section-builder.md +131 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/subagent-escalation.md +75 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/transcription-rules.md +98 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/verification.md +227 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/visual-verify-loop.md +117 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/_index.md +4 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/assets.md +105 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/best-practices.md +212 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/custom-scripts.md +294 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/i18n.md +155 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/introduction.md +91 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/layouts.md +158 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/pages.md +156 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/_index.md +4 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/filters.md +419 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/global-objects.md +415 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/schema-types.md +926 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/tags.md +259 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/sections.md +203 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/setup-guide.md +424 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/snippets.md +70 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/theme-structure.md +252 -0
- package/ts-dist/mocks/init-theme/.cursor/PLAYBOOK.md +144 -0
- package/ts-dist/mocks/init-theme/.cursor/README.md +6 -0
- package/ts-dist/mocks/init-theme/.cursor/agents/figma-desktop-mobile-parallel.md +48 -0
- package/ts-dist/mocks/init-theme/.cursor/agents/visual-compare.md +221 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/add-field.md +83 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/add-theme-setting.md +200 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/assemble-page.md +72 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/audit-page.md +57 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/build-page-sections.md +110 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/build-section.md +418 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/build-theme.md +307 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/compare-section.md +358 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/create-theme.md +77 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/extract-tokens.md +43 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/fix-section.md +92 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/impact.md +50 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-a11y.md +66 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-i18n.md +110 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-layout.md +127 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-performance.md +72 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-section.md +84 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-sections.md +48 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-theme.md +85 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/redesign-section.md +177 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/refactor-section.md +185 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/sync-theme-settings.md +132 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/validate-page.md +60 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/validate-section-group.md +88 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/validate-theme-settings.md +119 -0
- package/ts-dist/mocks/init-theme/.cursor/examples/design-instructions-template.md +151 -0
- package/ts-dist/mocks/init-theme/.cursor/mcp.json +18 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/README.md +160 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/accessibility.mdc +24 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/add-field.mdc +222 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/add-theme-setting.mdc +39 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/assemble-page.mdc +130 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/audit-page.mdc +92 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/build-section.mdc +178 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/build-theme.mdc +47 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/compare-section.mdc +94 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/create-theme.mdc +78 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/css.mdc +137 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/design-spec-extraction.mdc +255 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/extract-tokens.mdc +43 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/figma-mcp-resolution.mdc +40 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/fix-section.mdc +154 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/general.mdc +30 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/i18n.mdc +85 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/javascript.mdc +85 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/liquid-no-hardcoded-strings.mdc +42 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/liquid.mdc +171 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/mobile-desktop-setting-meta.mdc +34 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/naming-convention.mdc +64 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/pages.mdc +120 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/performance.mdc +51 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/qa-section.mdc +134 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/redesign-section.mdc +147 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/schema-sync.mdc +110 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/schema.mdc +360 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/share-urls.mdc +68 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/browser-verify.md +128 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/design-tokens.md +105 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/page-json-contract.md +87 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/qa-accessibility.md +35 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/reference-lookup.md +88 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/section-anatomy.md +173 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Custom schema syntax rules — applies to all themes
|
|
3
|
+
globs: ["sections/*.liquid", "blocks/*.liquid", "pages/*.json"]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Custom Schema Syntax — b2bizmart Theme
|
|
7
|
+
This project uses CUSTOM schema syntax. It is NOT standard Shopify schema.
|
|
8
|
+
NEVER use standard Shopify schema syntax. Always use the patterns below.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## ✅ URL Type
|
|
13
|
+
```jsonc
|
|
14
|
+
{
|
|
15
|
+
"type": "url",
|
|
16
|
+
"id": "my_url",
|
|
17
|
+
"label": "t:sections.section_name.settings.my_url.label",
|
|
18
|
+
"default": { "display_name": "t:sections.section_name.settings.my_url.default", "handle": "/path" }
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
- `display_name` → always a `t:` translation key
|
|
22
|
+
- `handle` → the actual URL path string (e.g. `"home"`, `"/categories"`, `"/bulk-orders"`)
|
|
23
|
+
- ❌ NEVER use: `"default": "/path"` (standard Shopify format)
|
|
24
|
+
|
|
25
|
+
### Render in Liquid
|
|
26
|
+
```liquid
|
|
27
|
+
{{ section.settings.my_url.handle }}
|
|
28
|
+
{{ section.settings.my_url.display_name }}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## ✅ Image Picker Type
|
|
34
|
+
```jsonc
|
|
35
|
+
{
|
|
36
|
+
"type": "image_picker",
|
|
37
|
+
"id": "desktop_banner_img",
|
|
38
|
+
"label": "t:sections.section_name.settings.desktop_banner_img.label",
|
|
39
|
+
"default": { "url": "filename.webp", "enable_customisation": true }
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
- `url` → filename string (e.g. `"banner1.webp"`, `"hero.jpg"`)
|
|
43
|
+
- `enable_customisation` → always `true`
|
|
44
|
+
- ❌ NEVER use: `"default": "/image.jpg"` (standard Shopify format)
|
|
45
|
+
|
|
46
|
+
### Render in Liquid
|
|
47
|
+
```liquid
|
|
48
|
+
{{ section.settings.desktop_banner_img.url }}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## ✅ Media Picker Type (Video)
|
|
54
|
+
```jsonc
|
|
55
|
+
{
|
|
56
|
+
"type": "media_picker",
|
|
57
|
+
"id": "video_media",
|
|
58
|
+
"label": "t:sections.section_name.settings.video_media.label",
|
|
59
|
+
"default": { "url": "video.mp4", "is_video": true }
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
- `url` → video filename string (e.g. `"intro.mp4"`, `"hero-video.mp4"`)
|
|
63
|
+
- `is_video` → always `true` for video media
|
|
64
|
+
|
|
65
|
+
### Render in Liquid
|
|
66
|
+
```liquid
|
|
67
|
+
{{ section.settings.video_media.url }}
|
|
68
|
+
{{ section.settings.video_media.is_video }}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## ✅ Select Type
|
|
74
|
+
```jsonc
|
|
75
|
+
{
|
|
76
|
+
"type": "select",
|
|
77
|
+
"id": "layout_type",
|
|
78
|
+
"label": "t:sections.section_name.settings.layout_type.label",
|
|
79
|
+
"options": [
|
|
80
|
+
{ "label": "t:sections.section_name.settings.layout_type.option__1.label", "value": "left-alignment" },
|
|
81
|
+
{ "label": "t:sections.section_name.settings.layout_type.option__2.label", "value": "right-alignment" }
|
|
82
|
+
],
|
|
83
|
+
"default": { "display_name": "t:sections.section_name.settings.layout_type.default", "value": "left-alignment" }
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
- `default` is an object `{ "display_name": "t:...", "value": "..." }`
|
|
87
|
+
- `display_name` → always a `t:` translation key
|
|
88
|
+
- ❌ NEVER use: `"default": "left-alignment"` (standard Shopify format)
|
|
89
|
+
|
|
90
|
+
### Render in Liquid
|
|
91
|
+
```liquid
|
|
92
|
+
{{ section.settings.layout_type.value }}
|
|
93
|
+
{{ section.settings.layout_type.display_name }}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## ✅ Menu Type
|
|
99
|
+
```jsonc
|
|
100
|
+
{
|
|
101
|
+
"type": "menu",
|
|
102
|
+
"id": "footer_menu",
|
|
103
|
+
"label": "t:sections.section_name.settings.footer_menu.label",
|
|
104
|
+
"default": { "display_name": "t:sections.section_name.settings.footer_menu.default", "handle": "" }
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
- `display_name` → always a `t:` translation key
|
|
108
|
+
- `handle` → menu handle string or empty string `""`
|
|
109
|
+
- ❌ NEVER use standard Shopify `linklists` or `linklist` objects
|
|
110
|
+
|
|
111
|
+
### Render in Liquid
|
|
112
|
+
```liquid
|
|
113
|
+
{{ section.settings.footer_menu.handle }}
|
|
114
|
+
{{ section.settings.footer_menu.display_name }}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## ✅ Text Type
|
|
120
|
+
```jsonc
|
|
121
|
+
{
|
|
122
|
+
"type": "text",
|
|
123
|
+
"id": "heading",
|
|
124
|
+
"label": "t:sections.section_name.settings.heading.label",
|
|
125
|
+
"default": "t:sections.section_name.settings.heading.default"
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
- `default` → always a `t:` translation key string
|
|
129
|
+
- ❌ NEVER use hardcoded English strings as defaults
|
|
130
|
+
|
|
131
|
+
### Render in Liquid
|
|
132
|
+
```liquid
|
|
133
|
+
{{ section.settings.heading | escape }}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Use `text` for all headings and short labels** — section titles, card titles, eyebrows, badge text, button/CTA labels, and any field rendered in `<h1>`–`<h6>`. Never use `richtext` for heading blocks or heading fields.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## ✅ Richtext Type
|
|
141
|
+
```jsonc
|
|
142
|
+
{
|
|
143
|
+
"type": "richtext",
|
|
144
|
+
"id": "description",
|
|
145
|
+
"label": "t:sections.section_name.settings.description.label",
|
|
146
|
+
"default": "<p>t:sections.section_name.settings.description.default</p>"
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
- `default` → HTML string (use `t:` keys inside tags when the default is translatable)
|
|
150
|
+
- Use only for **body copy** — paragraphs, descriptions, answers, multi-line content where merchants may need bold, links, or lists
|
|
151
|
+
- ❌ NEVER use `richtext` for headings, titles, eyebrows, or button labels
|
|
152
|
+
|
|
153
|
+
### Render in Liquid
|
|
154
|
+
```liquid
|
|
155
|
+
{{ section.settings.description | raw }}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## ✅ Heading vs content — field type rule
|
|
161
|
+
|
|
162
|
+
| Renders as | Schema type | Liquid output |
|
|
163
|
+
|---|---|---|
|
|
164
|
+
| `<h1>`–`<h6>`, title, eyebrow, badge, button label | `text` | `{{ field \| escape }}` |
|
|
165
|
+
| `<p>`, body copy, description, FAQ answer | `richtext` | `{{ field \| raw }}` |
|
|
166
|
+
|
|
167
|
+
Block types named `heading`, `title`, or similar → settings inside must use `text`, not `richtext`.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## ✅ Range Type
|
|
172
|
+
```jsonc
|
|
173
|
+
{
|
|
174
|
+
"type": "range",
|
|
175
|
+
"id": "logo_width",
|
|
176
|
+
"min": 32,
|
|
177
|
+
"max": 56,
|
|
178
|
+
"step": 2,
|
|
179
|
+
"unit": "px",
|
|
180
|
+
"default": 40,
|
|
181
|
+
"label": "t:sections.section_name.settings.logo_width.label"
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
- `default` → plain number (not an object)
|
|
185
|
+
- `unit` → optional string like `"px"`, `"%"`
|
|
186
|
+
|
|
187
|
+
### Render in Liquid
|
|
188
|
+
```liquid
|
|
189
|
+
{{ section.settings.logo_width }}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## ✅ Checkbox Type
|
|
195
|
+
```jsonc
|
|
196
|
+
{
|
|
197
|
+
"type": "checkbox",
|
|
198
|
+
"id": "show_banner_image",
|
|
199
|
+
"label": "t:sections.section_name.settings.show_banner_image.label",
|
|
200
|
+
"default": false
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
- `default` → plain boolean `true` or `false`
|
|
204
|
+
|
|
205
|
+
### Render in Liquid
|
|
206
|
+
```liquid
|
|
207
|
+
{% if section.settings.show_banner_image %}...{% endif %}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## ✅ Color Type
|
|
213
|
+
```jsonc
|
|
214
|
+
{
|
|
215
|
+
"type": "color",
|
|
216
|
+
"id": "overlay_color",
|
|
217
|
+
"label": "t:sections.section_name.settings.overlay_color.label",
|
|
218
|
+
"default": "#000000"
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
- `default` → hex color string
|
|
222
|
+
|
|
223
|
+
### Render in Liquid
|
|
224
|
+
```liquid
|
|
225
|
+
{{ section.settings.overlay_color }}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## ✅ Header Type (UI divider, no id)
|
|
231
|
+
```jsonc
|
|
232
|
+
{
|
|
233
|
+
"type": "header",
|
|
234
|
+
"content": "t:sections.section_name.settings.my_header.content"
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
- No `id` field
|
|
238
|
+
- `content` → always a `t:` translation key
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## ✅ Blocks
|
|
243
|
+
|
|
244
|
+
There are **two block models**. A section may use one or both.
|
|
245
|
+
|
|
246
|
+
### 1. Local blocks (section-scoped)
|
|
247
|
+
|
|
248
|
+
Defined inline in the section's `{% schema %}` with full `settings`. Page JSON `type` is the bare block type name (e.g. `"badge"`).
|
|
249
|
+
|
|
250
|
+
```jsonc
|
|
251
|
+
// In section schema
|
|
252
|
+
"blocks": [
|
|
253
|
+
{
|
|
254
|
+
"type": "block-type-name",
|
|
255
|
+
"name": "t:sections.section_name.blocks.block_type.name",
|
|
256
|
+
"limit": 3,
|
|
257
|
+
"settings": [ ...settings using above patterns... ]
|
|
258
|
+
}
|
|
259
|
+
]
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Render in the section with a `{% for block in section.blocks %}` loop and inline markup (or `{% case block.type %}`).
|
|
263
|
+
|
|
264
|
+
### 2. Theme blocks (reusable, theme-scoped)
|
|
265
|
+
|
|
266
|
+
Live as standalone files at `blocks/<name>.liquid`, each with its own `{% schema %}`. A section **opts in** by listing them in its schema `blocks` array:
|
|
267
|
+
|
|
268
|
+
```jsonc
|
|
269
|
+
// Offer ALL theme blocks in the picker
|
|
270
|
+
{ "type": "@theme" }
|
|
271
|
+
|
|
272
|
+
// Offer specific theme blocks only (preferred when mixing with local blocks)
|
|
273
|
+
{ "type": "zc_theme__text", "name": "t:blocks.text.name" },
|
|
274
|
+
{ "type": "zc_theme__button", "name": "t:blocks.button.name", "limit": 2 }
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
- Runtime type prefix: `zc_theme__` + file name (`blocks/text.liquid` → `zc_theme__text`)
|
|
278
|
+
- i18n keys: `t:blocks.<name>.*` (not `t:sections.*.blocks.*`)
|
|
279
|
+
- Theme block files must include `"presets": [ { "name": "t:blocks.<name>.presets.default.name" } ]` so they appear in the editor picker
|
|
280
|
+
- Theme blocks see only `block`, `section`, and globals — not section-local `{% liquid %}` assigns
|
|
281
|
+
- Nesting: a theme block may declare its own `"blocks"` array and render children with `{% render_blocks %}` (max depth 5)
|
|
282
|
+
|
|
283
|
+
```liquid
|
|
284
|
+
// Pure theme-block section
|
|
285
|
+
{% render_blocks %}
|
|
286
|
+
|
|
287
|
+
// Filtered slot (e.g. heading area only)
|
|
288
|
+
{% render_blocks type: "zc_theme__text" %}
|
|
289
|
+
|
|
290
|
+
// Mixed section — local + theme blocks
|
|
291
|
+
{% for block in section.blocks %}
|
|
292
|
+
{% case block.type %}
|
|
293
|
+
{% when 'badge' %}
|
|
294
|
+
{%- comment -%} inline local block markup {%- endcomment -%}
|
|
295
|
+
{% else %}
|
|
296
|
+
{% render block %}
|
|
297
|
+
{% endcase %}
|
|
298
|
+
{% endfor %}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Page JSON (both models)
|
|
302
|
+
|
|
303
|
+
```jsonc
|
|
304
|
+
"blocks": {
|
|
305
|
+
"heading-block": {
|
|
306
|
+
"type": "zc_theme__text",
|
|
307
|
+
"settings": {
|
|
308
|
+
"text": "<p>Welcome</p>",
|
|
309
|
+
"desktop_text_size": { "display_name": "Large", "value": "text-2xl" }
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
"badge-1": {
|
|
313
|
+
"type": "badge",
|
|
314
|
+
"settings": {
|
|
315
|
+
"select_field": { "display_name": "Left", "value": "left" },
|
|
316
|
+
"image_field": { "url": "image.webp", "enable_customisation": true },
|
|
317
|
+
"url_field": { "display_name": "Home", "handle": "/home" },
|
|
318
|
+
"checkbox_field": false,
|
|
319
|
+
"range_field": 48,
|
|
320
|
+
"color_field": "#000000",
|
|
321
|
+
"video_field": { "url": "video.mp4", "is_video": true }
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
"block_order": ["heading-block", "badge-1"]
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
- Local block `type` → bare name defined in section schema
|
|
329
|
+
- Theme block `type` → `zc_theme__<name>` matching `blocks/<name>.liquid`
|
|
330
|
+
- Block `settings` keys must match the schema for that block type (section schema for local; `blocks/<name>.liquid` schema for theme)
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## ✅ Full Section Schema Template
|
|
335
|
+
```jsonc
|
|
336
|
+
{% schema %}
|
|
337
|
+
{
|
|
338
|
+
"name": "t:sections.section_name.name",
|
|
339
|
+
"tag": "section",
|
|
340
|
+
"class": "section",
|
|
341
|
+
"settings": [],
|
|
342
|
+
"blocks": [],
|
|
343
|
+
"presets": [
|
|
344
|
+
{
|
|
345
|
+
"name": "t:sections.section_name.presets.default.name"
|
|
346
|
+
}
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
{% endschema %}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## ❌ Never Use These (Standard Shopify Patterns)
|
|
355
|
+
- `"default": "/some-url"` → use `{ "display_name": "t:...", "handle": "/some-url" }`
|
|
356
|
+
- `"default": "option-value"` for selects → use `{ "display_name": "t:...", "value": "option-value" }`
|
|
357
|
+
- `{{ section.settings.image | img_url }}` → use `{{ section.settings.image.url }}`
|
|
358
|
+
- Video in image_picker → use `media_picker` with `{ "url": "video.mp4", "is_video": true }`
|
|
359
|
+
- `{{ section.settings.menu }}` for menus → use `{{ section.settings.menu.handle }}`
|
|
360
|
+
- Hardcoded English in `label`, `default`, `content` → always use `t:` keys
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Social share URL patterns for product pages — use when adding share links to any section
|
|
3
|
+
alwaysApply: false
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Share URL Logic
|
|
7
|
+
|
|
8
|
+
When building social share icons on a product page, use these URL patterns. No JavaScript — pure `<a>` links only.
|
|
9
|
+
|
|
10
|
+
## Variable assignments
|
|
11
|
+
|
|
12
|
+
Always compute share variables before rendering links:
|
|
13
|
+
|
|
14
|
+
```liquid
|
|
15
|
+
{% liquid
|
|
16
|
+
assign pdp_share_origin = page_info.origin | default: storefrontRootUrl | default: storefrontHomeUrl | default: ''
|
|
17
|
+
assign pdp_share_url = product.url
|
|
18
|
+
if pdp_share_origin != blank
|
|
19
|
+
assign pdp_share_url = pdp_share_origin | append: product.url
|
|
20
|
+
endif
|
|
21
|
+
assign pdp_share_title = product.title | url_encode
|
|
22
|
+
assign pdp_share_url_encoded = pdp_share_url | url_encode
|
|
23
|
+
assign pdp_share_image = ''
|
|
24
|
+
if product.images and product.images.size > 0
|
|
25
|
+
assign pdp_share_image = product.images | first | image_url | url_encode
|
|
26
|
+
endif
|
|
27
|
+
assign pdp_share_desc = product.short_description | default: product.title | url_encode
|
|
28
|
+
%}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## URLs
|
|
32
|
+
|
|
33
|
+
| Platform | URL |
|
|
34
|
+
|------------|---------------------------------------------------------------------------------------------|
|
|
35
|
+
| Copy link | `{{ pdp_share_url }}` |
|
|
36
|
+
| Facebook | `https://www.facebook.com/sharer/sharer.php?u={{ pdp_share_url_encoded }}` |
|
|
37
|
+
| Pinterest | `https://pinterest.com/pin/create/button/?url={{ pdp_share_url_encoded }}{% if pdp_share_image != blank %}&media={{ pdp_share_image }}{% endif %}&description={{ pdp_share_desc }}` |
|
|
38
|
+
| Instagram | `https://www.instagram.com/` |
|
|
39
|
+
| X (Twitter)| `https://x.com/intent/tweet?url={{ pdp_share_url_encoded }}&text={{ pdp_share_title }}` |
|
|
40
|
+
|
|
41
|
+
## Markup pattern
|
|
42
|
+
|
|
43
|
+
```liquid
|
|
44
|
+
<a href="<share-url>" target="_blank" rel="noopener noreferrer"
|
|
45
|
+
class="flex items-center justify-center w-6 h-6 [&>svg]:w-full [&>svg]:h-full"
|
|
46
|
+
aria-label="{{ 'product_details.share_<platform>' | t }}">
|
|
47
|
+
{% render 'icon-<platform>' %}
|
|
48
|
+
</a>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Icon snippets
|
|
52
|
+
|
|
53
|
+
- `icon-link` — chain link (copy/share URL)
|
|
54
|
+
- `icon-facebook`
|
|
55
|
+
- `icon-pinterest`
|
|
56
|
+
- `icon-instagram`
|
|
57
|
+
- `icon-x` — X / Twitter
|
|
58
|
+
|
|
59
|
+
## i18n keys (runtime — `en.json`)
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
"share_label": "Share",
|
|
63
|
+
"share_copy_link": "Copy link",
|
|
64
|
+
"share_facebook": "Share on Facebook",
|
|
65
|
+
"share_pinterest": "Share on Pinterest",
|
|
66
|
+
"share_instagram": "Share on Instagram",
|
|
67
|
+
"share_x": "Share on X"
|
|
68
|
+
```
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Browser verification — Chrome DevTools MCP
|
|
2
|
+
|
|
3
|
+
Single source of truth for browser automation during theme development.
|
|
4
|
+
|
|
5
|
+
**MCP config:** `.cursor/mcp.json`
|
|
6
|
+
**Used by:** `/build-theme`, `/compare-section --visual`, section-builder, page-orchestrator
|
|
7
|
+
**Fallback:** `cursor-ide-browser` only if `chrome-devtools` MCP is unavailable
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Preconditions
|
|
12
|
+
|
|
13
|
+
1. **Developer confirmed `storeUrl`** — recorded in `.claude/scratchpad/<theme>/dev-config.json`
|
|
14
|
+
2. **Developer confirmed page URLs** — same file, `confirmed_by_developer: true`
|
|
15
|
+
3. Dev server running: `yarn run dev --storeUrl=<store_url>` (developer starts OR agent starts and notifies)
|
|
16
|
+
4. Chrome DevTools MCP connected
|
|
17
|
+
5. Figma node ID known for visual compare
|
|
18
|
+
|
|
19
|
+
**Do not navigate until URLs are confirmed.** If any fail → ask developer. Never invent a "verified pass."
|
|
20
|
+
|
|
21
|
+
See `.claude/skills/theme-from-figma/dev-server-and-urls.md`.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Page URLs (defaults — always confirm with developer)
|
|
26
|
+
|
|
27
|
+
| Page | Typical URL (verify!) |
|
|
28
|
+
|---|---|
|
|
29
|
+
| Home | `http://localhost:3000/home` |
|
|
30
|
+
| Product | `http://localhost:3000/products/item-1` |
|
|
31
|
+
| Collection | `http://localhost:3000/collections/all-products` |
|
|
32
|
+
| Blog list | ask developer |
|
|
33
|
+
| Blog detail | ask developer |
|
|
34
|
+
|
|
35
|
+
Read confirmed URLs from `dev-config.json` — never hardcode.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Tool map — use the full toolkit
|
|
40
|
+
|
|
41
|
+
| Task | Tool |
|
|
42
|
+
|---|---|
|
|
43
|
+
| Open tab | `list_pages` → `select_page` or `new_page` |
|
|
44
|
+
| Navigate | `navigate_page` |
|
|
45
|
+
| Viewport | `emulate` → `1440x900` or `375x812,mobile,touch` |
|
|
46
|
+
| Scroll to section | `evaluate_script` → `scrollIntoView` |
|
|
47
|
+
| Screenshot | `take_screenshot` + `filePath` to scratchpad |
|
|
48
|
+
| DOM / a11y tree | `take_snapshot` |
|
|
49
|
+
| Console | `list_console_messages` types `["error","issue"]` |
|
|
50
|
+
| Network / 404 images | `list_network_requests` |
|
|
51
|
+
| **A11y audit** | `lighthouse_audit` mode `navigation` device `mobile` |
|
|
52
|
+
| **Perf audit** | `lighthouse_audit` (baseline) + `performance_start_trace` → `performance_stop_trace` → `performance_analyze_insight` for LCP |
|
|
53
|
+
| Computed styles | `evaluate_script` |
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Standard 3-gate workflow (section or page)
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
GATE 1 — VISUAL
|
|
61
|
+
emulate desktop → navigate → scroll section → take_screenshot
|
|
62
|
+
emulate mobile → take_screenshot
|
|
63
|
+
Figma MCP get_screenshot (same node, desktop + mobile)
|
|
64
|
+
Agent vision → visual-diff.md (CRITICAL / MINOR / SUGGESTION)
|
|
65
|
+
list_network_requests → flag image 404s (check asset_url — see image-sources.md)
|
|
66
|
+
|
|
67
|
+
GATE 2 — A11Y
|
|
68
|
+
lighthouse_audit mode:navigation device:mobile
|
|
69
|
+
list_console_messages types:["error","issue"]
|
|
70
|
+
Pass: a11y score ≥ 90, no critical console issues affecting section
|
|
71
|
+
|
|
72
|
+
GATE 3 — PERF (pages; spot-check heavy sections)
|
|
73
|
+
lighthouse_audit device:mobile on page URL
|
|
74
|
+
If LCP poor: performance_start_trace → navigate → performance_stop_trace → analyze
|
|
75
|
+
Pass: perf score ≥ 85 mobile (pages), CLS < 0.1
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Run Gate 1 desktop + mobile screenshots **in parallel** with Figma `get_screenshot` when possible.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Parallel subagents
|
|
83
|
+
|
|
84
|
+
1. `new_page` per subagent
|
|
85
|
+
2. Pass `pageId` on every subsequent call
|
|
86
|
+
3. `close_page` when done
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Screenshot paths
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
.claude/scratchpad/<theme>/pages/<page>/sections/<section>/rendered-desktop.png
|
|
94
|
+
.claude/scratchpad/<theme>/pages/<page>/sections/<section>/rendered-mobile.png
|
|
95
|
+
.claude/scratchpad/<theme>/pages/<page>/rendered-desktop.png
|
|
96
|
+
.claude/scratchpad/<theme>/pages/<page>/rendered-mobile.png
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Image 404 debugging (common visual failure)
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
// evaluate_script — list broken images in section
|
|
105
|
+
() => {
|
|
106
|
+
const root = document.querySelector('#section-section_main') || document.body;
|
|
107
|
+
return [...root.querySelectorAll('img')].map(img => ({
|
|
108
|
+
src: img.src.slice(-80),
|
|
109
|
+
naturalWidth: img.naturalWidth,
|
|
110
|
+
broken: img.complete && img.naturalWidth === 0
|
|
111
|
+
})).filter(i => i.broken);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Fix: theme assets need `| asset_url`; product images need `?organization_id={{ organizationId }}`.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Release vs dev loop
|
|
120
|
+
|
|
121
|
+
| Gate | Dev loop (MCP) | Optional release script |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| Visual | Agent vision + screenshots | `scripts/pixel-diff.mjs` |
|
|
124
|
+
| A11y | `lighthouse_audit` | `scripts/a11y.mjs` |
|
|
125
|
+
| Perf | `lighthouse_audit` + trace | `scripts/perf.mjs` |
|
|
126
|
+
| Lint | `lint-section.mjs` | same |
|
|
127
|
+
|
|
128
|
+
**MCP results drive fixes.** Scripts produce JSON artefacts for CI if needed.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# SKILL: Design Tokens
|
|
2
|
+
# Save this as a Cursor Notepad named: design-tokens
|
|
3
|
+
# Usage in chat: @design-tokens
|
|
4
|
+
|
|
5
|
+
How to correctly map Figma values to Tailwind classes and CSS variables in this theme system.
|
|
6
|
+
Always use this when reading Figma output — never use raw values inline.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Figma MCP variable resolution (do this first)
|
|
11
|
+
When using **Figma MCP** (e.g. get_design_context), the response contains `var(--variable-name, fallback)`. The fallback may be from a different mode (e.g. TWICE). To use the theme’s mode (e.g. B2BIZMART):
|
|
12
|
+
|
|
13
|
+
1. **Look up** the variable name in `figma-variables.json`: split the name on `/` and traverse (e.g. `radius/xl` → `json["radius"]["xl"]`).
|
|
14
|
+
2. If the node has **`$value`**, use that value.
|
|
15
|
+
3. If not found, use the **fallback** from the MCP response.
|
|
16
|
+
4. Then map this **resolved** value to Tailwind/CSS using the tables below.
|
|
17
|
+
|
|
18
|
+
See `.cursor/rules/figma-mcp-resolution.mdc` for the full rule.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## The Rule
|
|
23
|
+
❌ Never output: `style="font-size: 48px; color: #1a1a1a"`
|
|
24
|
+
✅ Always output: `class="text-5xl" style="color: var(--color-heading)"`
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## CSS Variables (always use these for color)
|
|
29
|
+
| Role | Variable |
|
|
30
|
+
|------|----------|
|
|
31
|
+
| Primary brand | `var(--color-primary)` |
|
|
32
|
+
| Text on primary bg | `var(--color-on-primary)` |
|
|
33
|
+
| Headings / dark text | `var(--color-heading)` |
|
|
34
|
+
| Page / card background | `var(--color-background)` |
|
|
35
|
+
| Border / divider | `var(--color-border)` |
|
|
36
|
+
| Header bar background | `var(--color-header-bg)` |
|
|
37
|
+
| Section horizontal padding | `var(--section-padding-x, 16px)` |
|
|
38
|
+
|
|
39
|
+
For theme-specific colors not in this list → check `figma-variables.json` in the current theme folder (and resolve Figma MCP vars from it first when using MCP).
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Typography → Tailwind
|
|
44
|
+
| Figma px | Tailwind | Use for |
|
|
45
|
+
|----------|----------|---------|
|
|
46
|
+
| 12px | `text-xs` | Labels, captions |
|
|
47
|
+
| 14px | `text-sm` | Secondary text, meta |
|
|
48
|
+
| 16px | `text-base` | Body text |
|
|
49
|
+
| 18px | `text-lg` | Large body |
|
|
50
|
+
| 20px | `text-xl` | Small headings |
|
|
51
|
+
| 24px | `text-2xl` | Sub-headings |
|
|
52
|
+
| 30px | `text-3xl` | Section headings |
|
|
53
|
+
| 36px | `text-4xl` | Page headings |
|
|
54
|
+
| 48px | `text-5xl` | Hero headings |
|
|
55
|
+
| 60px | `text-6xl` | Display headings |
|
|
56
|
+
| 72px+ | `text-7xl` | Giant display |
|
|
57
|
+
|
|
58
|
+
Font weight:
|
|
59
|
+
| Figma | Tailwind |
|
|
60
|
+
|-------|----------|
|
|
61
|
+
| 400 | `font-normal` |
|
|
62
|
+
| 500 | `font-medium` |
|
|
63
|
+
| 600 | `font-semibold` |
|
|
64
|
+
| 700 | `font-bold` |
|
|
65
|
+
| 800 | `font-extrabold` |
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Spacing → Tailwind (1 unit = 4px)
|
|
70
|
+
| Figma px | Tailwind gap/p/m |
|
|
71
|
+
|----------|-----------------|
|
|
72
|
+
| 4px | `gap-1` / `p-1` |
|
|
73
|
+
| 8px | `gap-2` / `p-2` |
|
|
74
|
+
| 12px | `gap-3` / `p-3` |
|
|
75
|
+
| 16px | `gap-4` / `p-4` |
|
|
76
|
+
| 20px | `gap-5` / `p-5` |
|
|
77
|
+
| 24px | `gap-6` / `p-6` |
|
|
78
|
+
| 32px | `gap-8` / `p-8` |
|
|
79
|
+
| 40px | `gap-10` / `p-10` |
|
|
80
|
+
| 48px | `gap-12` / `p-12` |
|
|
81
|
+
| 64px | `gap-16` / `p-16` |
|
|
82
|
+
| 80px | `gap-20` / `p-20` |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Border Radius → Tailwind
|
|
87
|
+
| Figma px | Tailwind |
|
|
88
|
+
|----------|----------|
|
|
89
|
+
| 2px | `rounded-sm` |
|
|
90
|
+
| 4px | `rounded` |
|
|
91
|
+
| 6px | `rounded-md` |
|
|
92
|
+
| 8px | `rounded-lg` |
|
|
93
|
+
| 12px | `rounded-xl` |
|
|
94
|
+
| 16px | `rounded-2xl` |
|
|
95
|
+
| 24px | `rounded-3xl` |
|
|
96
|
+
| 9999px | `rounded-full` |
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## When a Value is Not in This Map
|
|
101
|
+
1. If from Figma MCP, resolve via `figma-variables.json` first (use `$value` if present).
|
|
102
|
+
2. Check `figma-variables.json` in the current theme folder for other mappings.
|
|
103
|
+
3. Use Tailwind arbitrary value: `text-[22px]` or `gap-[18px]`
|
|
104
|
+
4. Add a comment: `{{-- ⚠️ unmapped token: 22px --}}`
|
|
105
|
+
5. Report it in the build output so it can be added to the token map if needed.
|