@runwell/shopify-toolkit 0.3.0 → 0.4.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/lib/template.js +2 -1
- package/modules/INDEX.md +288 -0
- package/modules/comparison-table/module.json +29 -40
- package/modules/comparison-table/variants/feature-rows/sections/runwell-comparison-table.liquid +143 -0
- package/modules/sticky-atc/assets/runwell-sticky-atc.css +117 -0
- package/modules/sticky-atc/module.json +6 -3
- package/modules/sticky-atc/sections/runwell-pdp-sticky.liquid +1 -0
- package/package.json +1 -1
- /package/modules/comparison-table/{sections → variants/feature-columns/sections}/runwell-comparison-table.liquid +0 -0
package/lib/template.js
CHANGED
|
@@ -21,7 +21,8 @@ export function interpolate(source, vars) {
|
|
|
21
21
|
let working = source;
|
|
22
22
|
|
|
23
23
|
// Second pass: substitute {{config.X}} and {{brand.Y}} and {{client.Z}}
|
|
24
|
-
|
|
24
|
+
// Keys can include hyphens (e.g. brand.rain-forrest) and dots for nesting.
|
|
25
|
+
working = working.replace(/\{\{\s*([a-zA-Z][a-zA-Z0-9_.\-]*)\s*\}\}/g, (match, key) => {
|
|
25
26
|
// If the key starts with a Liquid keyword, leave it alone (it is Shopify Liquid)
|
|
26
27
|
const liquidKeywords = new Set([
|
|
27
28
|
'product', 'collection', 'cart', 'customer', 'shop', 'request',
|
package/modules/INDEX.md
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
# Runwell Shopify Toolkit: module index
|
|
2
|
+
|
|
3
|
+
Auto-generated by `scripts/generate-index.mjs`. Do not edit by hand.
|
|
4
|
+
Skills (shopify-storefront, shopify-cro, shopify-cli-ops, shopify-admin-browser) grep this file before writing custom Liquid.
|
|
5
|
+
|
|
6
|
+
Total modules: 31.
|
|
7
|
+
|
|
8
|
+
## By category
|
|
9
|
+
|
|
10
|
+
- **catalog**: bundle-builder, quantity-breaks, subscriptions
|
|
11
|
+
- **conversion**: cart-cross-sell, cart-freeship-progress, cart-usps, exit-intent, gift-with-purchase, post-purchase-upsell, quick-view, risk-reversal, shipping-bar, sticky-atc
|
|
12
|
+
- **customer**: loyalty-tiers, wishlist
|
|
13
|
+
- **pdp**: comparison-table, delivery-estimate, inventory-urgency, pdp-ingredients, pdp-journal-link, pdp-trust-checks, recently-viewed
|
|
14
|
+
- **social-proof**: press-bar, product-badges, reviews, testimonials, trust-badges
|
|
15
|
+
- **storefront**: editorial-block, editorial-hero, faq, how-it-works
|
|
16
|
+
|
|
17
|
+
## Modules
|
|
18
|
+
|
|
19
|
+
| Name | Category | Replaces | Files | Config keys | Variants | Admin steps |
|
|
20
|
+
|---|---|---|---|---|---|---|
|
|
21
|
+
| `bundle-builder` | catalog | BYOB-style bundle apps | sections:1 assets:1 | heading, sale_prefix, show_rating, rating_score, rating_count, show_trust_badges, trust_1, trust_2, trust_3, fomo_mode, fomo_cycle_days, fomo_stock_count | (none) | (none) |
|
|
22
|
+
| `cart-cross-sell` | conversion | Rebuy / OneClickUpsell pre-purchase upsell | snippets:1 | eyebrow, cta_label | (none) | (none) |
|
|
23
|
+
| `cart-freeship-progress` | conversion | Bold Free Shipping Manager and similar app features | snippets:1 | threshold_cents, away_text, unlocked_message | (none) | (none) |
|
|
24
|
+
| `cart-usps` | conversion | (native build) | snippets:1 | icon, usp_1, usp_2, usp_3 | (none) | (none) |
|
|
25
|
+
| `comparison-table` | pdp | app-driven comparison widgets | | eyebrow, heading, lede, background_color, text_color | feature-columns, feature-rows | (none) |
|
|
26
|
+
| `delivery-estimate` | pdp | (native build) | snippets:1 | (none) | (none) | (none) |
|
|
27
|
+
| `editorial-block` | storefront | (native build) | sections:1 | eyebrow, heading, lede, background_color, text_color | (none) | (none) |
|
|
28
|
+
| `editorial-hero` | storefront | (native build) | sections:1 | eyebrow, heading, subheading, video_url, poster_image, min_height, button_label_primary, button_link_primary, button_label_secondary, button_link_secondary | (none) | (none) |
|
|
29
|
+
| `exit-intent` | conversion | (native build) | sections:1 assets:1 | eyebrow, heading, lede | (none) | (none) |
|
|
30
|
+
| `faq` | storefront | (native build) | sections:1 | eyebrow, heading, background_color, text_color | (none) | (none) |
|
|
31
|
+
| `gift-with-purchase` | conversion | (native build) | snippets:1 assets:1 | threshold_cents, gift_handle, unlocked_message, locked_message_suffix | (none) | create-gift-product + create-gift-discount |
|
|
32
|
+
| `how-it-works` | storefront | (native build) | sections:1 | eyebrow, heading, lede, image, asset_filename, background_color, text_color, cta_label, cta_link | (none) | (none) |
|
|
33
|
+
| `inventory-urgency` | pdp | (native build) | snippets:1 | (none) | (none) | (none) |
|
|
34
|
+
| `loyalty-tiers` | customer | (native build) | sections:1 | tier_0_name, tier_1_name, tier_1_threshold, tier_1_perk_pct, tier_2_name, tier_2_threshold, tier_2_perk_pct | (none) | create-tier-tags-and-flows + create-tier-discounts + add-tier-card-to-account |
|
|
35
|
+
| `pdp-ingredients` | pdp | (native build) | sections:1 | eyebrow, heading, lede, background_color, text_color | (none) | (none) |
|
|
36
|
+
| `pdp-journal-link` | pdp | (native build) | sections:1 | eyebrow, article, background_color, text_color, fallback_title, fallback_body, fallback_link_label, fallback_link_url | (none) | (none) |
|
|
37
|
+
| `pdp-trust-checks` | pdp | (native build) | sections:1 | eyebrow, heading, lede, background_color, text_color, link_label, link_url | (none) | (none) |
|
|
38
|
+
| `post-purchase-upsell` | conversion | Reconvert / OneClickUpsell / AfterSell display layer | assets:2 | discount_code, discount_label, max_items, heading, eyebrow, lede, cross_category_logic | (none) | create-discount + paste-bootstrap |
|
|
39
|
+
| `press-bar` | social-proof | (native build) | sections:1 | eyebrow, background_color, text_color | (none) | (none) |
|
|
40
|
+
| `product-badges` | social-proof | (native build) | snippets:1 | label_best_seller, label_new, label_editor_pick | (none) | (none) |
|
|
41
|
+
| `quantity-breaks` | catalog | (native build) | snippets:1 | eyebrow, fineprint | (none) | define-breaks-metafield + set-product-breaks + create-discount-function |
|
|
42
|
+
| `quick-view` | conversion | (native build) | snippets:2 assets:1 | (none) | (none) | (none) |
|
|
43
|
+
| `recently-viewed` | pdp | (native build) | sections:1 assets:1 | eyebrow, heading, background_color | (none) | (none) |
|
|
44
|
+
| `reviews` | social-proof | (native build) | sections:1 | heading | (none) | (none) |
|
|
45
|
+
| `risk-reversal` | conversion | (native build) | sections:1 | icon, heading, body, link_label, link_url, background_color, text_color | (none) | (none) |
|
|
46
|
+
| `shipping-bar` | conversion | (native build) | sections:1 | threshold_cents, message_below, message_qualified, message_default, background_color, text_color | (none) | (none) |
|
|
47
|
+
| `sticky-atc` | conversion | Sticky Add To Cart Booster Pro and similar | sections:1 assets:1 | (none) | (none) | (none) |
|
|
48
|
+
| `subscriptions` | catalog | Recharge / Bold Subscriptions / Appstle for the storefront display layer; subscription management still uses Shopify's native customer account | snippets:1 | one_time_label, subscribe_label, fineprint | (none) | install-shopify-subscriptions + create-selling-plan-group + enable-customer-account-tab |
|
|
49
|
+
| `testimonials` | social-proof | (native build) | sections:1 | eyebrow, heading, background_color, text_color | (none) | (none) |
|
|
50
|
+
| `trust-badges` | social-proof | (native build) | sections:1 | background_color, text_color | (none) | (none) |
|
|
51
|
+
| `wishlist` | customer | Wishlist Plus, Wishlist King, Globo Wishlist | sections:1 snippets:1 assets:1 templates:1 | max_items | (none) | create-wishlist-page |
|
|
52
|
+
|
|
53
|
+
## Descriptions
|
|
54
|
+
|
|
55
|
+
### bundle-builder
|
|
56
|
+
|
|
57
|
+
- Category: catalog
|
|
58
|
+
- Replaces: BYOB-style bundle apps
|
|
59
|
+
- What: Build-your-own-bundle PDP section.
|
|
60
|
+
- Files: sections:1 assets:1
|
|
61
|
+
- Config: heading, sale_prefix, show_rating, rating_score, rating_count, show_trust_badges, trust_1, trust_2, trust_3, fomo_mode, fomo_cycle_days, fomo_stock_count
|
|
62
|
+
|
|
63
|
+
### cart-cross-sell
|
|
64
|
+
|
|
65
|
+
- Category: conversion
|
|
66
|
+
- Replaces: Rebuy / OneClickUpsell pre-purchase upsell
|
|
67
|
+
- What: Cart drawer cross-sell card.
|
|
68
|
+
- Files: snippets:1
|
|
69
|
+
- Config: eyebrow, cta_label
|
|
70
|
+
|
|
71
|
+
### cart-freeship-progress
|
|
72
|
+
|
|
73
|
+
- Category: conversion
|
|
74
|
+
- Replaces: Bold Free Shipping Manager and similar app features
|
|
75
|
+
- What: Cart drawer free-shipping progress bar.
|
|
76
|
+
- Files: snippets:1
|
|
77
|
+
- Config: threshold_cents, away_text, unlocked_message
|
|
78
|
+
|
|
79
|
+
### cart-usps
|
|
80
|
+
|
|
81
|
+
- Category: conversion
|
|
82
|
+
- What: Three brand promises listed at the bottom of the cart drawer.
|
|
83
|
+
- Files: snippets:1
|
|
84
|
+
- Config: icon, usp_1, usp_2, usp_3
|
|
85
|
+
|
|
86
|
+
### comparison-table
|
|
87
|
+
|
|
88
|
+
- Category: pdp
|
|
89
|
+
- Replaces: app-driven comparison widgets
|
|
90
|
+
- What: Comparison table section.
|
|
91
|
+
- Config: eyebrow, heading, lede, background_color, text_color
|
|
92
|
+
- Variants: feature-columns, feature-rows
|
|
93
|
+
|
|
94
|
+
### delivery-estimate
|
|
95
|
+
|
|
96
|
+
- Category: pdp
|
|
97
|
+
- What: delivery-estimate module migrated from Lushi.
|
|
98
|
+
- Files: snippets:1
|
|
99
|
+
|
|
100
|
+
### editorial-block
|
|
101
|
+
|
|
102
|
+
- Category: storefront
|
|
103
|
+
- What: Lushi editorial block module migrated from Lushi.
|
|
104
|
+
- Files: sections:1
|
|
105
|
+
- Config: eyebrow, heading, lede, background_color, text_color
|
|
106
|
+
|
|
107
|
+
### editorial-hero
|
|
108
|
+
|
|
109
|
+
- Category: storefront
|
|
110
|
+
- What: Lushi video hero module migrated from Lushi.
|
|
111
|
+
- Files: sections:1
|
|
112
|
+
- Config: eyebrow, heading, subheading, video_url, poster_image, min_height, button_label_primary, button_link_primary, button_label_secondary, button_link_secondary
|
|
113
|
+
|
|
114
|
+
### exit-intent
|
|
115
|
+
|
|
116
|
+
- Category: conversion
|
|
117
|
+
- What: Lushi exit popup module migrated from Lushi.
|
|
118
|
+
- Files: sections:1 assets:1
|
|
119
|
+
- Config: eyebrow, heading, lede
|
|
120
|
+
|
|
121
|
+
### faq
|
|
122
|
+
|
|
123
|
+
- Category: storefront
|
|
124
|
+
- What: Lushi FAQ module migrated from Lushi.
|
|
125
|
+
- Files: sections:1
|
|
126
|
+
- Config: eyebrow, heading, background_color, text_color
|
|
127
|
+
|
|
128
|
+
### gift-with-purchase
|
|
129
|
+
|
|
130
|
+
- Category: conversion
|
|
131
|
+
- What: Auto-add a gift product to the cart when total clears a threshold.
|
|
132
|
+
- Files: snippets:1 assets:1
|
|
133
|
+
- Config: threshold_cents, gift_handle, unlocked_message, locked_message_suffix
|
|
134
|
+
- Admin steps: create-gift-product + create-gift-discount
|
|
135
|
+
|
|
136
|
+
### how-it-works
|
|
137
|
+
|
|
138
|
+
- Category: storefront
|
|
139
|
+
- What: Lushi how it works module migrated from Lushi.
|
|
140
|
+
- Files: sections:1
|
|
141
|
+
- Config: eyebrow, heading, lede, image, asset_filename, background_color, text_color, cta_label, cta_link
|
|
142
|
+
|
|
143
|
+
### inventory-urgency
|
|
144
|
+
|
|
145
|
+
- Category: pdp
|
|
146
|
+
- What: inventory-urgency module migrated from Lushi.
|
|
147
|
+
- Files: snippets:1
|
|
148
|
+
|
|
149
|
+
### loyalty-tiers
|
|
150
|
+
|
|
151
|
+
- Category: customer
|
|
152
|
+
- What: Lifetime-spend tier card on the customer account page.
|
|
153
|
+
- Files: sections:1
|
|
154
|
+
- Config: tier_0_name, tier_1_name, tier_1_threshold, tier_1_perk_pct, tier_2_name, tier_2_threshold, tier_2_perk_pct
|
|
155
|
+
- Admin steps: create-tier-tags-and-flows + create-tier-discounts + add-tier-card-to-account
|
|
156
|
+
|
|
157
|
+
### pdp-ingredients
|
|
158
|
+
|
|
159
|
+
- Category: pdp
|
|
160
|
+
- What: Lushi ingredients module migrated from Lushi.
|
|
161
|
+
- Files: sections:1
|
|
162
|
+
- Config: eyebrow, heading, lede, background_color, text_color
|
|
163
|
+
|
|
164
|
+
### pdp-journal-link
|
|
165
|
+
|
|
166
|
+
- Category: pdp
|
|
167
|
+
- What: Lushi PDP journal link module migrated from Lushi.
|
|
168
|
+
- Files: sections:1
|
|
169
|
+
- Config: eyebrow, article, background_color, text_color, fallback_title, fallback_body, fallback_link_label, fallback_link_url
|
|
170
|
+
|
|
171
|
+
### pdp-trust-checks
|
|
172
|
+
|
|
173
|
+
- Category: pdp
|
|
174
|
+
- What: Lushi PDP trust module migrated from Lushi.
|
|
175
|
+
- Files: sections:1
|
|
176
|
+
- Config: eyebrow, heading, lede, background_color, text_color, link_label, link_url
|
|
177
|
+
|
|
178
|
+
### post-purchase-upsell
|
|
179
|
+
|
|
180
|
+
- Category: conversion
|
|
181
|
+
- Replaces: Reconvert / OneClickUpsell / AfterSell display layer
|
|
182
|
+
- What: Order status page upsell with auto-applied discount on click-through.
|
|
183
|
+
- Files: assets:2
|
|
184
|
+
- Config: discount_code, discount_label, max_items, heading, eyebrow, lede, cross_category_logic
|
|
185
|
+
- Admin steps: create-discount + paste-bootstrap
|
|
186
|
+
|
|
187
|
+
### press-bar
|
|
188
|
+
|
|
189
|
+
- Category: social-proof
|
|
190
|
+
- What: Lushi press bar module migrated from Lushi.
|
|
191
|
+
- Files: sections:1
|
|
192
|
+
- Config: eyebrow, background_color, text_color
|
|
193
|
+
|
|
194
|
+
### product-badges
|
|
195
|
+
|
|
196
|
+
- Category: social-proof
|
|
197
|
+
- What: Tag-driven badges on product cards (Best seller, New, Editor's pick).
|
|
198
|
+
- Files: snippets:1
|
|
199
|
+
- Config: label_best_seller, label_new, label_editor_pick
|
|
200
|
+
|
|
201
|
+
### quantity-breaks
|
|
202
|
+
|
|
203
|
+
- Category: catalog
|
|
204
|
+
- What: Tiered quantity-discount display on the PDP.
|
|
205
|
+
- Files: snippets:1
|
|
206
|
+
- Config: eyebrow, fineprint
|
|
207
|
+
- Admin steps: define-breaks-metafield + set-product-breaks + create-discount-function
|
|
208
|
+
|
|
209
|
+
### quick-view
|
|
210
|
+
|
|
211
|
+
- Category: conversion
|
|
212
|
+
- What: Modal product quick-view triggered from product cards.
|
|
213
|
+
- Files: snippets:2 assets:1
|
|
214
|
+
|
|
215
|
+
### recently-viewed
|
|
216
|
+
|
|
217
|
+
- Category: pdp
|
|
218
|
+
- What: Lushi recently viewed module migrated from Lushi.
|
|
219
|
+
- Files: sections:1 assets:1
|
|
220
|
+
- Config: eyebrow, heading, background_color
|
|
221
|
+
|
|
222
|
+
### reviews
|
|
223
|
+
|
|
224
|
+
- Category: social-proof
|
|
225
|
+
- What: Lushi PDP reviews module migrated from Lushi.
|
|
226
|
+
- Files: sections:1
|
|
227
|
+
- Config: heading
|
|
228
|
+
|
|
229
|
+
### risk-reversal
|
|
230
|
+
|
|
231
|
+
- Category: conversion
|
|
232
|
+
- What: Lushi risk reversal module migrated from Lushi.
|
|
233
|
+
- Files: sections:1
|
|
234
|
+
- Config: icon, heading, body, link_label, link_url, background_color, text_color
|
|
235
|
+
|
|
236
|
+
### shipping-bar
|
|
237
|
+
|
|
238
|
+
- Category: conversion
|
|
239
|
+
- What: Lushi shipping bar module migrated from Lushi.
|
|
240
|
+
- Files: sections:1
|
|
241
|
+
- Config: threshold_cents, message_below, message_qualified, message_default, background_color, text_color
|
|
242
|
+
|
|
243
|
+
### sticky-atc
|
|
244
|
+
|
|
245
|
+
- Category: conversion
|
|
246
|
+
- Replaces: Sticky Add To Cart Booster Pro and similar
|
|
247
|
+
- What: Sticky add-to-cart bar that slides up from the bottom on PDP after the buy area scrolls out of view.
|
|
248
|
+
- Files: sections:1 assets:1
|
|
249
|
+
|
|
250
|
+
### subscriptions
|
|
251
|
+
|
|
252
|
+
- Category: catalog
|
|
253
|
+
- Replaces: Recharge / Bold Subscriptions / Appstle for the storefront display layer; subscription management still uses Shopify's native customer account
|
|
254
|
+
- What: Brand-styled subscribe-and-save picker that wraps Shopify's native Selling Plan API.
|
|
255
|
+
- Files: snippets:1
|
|
256
|
+
- Config: one_time_label, subscribe_label, fineprint
|
|
257
|
+
- Admin steps: install-shopify-subscriptions + create-selling-plan-group + enable-customer-account-tab
|
|
258
|
+
|
|
259
|
+
### testimonials
|
|
260
|
+
|
|
261
|
+
- Category: social-proof
|
|
262
|
+
- What: Lushi testimonials module migrated from Lushi.
|
|
263
|
+
- Files: sections:1
|
|
264
|
+
- Config: eyebrow, heading, background_color, text_color
|
|
265
|
+
|
|
266
|
+
### trust-badges
|
|
267
|
+
|
|
268
|
+
- Category: social-proof
|
|
269
|
+
- What: Lushi trust badges module migrated from Lushi.
|
|
270
|
+
- Files: sections:1
|
|
271
|
+
- Config: background_color, text_color
|
|
272
|
+
|
|
273
|
+
### wishlist
|
|
274
|
+
|
|
275
|
+
- Category: customer
|
|
276
|
+
- Replaces: Wishlist Plus, Wishlist King, Globo Wishlist
|
|
277
|
+
- What: Native wishlist using localStorage.
|
|
278
|
+
- Files: sections:1 snippets:1 assets:1 templates:1
|
|
279
|
+
- Config: max_items
|
|
280
|
+
- Admin steps: create-wishlist-page
|
|
281
|
+
|
|
282
|
+
## How a skill should use this
|
|
283
|
+
|
|
284
|
+
1. Grep this file for keywords from the user request (e.g. "free shipping", "exit popup", "bundle").
|
|
285
|
+
2. If a row matches, run `node ~/Documents/Code/runwell-shopify-toolkit/bin/runwell-shopify add <module-name>` from the client theme directory.
|
|
286
|
+
3. Run `runwell-shopify sync` to copy files into the theme.
|
|
287
|
+
4. If the module has admin steps, hand them to shopify-admin-browser to drive merchant clicks.
|
|
288
|
+
5. Push: `shopify theme push` from the client theme directory.
|
|
@@ -1,50 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "comparison-table",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"category": "pdp",
|
|
5
|
-
"description": "
|
|
6
|
-
"
|
|
7
|
-
"sections": [
|
|
8
|
-
"sections/runwell-comparison-table.liquid"
|
|
9
|
-
]
|
|
10
|
-
},
|
|
5
|
+
"description": "Comparison table section. Two visual treatments: feature-columns (default) renders columns as Theme Editor blocks with a single textarea of pipe-delimited rows; feature-rows renders one Theme Editor block per comparison row in a 'us vs them' shape with two fixed brand columns. Replaces app-driven comparison widgets.",
|
|
6
|
+
"default_variant": "feature-columns",
|
|
11
7
|
"config": {
|
|
12
8
|
"schema": {
|
|
13
|
-
"eyebrow": {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"default": "We do not stock everything; here is what makes this one earn the spot.",
|
|
26
|
-
"label": "Lede"
|
|
27
|
-
},
|
|
28
|
-
"row_label_header": {
|
|
29
|
-
"type": "string",
|
|
30
|
-
"default": "What you get",
|
|
31
|
-
"label": "Row label header"
|
|
32
|
-
},
|
|
33
|
-
"rows": {
|
|
34
|
-
"type": "string",
|
|
35
|
-
"default": "Bioavailable form|yes|no|no\nDose matches research|yes|no|no\nThird-party tested|yes|yes|no\nClean ingredient deck|yes|no|no\nTransparent sourcing|yes|no|yes",
|
|
36
|
-
"label": "Rows"
|
|
9
|
+
"eyebrow": { "type": "string", "default": "Compared", "label": "Eyebrow" },
|
|
10
|
+
"heading": { "type": "string", "default": "How it stacks up.", "label": "Heading" },
|
|
11
|
+
"lede": { "type": "string", "default": "We do not stock everything; here is what makes this one earn the spot.", "label": "Lede" },
|
|
12
|
+
"background_color": { "type": "string", "default": "#F5F0EE", "label": "Background color" },
|
|
13
|
+
"text_color": { "type": "string", "default": "#0B3D38", "label": "Text color" }
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"variants": {
|
|
17
|
+
"feature-columns": {
|
|
18
|
+
"description": "Theme Editor blocks are columns (e.g. Lushi pick / Drugstore / Hype brand). Rows come from a textarea (pipe-delimited). Best when comparing many products across the same attributes.",
|
|
19
|
+
"files": {
|
|
20
|
+
"sections": ["variants/feature-columns/sections/runwell-comparison-table.liquid"]
|
|
37
21
|
},
|
|
38
|
-
"
|
|
39
|
-
"type": "string",
|
|
40
|
-
"default": "
|
|
41
|
-
|
|
22
|
+
"config_extra": {
|
|
23
|
+
"row_label_header": { "type": "string", "default": "What you get", "label": "Row label header" },
|
|
24
|
+
"rows": { "type": "string", "default": "Bioavailable form|yes|no|no\nDose matches research|yes|no|no\nThird-party tested|yes|yes|no\nClean ingredient deck|yes|no|no\nTransparent sourcing|yes|no|yes", "label": "Rows (pipe-delimited)" }
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"feature-rows": {
|
|
28
|
+
"description": "Theme Editor blocks are rows (one per feature). Two fixed columns: your brand vs one competitor. Best for 'us vs them' positioning on PDP or landing pages.",
|
|
29
|
+
"files": {
|
|
30
|
+
"sections": ["variants/feature-rows/sections/runwell-comparison-table.liquid"]
|
|
42
31
|
},
|
|
43
|
-
"
|
|
44
|
-
"type": "string",
|
|
45
|
-
"default": "
|
|
46
|
-
"label": "
|
|
32
|
+
"config_extra": {
|
|
33
|
+
"feature_label": { "type": "string", "default": "Feature", "label": "Feature column label" },
|
|
34
|
+
"brand_name": { "type": "string", "default": "Us", "label": "Your brand name" },
|
|
35
|
+
"competitor_name": { "type": "string", "default": "Traditional", "label": "Competitor name" }
|
|
47
36
|
}
|
|
48
37
|
}
|
|
49
38
|
}
|
|
50
|
-
}
|
|
39
|
+
}
|
package/modules/comparison-table/variants/feature-rows/sections/runwell-comparison-table.liquid
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
Comparison table, feature-rows variant. Each Theme Editor block is one
|
|
3
|
+
comparison row (feature + ours + theirs). Use when the brand wants a
|
|
4
|
+
"us vs them" pattern with a small fixed competitor set.
|
|
5
|
+
Original shape ported from Lusha (guabrasha-store/sections/comparison-table.liquid).
|
|
6
|
+
{%- endcomment -%}
|
|
7
|
+
|
|
8
|
+
<section
|
|
9
|
+
class="runwell-comparison runwell-comparison--feature-rows"
|
|
10
|
+
style="background: {{ section.settings.background_color }}; color: {{ section.settings.text_color }};"
|
|
11
|
+
>
|
|
12
|
+
<div style="max-width: 1200px; margin: 0 auto; padding: clamp(3rem, 6vw, 5rem) 6vw;">
|
|
13
|
+
{%- if section.settings.eyebrow != blank -%}
|
|
14
|
+
<div style="font-family: var(--font-body-family); font-size: 0.78rem; font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase; opacity: 0.65; margin-bottom: 0.6rem; text-align: center;">
|
|
15
|
+
{{ section.settings.eyebrow }}
|
|
16
|
+
</div>
|
|
17
|
+
{%- endif -%}
|
|
18
|
+
|
|
19
|
+
{%- if section.settings.heading != blank -%}
|
|
20
|
+
<h2 style="font-family: var(--font-heading-family); font-style: italic; font-weight: 400; font-size: clamp(1.8rem, 3.2vw, 2.6rem); line-height: 1.1; margin: 0 auto 1rem; max-width: 24ch; text-align: center;">
|
|
21
|
+
{{ section.settings.heading }}
|
|
22
|
+
</h2>
|
|
23
|
+
{%- endif -%}
|
|
24
|
+
|
|
25
|
+
{%- if section.settings.lede != blank -%}
|
|
26
|
+
<p style="font-family: var(--font-body-family); font-size: 1rem; line-height: 1.65; max-width: 60ch; opacity: 0.85; margin: 0 auto 2rem; text-align: center;">
|
|
27
|
+
{{ section.settings.lede }}
|
|
28
|
+
</p>
|
|
29
|
+
{%- endif -%}
|
|
30
|
+
|
|
31
|
+
{%- if section.blocks.size > 0 -%}
|
|
32
|
+
<div style="overflow-x: auto;">
|
|
33
|
+
<table style="width: 100%; border-collapse: collapse; min-width: 520px; font-family: var(--font-body-family); font-size: 0.95rem;">
|
|
34
|
+
<thead>
|
|
35
|
+
<tr>
|
|
36
|
+
<th style="text-align: left; padding: 0.9rem 1rem 0.9rem 0; font-family: var(--font-body-family); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; opacity: 0.6; vertical-align: bottom; border-bottom: 2px solid currentColor;">
|
|
37
|
+
{{ section.settings.feature_label }}
|
|
38
|
+
</th>
|
|
39
|
+
<th style="text-align: center; padding: 0.9rem 1rem; vertical-align: bottom; border-bottom: 2px solid currentColor;">
|
|
40
|
+
<div style="font-family: var(--font-heading-family); font-style: italic; font-weight: 400; font-size: 1.15rem; line-height: 1.2;">
|
|
41
|
+
{{ section.settings.brand_name }}
|
|
42
|
+
</div>
|
|
43
|
+
</th>
|
|
44
|
+
<th style="text-align: center; padding: 0.9rem 1rem; vertical-align: bottom; border-bottom: 2px solid currentColor;">
|
|
45
|
+
<div style="font-family: var(--font-heading-family); font-style: italic; font-weight: 400; font-size: 1.15rem; line-height: 1.2; opacity: 0.7;">
|
|
46
|
+
{{ section.settings.competitor_name }}
|
|
47
|
+
</div>
|
|
48
|
+
</th>
|
|
49
|
+
</tr>
|
|
50
|
+
</thead>
|
|
51
|
+
<tbody>
|
|
52
|
+
{%- for block in section.blocks -%}
|
|
53
|
+
<tr {{ block.shopify_attributes }}>
|
|
54
|
+
<td style="padding: 0.9rem 1rem 0.9rem 0; vertical-align: top; border-bottom: 1px solid rgba(0,0,0,0.08); font-weight: 600;">
|
|
55
|
+
{{ block.settings.feature }}
|
|
56
|
+
</td>
|
|
57
|
+
<td style="padding: 0.9rem 1rem; vertical-align: top; border-bottom: 1px solid rgba(0,0,0,0.08); text-align: center;">
|
|
58
|
+
{%- if block.settings.ours == 'yes' -%}
|
|
59
|
+
<span style="display: inline-block; min-width: 1.6rem; font-weight: 700; color: var(--runwell-rain-forrest, currentColor);">✓</span>
|
|
60
|
+
{%- elsif block.settings.ours == 'no' -%}
|
|
61
|
+
<span style="display: inline-block; min-width: 1.6rem; opacity: 0.4;">×</span>
|
|
62
|
+
{%- else -%}
|
|
63
|
+
<span style="opacity: 0.92;">{{ block.settings.ours_text }}</span>
|
|
64
|
+
{%- endif -%}
|
|
65
|
+
</td>
|
|
66
|
+
<td style="padding: 0.9rem 1rem; vertical-align: top; border-bottom: 1px solid rgba(0,0,0,0.08); text-align: center;">
|
|
67
|
+
{%- if block.settings.theirs == 'yes' -%}
|
|
68
|
+
<span style="display: inline-block; min-width: 1.6rem; font-weight: 700; opacity: 0.6;">✓</span>
|
|
69
|
+
{%- elsif block.settings.theirs == 'no' -%}
|
|
70
|
+
<span style="display: inline-block; min-width: 1.6rem; opacity: 0.4;">×</span>
|
|
71
|
+
{%- else -%}
|
|
72
|
+
<span style="opacity: 0.7;">{{ block.settings.theirs_text }}</span>
|
|
73
|
+
{%- endif -%}
|
|
74
|
+
</td>
|
|
75
|
+
</tr>
|
|
76
|
+
{%- endfor -%}
|
|
77
|
+
</tbody>
|
|
78
|
+
</table>
|
|
79
|
+
</div>
|
|
80
|
+
{%- endif -%}
|
|
81
|
+
</div>
|
|
82
|
+
</section>
|
|
83
|
+
|
|
84
|
+
{% schema %}
|
|
85
|
+
{
|
|
86
|
+
"name": "Runwell comparison (rows)",
|
|
87
|
+
"tag": "section",
|
|
88
|
+
"class": "section-runwell-comparison-rows",
|
|
89
|
+
"settings": [
|
|
90
|
+
{ "type": "text", "id": "eyebrow", "label": "Eyebrow", "default": "Compared" },
|
|
91
|
+
{ "type": "text", "id": "heading", "label": "Heading", "default": "How it stacks up." },
|
|
92
|
+
{ "type": "textarea", "id": "lede", "label": "Lede" },
|
|
93
|
+
{ "type": "text", "id": "feature_label", "label": "Feature column label", "default": "Feature" },
|
|
94
|
+
{ "type": "text", "id": "brand_name", "label": "Your brand name", "default": "Us" },
|
|
95
|
+
{ "type": "text", "id": "competitor_name", "label": "Competitor name", "default": "Traditional" },
|
|
96
|
+
{ "type": "color", "id": "background_color", "label": "Background", "default": "#F5F0EE" },
|
|
97
|
+
{ "type": "color", "id": "text_color", "label": "Text", "default": "#0B3D38" }
|
|
98
|
+
],
|
|
99
|
+
"blocks": [
|
|
100
|
+
{
|
|
101
|
+
"type": "row",
|
|
102
|
+
"name": "Comparison row",
|
|
103
|
+
"settings": [
|
|
104
|
+
{ "type": "text", "id": "feature", "label": "Feature" },
|
|
105
|
+
{
|
|
106
|
+
"type": "select",
|
|
107
|
+
"id": "ours",
|
|
108
|
+
"label": "Your brand",
|
|
109
|
+
"options": [
|
|
110
|
+
{ "value": "yes", "label": "Yes" },
|
|
111
|
+
{ "value": "no", "label": "No" },
|
|
112
|
+
{ "value": "custom", "label": "Custom text" }
|
|
113
|
+
],
|
|
114
|
+
"default": "yes"
|
|
115
|
+
},
|
|
116
|
+
{ "type": "text", "id": "ours_text", "label": "Custom text (yours)" },
|
|
117
|
+
{
|
|
118
|
+
"type": "select",
|
|
119
|
+
"id": "theirs",
|
|
120
|
+
"label": "Competitor",
|
|
121
|
+
"options": [
|
|
122
|
+
{ "value": "yes", "label": "Yes" },
|
|
123
|
+
{ "value": "no", "label": "No" },
|
|
124
|
+
{ "value": "custom", "label": "Custom text" }
|
|
125
|
+
],
|
|
126
|
+
"default": "no"
|
|
127
|
+
},
|
|
128
|
+
{ "type": "text", "id": "theirs_text", "label": "Custom text (theirs)" }
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
"presets": [
|
|
133
|
+
{
|
|
134
|
+
"name": "Runwell comparison (rows)",
|
|
135
|
+
"blocks": [
|
|
136
|
+
{ "type": "row", "settings": { "feature": "Bioavailable form", "ours": "yes", "theirs": "no" } },
|
|
137
|
+
{ "type": "row", "settings": { "feature": "Third-party tested", "ours": "yes", "theirs": "no" } },
|
|
138
|
+
{ "type": "row", "settings": { "feature": "Transparent sourcing", "ours": "yes", "theirs": "no" } }
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
{% endschema %}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/* Runwell sticky add-to-cart bar.
|
|
2
|
+
Slides up from bottom on scroll past the buy area; hides when the
|
|
3
|
+
main buy button returns to view (driven by IntersectionObserver in
|
|
4
|
+
the section template).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
.runwell-sticky-atc {
|
|
8
|
+
position: fixed;
|
|
9
|
+
inset: auto 0 0 0;
|
|
10
|
+
z-index: 60;
|
|
11
|
+
background: #FFFFFF;
|
|
12
|
+
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
|
13
|
+
box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.06);
|
|
14
|
+
transform: translateY(100%);
|
|
15
|
+
transition: transform 0.25s ease, opacity 0.25s ease;
|
|
16
|
+
opacity: 0;
|
|
17
|
+
visibility: hidden;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.runwell-sticky-atc[aria-hidden='false'] {
|
|
21
|
+
transform: translateY(0);
|
|
22
|
+
opacity: 1;
|
|
23
|
+
visibility: visible;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.runwell-sticky-atc__inner {
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
justify-content: space-between;
|
|
30
|
+
gap: 1rem;
|
|
31
|
+
max-width: 1200px;
|
|
32
|
+
margin: 0 auto;
|
|
33
|
+
padding: 0.75rem 1.25rem;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.runwell-sticky-atc__product {
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
gap: 0.75rem;
|
|
40
|
+
min-width: 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.runwell-sticky-atc__thumb {
|
|
44
|
+
width: 40px;
|
|
45
|
+
height: 40px;
|
|
46
|
+
border-radius: 4px;
|
|
47
|
+
object-fit: cover;
|
|
48
|
+
flex-shrink: 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.runwell-sticky-atc__meta {
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-direction: column;
|
|
54
|
+
min-width: 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.runwell-sticky-atc__title {
|
|
58
|
+
font-family: var(--font-heading-family, serif);
|
|
59
|
+
font-style: italic;
|
|
60
|
+
font-size: 0.95rem;
|
|
61
|
+
font-weight: 400;
|
|
62
|
+
line-height: 1.2;
|
|
63
|
+
color: var(--runwell-primary, #1A1A1A);
|
|
64
|
+
white-space: nowrap;
|
|
65
|
+
overflow: hidden;
|
|
66
|
+
text-overflow: ellipsis;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.runwell-sticky-atc__price {
|
|
70
|
+
font-family: var(--font-body-family, sans-serif);
|
|
71
|
+
font-size: 0.85rem;
|
|
72
|
+
font-weight: 500;
|
|
73
|
+
color: var(--runwell-primary, #1A1A1A);
|
|
74
|
+
opacity: 0.8;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.runwell-sticky-atc__form {
|
|
78
|
+
flex-shrink: 0;
|
|
79
|
+
margin: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.runwell-sticky-atc__cta {
|
|
83
|
+
background: var(--runwell-primary, #1A1A1A);
|
|
84
|
+
color: #FFFFFF;
|
|
85
|
+
border: none;
|
|
86
|
+
border-radius: 0;
|
|
87
|
+
padding: 0.75rem 1.5rem;
|
|
88
|
+
font-family: var(--font-body-family, sans-serif);
|
|
89
|
+
font-size: 0.9rem;
|
|
90
|
+
font-weight: 600;
|
|
91
|
+
letter-spacing: 0.04em;
|
|
92
|
+
text-transform: uppercase;
|
|
93
|
+
cursor: pointer;
|
|
94
|
+
transition: opacity 0.15s ease;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.runwell-sticky-atc__cta:hover {
|
|
98
|
+
opacity: 0.85;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.runwell-sticky-atc__cta:disabled {
|
|
102
|
+
opacity: 0.5;
|
|
103
|
+
cursor: not-allowed;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@media (max-width: 749px) {
|
|
107
|
+
.runwell-sticky-atc__inner {
|
|
108
|
+
padding: 0.6rem 0.9rem;
|
|
109
|
+
}
|
|
110
|
+
.runwell-sticky-atc__title {
|
|
111
|
+
font-size: 0.85rem;
|
|
112
|
+
}
|
|
113
|
+
.runwell-sticky-atc__cta {
|
|
114
|
+
padding: 0.6rem 1.1rem;
|
|
115
|
+
font-size: 0.8rem;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sticky-atc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"category": "conversion",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Sticky add-to-cart bar that slides up from the bottom on PDP after the buy area scrolls out of view. Native, no app. Replaces Sticky Add To Cart Booster Pro and similar.",
|
|
6
6
|
"files": {
|
|
7
7
|
"sections": [
|
|
8
8
|
"sections/runwell-pdp-sticky.liquid"
|
|
9
|
+
],
|
|
10
|
+
"assets": [
|
|
11
|
+
"assets/runwell-sticky-atc.css"
|
|
9
12
|
]
|
|
10
13
|
},
|
|
11
14
|
"config": {
|
|
12
15
|
"schema": {}
|
|
13
16
|
}
|
|
14
|
-
}
|
|
17
|
+
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
{%- endcomment -%}
|
|
6
6
|
|
|
7
7
|
{%- if template == 'product' and product != blank -%}
|
|
8
|
+
{{ 'runwell-sticky-atc.css' | asset_url | stylesheet_tag }}
|
|
8
9
|
<div class="runwell-sticky-atc" data-runwell-sticky aria-hidden="true">
|
|
9
10
|
<div class="runwell-sticky-atc__inner">
|
|
10
11
|
<div class="runwell-sticky-atc__product">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runwell/shopify-toolkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Reusable Shopify theme modules from Runwell. Replaces typically app-driven features (reviews, wishlist, urgency, FAQ, post-purchase upsell, exit popups, free-ship progress, sticky ATC, testimonials, badges, bundles) with native Liquid + JS + CSS that ship across multiple client themes via a config-driven sync CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
File without changes
|