@runwell/shopify-toolkit 0.2.0 → 0.4.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.
- package/modules/INDEX.md +287 -0
- package/modules/bundle-builder/README.md +40 -0
- package/modules/bundle-builder/assets/runwell-bundle-builder.css +383 -0
- package/modules/bundle-builder/module.json +26 -0
- package/modules/bundle-builder/sections/runwell-bundle-builder.liquid +370 -0
- package/modules/comparison-table/module.json +29 -40
- package/modules/comparison-table/variants/feature-rows/sections/runwell-comparison-table.liquid +143 -0
- package/package.json +1 -1
- /package/modules/comparison-table/{sections → variants/feature-columns/sections}/runwell-comparison-table.liquid +0 -0
package/modules/INDEX.md
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
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 | (native build) | sections: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
|
+
- What: Lushi sticky ATC module migrated from Lushi.
|
|
247
|
+
- Files: sections:1
|
|
248
|
+
|
|
249
|
+
### subscriptions
|
|
250
|
+
|
|
251
|
+
- Category: catalog
|
|
252
|
+
- Replaces: Recharge / Bold Subscriptions / Appstle for the storefront display layer; subscription management still uses Shopify's native customer account
|
|
253
|
+
- What: Brand-styled subscribe-and-save picker that wraps Shopify's native Selling Plan API.
|
|
254
|
+
- Files: snippets:1
|
|
255
|
+
- Config: one_time_label, subscribe_label, fineprint
|
|
256
|
+
- Admin steps: install-shopify-subscriptions + create-selling-plan-group + enable-customer-account-tab
|
|
257
|
+
|
|
258
|
+
### testimonials
|
|
259
|
+
|
|
260
|
+
- Category: social-proof
|
|
261
|
+
- What: Lushi testimonials module migrated from Lushi.
|
|
262
|
+
- Files: sections:1
|
|
263
|
+
- Config: eyebrow, heading, background_color, text_color
|
|
264
|
+
|
|
265
|
+
### trust-badges
|
|
266
|
+
|
|
267
|
+
- Category: social-proof
|
|
268
|
+
- What: Lushi trust badges module migrated from Lushi.
|
|
269
|
+
- Files: sections:1
|
|
270
|
+
- Config: background_color, text_color
|
|
271
|
+
|
|
272
|
+
### wishlist
|
|
273
|
+
|
|
274
|
+
- Category: customer
|
|
275
|
+
- Replaces: Wishlist Plus, Wishlist King, Globo Wishlist
|
|
276
|
+
- What: Native wishlist using localStorage.
|
|
277
|
+
- Files: sections:1 snippets:1 assets:1 templates:1
|
|
278
|
+
- Config: max_items
|
|
279
|
+
- Admin steps: create-wishlist-page
|
|
280
|
+
|
|
281
|
+
## How a skill should use this
|
|
282
|
+
|
|
283
|
+
1. Grep this file for keywords from the user request (e.g. "free shipping", "exit popup", "bundle").
|
|
284
|
+
2. If a row matches, run `node ~/Documents/Code/runwell-shopify-toolkit/bin/runwell-shopify add <module-name>` from the client theme directory.
|
|
285
|
+
3. Run `runwell-shopify sync` to copy files into the theme.
|
|
286
|
+
4. If the module has admin steps, hand them to shopify-admin-browser to drive merchant clicks.
|
|
287
|
+
5. Push: `shopify theme push` from the client theme directory.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# bundle-builder
|
|
2
|
+
|
|
3
|
+
PDP section for build-your-own-bundle merchandising. Slideshow gallery + thumbnail nav + radio bundle picker (1x / 2x / 3x with savings, free-ship and free-gift badges) + sticky ATC + FOMO countdown + scarcity. Migrated from Lusha's bundle-selector.
|
|
4
|
+
|
|
5
|
+
## Files
|
|
6
|
+
|
|
7
|
+
- `sections/runwell-bundle-builder.liquid`. Section template (392 lines).
|
|
8
|
+
- `assets/runwell-bundle-builder.css`. ~370 lines of styling, brand-aware via `var(--runwell-*)`.
|
|
9
|
+
|
|
10
|
+
## Behaviour
|
|
11
|
+
|
|
12
|
+
- **Gallery**: configurable via section blocks of type `gallery_image`. If no images set, falls back to the product's featured image, then to a brand-coloured placeholder.
|
|
13
|
+
- **Thumbnails**: clickable navigation between gallery images.
|
|
14
|
+
- **Bundle options**: configurable via section blocks of type `bundle_option`. Each one shows: title, price, compare-at price, savings badge, free-ship badge, "MOST POPULAR" highlight, free-gift text.
|
|
15
|
+
- **FOMO mode**: `discount` (countdown to sale end), `scarcity` (low-stock count), `both`, or `none`. The deadline rotates on a configurable cycle so it never expires for a returning visitor.
|
|
16
|
+
- **Trust badges**: 3 configurable promise lines below the ATC.
|
|
17
|
+
- **ATC**: posts to `/cart/add.js` with quantity parsed from the title (`"3x Product"` adds qty 3).
|
|
18
|
+
|
|
19
|
+
## How to use
|
|
20
|
+
|
|
21
|
+
1. Sync: `runwell-shopify sync`
|
|
22
|
+
2. In any product template (or a custom landing page), add the section "Runwell Bundle Builder"
|
|
23
|
+
3. Inside the section, add `gallery_image` blocks for product photography
|
|
24
|
+
4. Add `bundle_option` blocks for each bundle tier (typically 3 with the middle marked "popular")
|
|
25
|
+
5. Configure FOMO mode if desired
|
|
26
|
+
6. Style further via the brand's `--runwell-*` CSS custom properties
|
|
27
|
+
|
|
28
|
+
## Lineage
|
|
29
|
+
|
|
30
|
+
Migrated from `guabrasha-store/sections/bundle-selector.liquid` (Lusha gua sha brand). Class prefix renamed from `bundle-selector` to `runwell-bundle-builder`. Lusha-specific hardcoded gallery filenames replaced with a placeholder pattern. Lusha-specific copy ("Lusha Sculpting Brush", "Spring Sculpting Sale") replaced with generic defaults that the merchant overrides via section settings.
|
|
31
|
+
|
|
32
|
+
## Replaces
|
|
33
|
+
|
|
34
|
+
Bundle Builder, BYOB Bundles by Pickystory, Bundler. The toolkit version is display + ATC only; if you need true bundle-as-SKU pricing the merchant should pair this with a Shopify Functions discount.
|
|
35
|
+
|
|
36
|
+
## Future variants
|
|
37
|
+
|
|
38
|
+
- `step-by-step` (single-product, multi-step BYOB walkthrough)
|
|
39
|
+
- `mix-and-match` (any 3 from a curated set)
|
|
40
|
+
- `subscription-bundle` (bundle with subscription price option)
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
.runwell-bundle-builder__grid {
|
|
2
|
+
display: grid;
|
|
3
|
+
grid-template-columns: 1fr 1fr;
|
|
4
|
+
gap: 2.4rem;
|
|
5
|
+
align-items: start;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/* Slideshow Gallery */
|
|
9
|
+
.runwell-bundle-builder__slideshow {
|
|
10
|
+
position: relative;
|
|
11
|
+
border-radius: 12px;
|
|
12
|
+
overflow: hidden;
|
|
13
|
+
background: #E8D5C4;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.runwell-bundle-builder__slide {
|
|
17
|
+
display: none;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.runwell-bundle-builder__slide--active {
|
|
21
|
+
display: block;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.runwell-bundle-builder__img {
|
|
25
|
+
width: 100%;
|
|
26
|
+
height: auto;
|
|
27
|
+
display: block;
|
|
28
|
+
aspect-ratio: 1 / 1;
|
|
29
|
+
object-fit: cover;
|
|
30
|
+
max-height: calc(100vh - 260px);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Thumbnail Strip - ALWAYS visible including mobile */
|
|
34
|
+
.runwell-bundle-builder__thumbnails {
|
|
35
|
+
display: flex;
|
|
36
|
+
gap: 8px;
|
|
37
|
+
margin-top: 12px;
|
|
38
|
+
overflow-x: auto;
|
|
39
|
+
scrollbar-width: thin;
|
|
40
|
+
scrollbar-color: #EADFD4 transparent;
|
|
41
|
+
padding-bottom: 4px;
|
|
42
|
+
-webkit-overflow-scrolling: touch;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.runwell-bundle-builder__thumbnails::-webkit-scrollbar {
|
|
46
|
+
height: 4px;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.runwell-bundle-builder__thumbnails::-webkit-scrollbar-thumb {
|
|
50
|
+
background: #EADFD4;
|
|
51
|
+
border-radius: 2px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.runwell-bundle-builder__thumb {
|
|
55
|
+
flex: 0 0 72px;
|
|
56
|
+
height: 72px;
|
|
57
|
+
border-radius: 8px;
|
|
58
|
+
overflow: hidden;
|
|
59
|
+
border: 2px solid transparent;
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
padding: 0;
|
|
62
|
+
background: #E8D5C4;
|
|
63
|
+
transition: border-color 0.2s, opacity 0.2s;
|
|
64
|
+
opacity: 0.7;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.runwell-bundle-builder__thumb--active {
|
|
68
|
+
border-color: #3F5B4C;
|
|
69
|
+
opacity: 1;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.runwell-bundle-builder__thumb:hover {
|
|
73
|
+
opacity: 1;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.runwell-bundle-builder__thumb img {
|
|
77
|
+
width: 100%;
|
|
78
|
+
height: 100%;
|
|
79
|
+
object-fit: cover;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Rating */
|
|
83
|
+
.runwell-bundle-builder__rating {
|
|
84
|
+
display: flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
gap: 8px;
|
|
87
|
+
margin-bottom: 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.runwell-bundle-builder__stars {
|
|
91
|
+
color: #E8B931;
|
|
92
|
+
font-size: 1.6rem;
|
|
93
|
+
letter-spacing: 1px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.runwell-bundle-builder__rating-text {
|
|
97
|
+
font-size: 1.4rem;
|
|
98
|
+
font-weight: 600;
|
|
99
|
+
font-style: italic;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Title */
|
|
103
|
+
.runwell-bundle-builder__title {
|
|
104
|
+
margin-top: 0.4rem;
|
|
105
|
+
margin-bottom: 1rem;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Sale heading */
|
|
109
|
+
.runwell-bundle-builder__sale-heading {
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
gap: 1.2rem;
|
|
113
|
+
margin-bottom: 1.2rem;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.runwell-bundle-builder__sale-line {
|
|
117
|
+
flex: 1;
|
|
118
|
+
height: 1px;
|
|
119
|
+
background: #2A2622;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.runwell-bundle-builder__sale-text {
|
|
123
|
+
font-weight: 700;
|
|
124
|
+
font-size: 1.5rem;
|
|
125
|
+
white-space: nowrap;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Scarcity indicator */
|
|
129
|
+
.runwell-bundle-builder__scarcity {
|
|
130
|
+
display: flex;
|
|
131
|
+
align-items: center;
|
|
132
|
+
justify-content: center;
|
|
133
|
+
gap: 6px;
|
|
134
|
+
font-size: 1.3rem;
|
|
135
|
+
font-weight: 500;
|
|
136
|
+
color: #b45309;
|
|
137
|
+
margin-bottom: 1rem;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.runwell-bundle-builder__scarcity-dot {
|
|
141
|
+
width: 8px;
|
|
142
|
+
height: 8px;
|
|
143
|
+
border-radius: 50%;
|
|
144
|
+
background: #b45309;
|
|
145
|
+
animation: scarcity-pulse 2s ease-in-out infinite;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@keyframes scarcity-pulse {
|
|
149
|
+
0%, 100% { opacity: 1; }
|
|
150
|
+
50% { opacity: 0.4; }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Options */
|
|
154
|
+
.runwell-bundle-builder__options {
|
|
155
|
+
display: flex;
|
|
156
|
+
flex-direction: column;
|
|
157
|
+
gap: 10px;
|
|
158
|
+
margin-bottom: 1.2rem;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.runwell-bundle-builder__option {
|
|
162
|
+
display: flex;
|
|
163
|
+
align-items: flex-start;
|
|
164
|
+
gap: 12px;
|
|
165
|
+
padding: 14px 18px;
|
|
166
|
+
border: 2px solid #EADFD4;
|
|
167
|
+
border-radius: 10px;
|
|
168
|
+
cursor: pointer;
|
|
169
|
+
transition: border-color 0.2s, box-shadow 0.2s;
|
|
170
|
+
position: relative;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.runwell-bundle-builder__option:hover {
|
|
174
|
+
border-color: #3F5B4C;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.runwell-bundle-builder__option--selected {
|
|
178
|
+
border-color: #2A2622;
|
|
179
|
+
box-shadow: 0 0 0 1px #2A2622;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.runwell-bundle-builder__option--popular {
|
|
183
|
+
border-color: #3F5B4C;
|
|
184
|
+
position: relative;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.runwell-bundle-builder__popular-badge {
|
|
188
|
+
position: absolute;
|
|
189
|
+
top: -10px;
|
|
190
|
+
right: 16px;
|
|
191
|
+
background: #3F5B4C;
|
|
192
|
+
color: #fff;
|
|
193
|
+
font-size: 1.0rem;
|
|
194
|
+
font-weight: 700;
|
|
195
|
+
padding: 2px 10px;
|
|
196
|
+
border-radius: 4px;
|
|
197
|
+
letter-spacing: 0.06em;
|
|
198
|
+
text-transform: uppercase;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.runwell-bundle-builder__option input {
|
|
202
|
+
position: absolute;
|
|
203
|
+
opacity: 0;
|
|
204
|
+
pointer-events: none;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.runwell-bundle-builder__option-radio {
|
|
208
|
+
width: 22px;
|
|
209
|
+
height: 22px;
|
|
210
|
+
border-radius: 50%;
|
|
211
|
+
border: 2px solid #EADFD4;
|
|
212
|
+
flex-shrink: 0;
|
|
213
|
+
margin-top: 2px;
|
|
214
|
+
display: flex;
|
|
215
|
+
align-items: center;
|
|
216
|
+
justify-content: center;
|
|
217
|
+
transition: border-color 0.2s;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.runwell-bundle-builder__option--selected .runwell-bundle-builder__option-radio {
|
|
221
|
+
border-color: #2A2622;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.runwell-bundle-builder__option--selected .runwell-bundle-builder__option-radio::after {
|
|
225
|
+
content: '';
|
|
226
|
+
width: 12px;
|
|
227
|
+
height: 12px;
|
|
228
|
+
border-radius: 50%;
|
|
229
|
+
background: #2A2622;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.runwell-bundle-builder__option-content {
|
|
233
|
+
flex: 1;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.runwell-bundle-builder__option-header {
|
|
237
|
+
display: flex;
|
|
238
|
+
justify-content: space-between;
|
|
239
|
+
align-items: baseline;
|
|
240
|
+
gap: 12px;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.runwell-bundle-builder__option-title {
|
|
244
|
+
font-weight: 700;
|
|
245
|
+
font-size: 1.5rem;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.runwell-bundle-builder__option-pricing {
|
|
249
|
+
display: flex;
|
|
250
|
+
align-items: baseline;
|
|
251
|
+
gap: 8px;
|
|
252
|
+
flex-shrink: 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.runwell-bundle-builder__option-price {
|
|
256
|
+
font-weight: 700;
|
|
257
|
+
font-size: 1.8rem;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.runwell-bundle-builder__option-compare {
|
|
261
|
+
font-size: 1.3rem;
|
|
262
|
+
text-decoration: line-through;
|
|
263
|
+
opacity: 0.5;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.runwell-bundle-builder__option-badges {
|
|
267
|
+
display: flex;
|
|
268
|
+
gap: 6px;
|
|
269
|
+
margin-top: 6px;
|
|
270
|
+
flex-wrap: wrap;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.runwell-bundle-builder__badge {
|
|
274
|
+
font-size: 1.1rem;
|
|
275
|
+
font-weight: 700;
|
|
276
|
+
padding: 2px 8px;
|
|
277
|
+
border-radius: 4px;
|
|
278
|
+
text-transform: uppercase;
|
|
279
|
+
letter-spacing: 0.03em;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.runwell-bundle-builder__badge--save {
|
|
283
|
+
background: #3F5B4C;
|
|
284
|
+
color: #fff;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.runwell-bundle-builder__badge--shipping {
|
|
288
|
+
color: #3F5B4C;
|
|
289
|
+
font-weight: 600;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.runwell-bundle-builder__free-gift {
|
|
293
|
+
display: flex;
|
|
294
|
+
align-items: center;
|
|
295
|
+
gap: 6px;
|
|
296
|
+
margin-top: 8px;
|
|
297
|
+
padding: 8px 12px;
|
|
298
|
+
background: rgba(63, 91, 76, 0.06);
|
|
299
|
+
border-radius: 6px;
|
|
300
|
+
font-size: 1.3rem;
|
|
301
|
+
font-weight: 600;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.runwell-bundle-builder__gift-icon {
|
|
305
|
+
font-size: 1.6rem;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/* ATC Button */
|
|
309
|
+
.runwell-bundle-builder__atc {
|
|
310
|
+
width: 100%;
|
|
311
|
+
padding: 1.6rem;
|
|
312
|
+
font-size: 1.6rem;
|
|
313
|
+
font-weight: 700;
|
|
314
|
+
letter-spacing: 0.06em;
|
|
315
|
+
text-transform: uppercase;
|
|
316
|
+
background: #2A2622;
|
|
317
|
+
color: #fff;
|
|
318
|
+
border: none;
|
|
319
|
+
border-radius: 8px;
|
|
320
|
+
cursor: pointer;
|
|
321
|
+
transition: background 0.2s;
|
|
322
|
+
margin-bottom: 1.2rem;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.runwell-bundle-builder__atc:hover {
|
|
326
|
+
background: #3F5B4C;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/* Trust badges */
|
|
330
|
+
.runwell-bundle-builder__trust {
|
|
331
|
+
display: flex;
|
|
332
|
+
justify-content: center;
|
|
333
|
+
gap: 2rem;
|
|
334
|
+
font-size: 1.3rem;
|
|
335
|
+
opacity: 0.7;
|
|
336
|
+
flex-wrap: wrap;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* Sticky ATC on mobile */
|
|
340
|
+
@media screen and (max-width: 989px) {
|
|
341
|
+
.runwell-bundle-builder__grid {
|
|
342
|
+
grid-template-columns: 1fr;
|
|
343
|
+
gap: 2rem;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.runwell-bundle-builder__atc-wrap {
|
|
347
|
+
position: sticky;
|
|
348
|
+
bottom: 0;
|
|
349
|
+
z-index: 10;
|
|
350
|
+
background: #fff;
|
|
351
|
+
padding: 12px 0 max(12px, env(safe-area-inset-bottom));
|
|
352
|
+
box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.08);
|
|
353
|
+
margin: 0 -1.5rem;
|
|
354
|
+
padding-left: 1.5rem;
|
|
355
|
+
padding-right: 1.5rem;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
@media screen and (max-width: 749px) {
|
|
360
|
+
.runwell-bundle-builder__option-header {
|
|
361
|
+
flex-direction: column;
|
|
362
|
+
gap: 4px;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.runwell-bundle-builder__trust {
|
|
366
|
+
flex-direction: column;
|
|
367
|
+
align-items: center;
|
|
368
|
+
gap: 0.6rem;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/* Runwell additions: placeholder states when gallery is empty */
|
|
373
|
+
.runwell-bundle-builder__img--placeholder,
|
|
374
|
+
.runwell-bundle-builder__thumb-img--placeholder {
|
|
375
|
+
width: 100%;
|
|
376
|
+
height: 100%;
|
|
377
|
+
min-height: 320px;
|
|
378
|
+
background: linear-gradient(135deg, var(--runwell-oat, #F5F0EE), var(--runwell-cream, #EDE6D8));
|
|
379
|
+
display: block;
|
|
380
|
+
}
|
|
381
|
+
.runwell-bundle-builder__thumb-img--placeholder {
|
|
382
|
+
min-height: 0;
|
|
383
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bundle-builder",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"category": "catalog",
|
|
5
|
+
"description": "Build-your-own-bundle PDP section. Slideshow gallery + thumbnail nav + radio bundle picker (1x / 2x / 3x with savings, free-ship and free-gift badges) + sticky ATC + FOMO countdown + scarcity. Migrated from Lusha (guabrasha-store/sections/bundle-selector.liquid). Replaces BYOB-style bundle apps.",
|
|
6
|
+
"files": {
|
|
7
|
+
"sections": ["sections/runwell-bundle-builder.liquid"],
|
|
8
|
+
"assets": ["assets/runwell-bundle-builder.css"]
|
|
9
|
+
},
|
|
10
|
+
"config": {
|
|
11
|
+
"schema": {
|
|
12
|
+
"heading": { "type": "string", "default": "Build your bundle" },
|
|
13
|
+
"sale_prefix": { "type": "string", "default": "Limited time offer" },
|
|
14
|
+
"show_rating": { "type": "boolean", "default": true },
|
|
15
|
+
"rating_score": { "type": "string", "default": "4.8/5" },
|
|
16
|
+
"rating_count": { "type": "string", "default": "2,400+" },
|
|
17
|
+
"show_trust_badges": { "type": "boolean", "default": true },
|
|
18
|
+
"trust_1": { "type": "string", "default": "90-Day Guarantee" },
|
|
19
|
+
"trust_2": { "type": "string", "default": "Easy Returns" },
|
|
20
|
+
"trust_3": { "type": "string", "default": "Free Shipping" },
|
|
21
|
+
"fomo_mode": { "type": "string", "default": "both", "enum": ["discount", "scarcity", "both", "none"] },
|
|
22
|
+
"fomo_cycle_days": { "type": "number", "default": 30 },
|
|
23
|
+
"fomo_stock_count": { "type": "number", "default": 47 }
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
{{ 'runwell-bundle-builder.css' | asset_url | stylesheet_tag }}
|
|
2
|
+
|
|
3
|
+
<div class="runwell-bundle-builder color-{{ section.settings.color_scheme }} section-{{ section.id }}-padding">
|
|
4
|
+
<div class="page-width">
|
|
5
|
+
<div class="runwell-bundle-builder__grid">
|
|
6
|
+
<div class="runwell-bundle-builder__media">
|
|
7
|
+
{%- assign gallery_images = section.blocks | where: "type", "gallery_image" -%}
|
|
8
|
+
{%- if gallery_images.size > 0 -%}
|
|
9
|
+
<div class="runwell-bundle-builder__slideshow" data-slideshow>
|
|
10
|
+
{%- for block in gallery_images -%}
|
|
11
|
+
<div class="runwell-bundle-builder__slide {% if forloop.first %}runwell-bundle-builder__slide--active{% endif %}" data-slide="{{ forloop.index0 }}" {{ block.shopify_attributes }}>
|
|
12
|
+
{%- if block.settings.image != blank -%}
|
|
13
|
+
{{ block.settings.image | image_url: width: 800 | image_tag: class: 'runwell-bundle-builder__img', loading: forloop.first | default: 'eager', sizes: '(min-width: 990px) 50vw, 100vw' }}
|
|
14
|
+
{%- else -%}
|
|
15
|
+
<div class="runwell-bundle-builder__img runwell-bundle-builder__img--placeholder" aria-label="Image placeholder"></div>
|
|
16
|
+
{%- endif -%}
|
|
17
|
+
</div>
|
|
18
|
+
{%- endfor -%}
|
|
19
|
+
</div>
|
|
20
|
+
<div class="runwell-bundle-builder__thumbnails" data-thumbnails>
|
|
21
|
+
{%- for block in gallery_images -%}
|
|
22
|
+
<button class="runwell-bundle-builder__thumb {% if forloop.first %}runwell-bundle-builder__thumb--active{% endif %}" data-thumb="{{ forloop.index0 }}" aria-label="View image {{ forloop.index }}">
|
|
23
|
+
{%- if block.settings.image != blank -%}
|
|
24
|
+
{{ block.settings.image | image_url: width: 120, height: 120, crop: 'center' | image_tag: loading: 'lazy' }}
|
|
25
|
+
{%- else -%}
|
|
26
|
+
<div class="runwell-bundle-builder__thumb-img runwell-bundle-builder__thumb-img--placeholder" aria-label="Thumbnail placeholder"></div>
|
|
27
|
+
{%- endif -%}
|
|
28
|
+
</button>
|
|
29
|
+
{%- endfor -%}
|
|
30
|
+
</div>
|
|
31
|
+
{%- else -%}
|
|
32
|
+
<div class="runwell-bundle-builder__slideshow runwell-bundle-builder__slideshow--empty" data-slideshow>
|
|
33
|
+
<div class="runwell-bundle-builder__slide runwell-bundle-builder__slide--active" data-slide="0">
|
|
34
|
+
{%- if section.settings.product.featured_image != blank -%}
|
|
35
|
+
{{ section.settings.product.featured_image | image_url: width: 800 | image_tag: class: 'runwell-bundle-builder__img', loading: 'eager', alt: section.settings.product.title }}
|
|
36
|
+
{%- else -%}
|
|
37
|
+
<div class="runwell-bundle-builder__img runwell-bundle-builder__img--placeholder" aria-label="Add gallery images via the section editor"></div>
|
|
38
|
+
{%- endif -%}
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
{%- endif -%}
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div class="runwell-bundle-builder__info">
|
|
45
|
+
{% if section.settings.show_rating %}
|
|
46
|
+
<div class="runwell-bundle-builder__rating">
|
|
47
|
+
<span class="runwell-bundle-builder__stars">★★★★★</span>
|
|
48
|
+
<span class="runwell-bundle-builder__rating-text">Rated {{ section.settings.rating_score }} ({{ section.settings.rating_count }} Reviews)</span>
|
|
49
|
+
</div>
|
|
50
|
+
{% endif %}
|
|
51
|
+
|
|
52
|
+
{% if section.settings.product != blank %}
|
|
53
|
+
<h2 class="runwell-bundle-builder__title h1">{{ section.settings.product.title }}</h2>
|
|
54
|
+
{% else %}
|
|
55
|
+
<h2 class="runwell-bundle-builder__title h1">{{ section.settings.heading }}</h2>
|
|
56
|
+
{% endif %}
|
|
57
|
+
|
|
58
|
+
{%- assign fomo_mode = section.settings.fomo_mode | default: 'none' -%}
|
|
59
|
+
{%- if fomo_mode != 'none' -%}
|
|
60
|
+
{%- comment -%} Dynamic FOMO deadline computation {%- endcomment -%}
|
|
61
|
+
{%- assign now_epoch = 'now' | date: '%s' | plus: 0 -%}
|
|
62
|
+
{%- assign cycle_seconds = section.settings.fomo_cycle_days | times: 86400 -%}
|
|
63
|
+
{%- assign cycle_position = now_epoch | modulo: cycle_seconds -%}
|
|
64
|
+
{%- assign remaining_seconds = cycle_seconds | minus: cycle_position -%}
|
|
65
|
+
{%- assign remaining_days = remaining_seconds | divided_by: 86400 -%}
|
|
66
|
+
{%- assign end_epoch = now_epoch | plus: remaining_seconds -%}
|
|
67
|
+
{%- assign end_date = end_epoch | date: '%B %e' -%}
|
|
68
|
+
|
|
69
|
+
<div class="runwell-bundle-builder__sale-heading">
|
|
70
|
+
<span class="runwell-bundle-builder__sale-line"></span>
|
|
71
|
+
<span class="runwell-bundle-builder__sale-text">
|
|
72
|
+
{%- if fomo_mode == 'discount' or fomo_mode == 'both' -%}
|
|
73
|
+
{{ section.settings.sale_prefix }}: Ends {{ end_date }}
|
|
74
|
+
{%- else -%}
|
|
75
|
+
{{ section.settings.sale_prefix }}
|
|
76
|
+
{%- endif -%}
|
|
77
|
+
</span>
|
|
78
|
+
<span class="runwell-bundle-builder__sale-line"></span>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<div class="runwell-bundle-builder__scarcity">
|
|
82
|
+
<span class="runwell-bundle-builder__scarcity-dot"></span>
|
|
83
|
+
Only {{ section.settings.fomo_stock_count }} left in stock
|
|
84
|
+
</div>
|
|
85
|
+
{%- elsif section.settings.sale_prefix != blank -%}
|
|
86
|
+
<div class="runwell-bundle-builder__sale-heading">
|
|
87
|
+
<span class="runwell-bundle-builder__sale-line"></span>
|
|
88
|
+
<span class="runwell-bundle-builder__sale-text">{{ section.settings.sale_prefix }}</span>
|
|
89
|
+
<span class="runwell-bundle-builder__sale-line"></span>
|
|
90
|
+
</div>
|
|
91
|
+
{%- endif -%}
|
|
92
|
+
|
|
93
|
+
<div class="runwell-bundle-builder__options">
|
|
94
|
+
{%- assign has_popular = false -%}
|
|
95
|
+
{%- for block in section.blocks -%}
|
|
96
|
+
{%- if block.type == 'bundle_option' and block.settings.popular -%}
|
|
97
|
+
{%- assign has_popular = true -%}
|
|
98
|
+
{%- endif -%}
|
|
99
|
+
{%- endfor -%}
|
|
100
|
+
{% for block in section.blocks %}
|
|
101
|
+
{% if block.type != 'bundle_option' %}{% continue %}{% endif %}
|
|
102
|
+
{%- assign is_selected = false -%}
|
|
103
|
+
{%- if has_popular and block.settings.popular -%}
|
|
104
|
+
{%- assign is_selected = true -%}
|
|
105
|
+
{%- elsif has_popular == false and forloop.first -%}
|
|
106
|
+
{%- assign is_selected = true -%}
|
|
107
|
+
{%- endif -%}
|
|
108
|
+
<label class="runwell-bundle-builder__option {% if block.settings.popular %}runwell-bundle-builder__option--popular{% endif %} {% if is_selected %}runwell-bundle-builder__option--selected{% endif %}" {{ block.shopify_attributes }}>
|
|
109
|
+
{% if block.settings.popular %}
|
|
110
|
+
<span class="runwell-bundle-builder__popular-badge">MOST POPULAR</span>
|
|
111
|
+
{% endif %}
|
|
112
|
+
<input type="radio" name="bundle-{{ section.id }}" value="{{ block.id }}" {% if is_selected %}checked{% endif %}>
|
|
113
|
+
<div class="runwell-bundle-builder__option-radio"></div>
|
|
114
|
+
<div class="runwell-bundle-builder__option-content">
|
|
115
|
+
<div class="runwell-bundle-builder__option-header">
|
|
116
|
+
<span class="runwell-bundle-builder__option-title">{{ block.settings.title }}</span>
|
|
117
|
+
<div class="runwell-bundle-builder__option-pricing">
|
|
118
|
+
<span class="runwell-bundle-builder__option-price">${{ block.settings.price }}</span>
|
|
119
|
+
{% if block.settings.compare_price != blank %}
|
|
120
|
+
<span class="runwell-bundle-builder__option-compare">${{ block.settings.compare_price }}</span>
|
|
121
|
+
{% endif %}
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
<div class="runwell-bundle-builder__option-badges">
|
|
125
|
+
{% if block.settings.savings != blank %}
|
|
126
|
+
<span class="runwell-bundle-builder__badge runwell-bundle-builder__badge--save">SAVE ${{ block.settings.savings }}</span>
|
|
127
|
+
{% endif %}
|
|
128
|
+
{% if block.settings.free_shipping %}
|
|
129
|
+
<span class="runwell-bundle-builder__badge runwell-bundle-builder__badge--shipping">FREE SHIPPING</span>
|
|
130
|
+
{% endif %}
|
|
131
|
+
</div>
|
|
132
|
+
{% if block.settings.free_gift_text != blank %}
|
|
133
|
+
<div class="runwell-bundle-builder__free-gift">
|
|
134
|
+
<span class="runwell-bundle-builder__gift-icon">🎁</span>
|
|
135
|
+
<span>{{ block.settings.free_gift_text }}</span>
|
|
136
|
+
</div>
|
|
137
|
+
{% endif %}
|
|
138
|
+
</div>
|
|
139
|
+
</label>
|
|
140
|
+
{% endfor %}
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<div class="runwell-bundle-builder__atc-wrap">
|
|
144
|
+
<button class="runwell-bundle-builder__atc button" type="button" data-atc>
|
|
145
|
+
<span class="runwell-bundle-builder__atc-text">ADD TO CART</span>
|
|
146
|
+
<span class="runwell-bundle-builder__atc-loading" style="display:none;">Adding...</span>
|
|
147
|
+
</button>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
{% if section.settings.show_trust_badges %}
|
|
151
|
+
<div class="runwell-bundle-builder__trust">
|
|
152
|
+
<span>✅ {{ section.settings.trust_1 }}</span>
|
|
153
|
+
<span>✅ {{ section.settings.trust_2 }}</span>
|
|
154
|
+
<span>✅ {{ section.settings.trust_3 }}</span>
|
|
155
|
+
</div>
|
|
156
|
+
{% endif %}
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<script>
|
|
163
|
+
/* Bundle option selection */
|
|
164
|
+
document.querySelectorAll('.runwell-bundle-builder__option').forEach(option => {
|
|
165
|
+
option.addEventListener('click', function() {
|
|
166
|
+
this.closest('.runwell-bundle-builder__options').querySelectorAll('.runwell-bundle-builder__option').forEach(o => o.classList.remove('runwell-bundle-builder__option--selected'));
|
|
167
|
+
this.classList.add('runwell-bundle-builder__option--selected');
|
|
168
|
+
this.querySelector('input').checked = true;
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
/* Thumbnail slideshow */
|
|
173
|
+
document.querySelectorAll('[data-thumbnails]').forEach(container => {
|
|
174
|
+
container.querySelectorAll('[data-thumb]').forEach(thumb => {
|
|
175
|
+
thumb.addEventListener('click', function() {
|
|
176
|
+
const idx = this.dataset.thumb;
|
|
177
|
+
const section = this.closest('.runwell-bundle-builder');
|
|
178
|
+
section.querySelectorAll('.runwell-bundle-builder__slide').forEach(s => s.classList.remove('runwell-bundle-builder__slide--active'));
|
|
179
|
+
section.querySelectorAll('.runwell-bundle-builder__thumb').forEach(t => t.classList.remove('runwell-bundle-builder__thumb--active'));
|
|
180
|
+
section.querySelector('[data-slide="' + idx + '"]').classList.add('runwell-bundle-builder__slide--active');
|
|
181
|
+
this.classList.add('runwell-bundle-builder__thumb--active');
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
/* Add to Cart (Shopify Ajax API) */
|
|
187
|
+
document.querySelectorAll('[data-atc]').forEach(btn => {
|
|
188
|
+
btn.addEventListener('click', function() {
|
|
189
|
+
const section = this.closest('.runwell-bundle-builder');
|
|
190
|
+
const selected = section.querySelector('.runwell-bundle-builder__option--selected');
|
|
191
|
+
if (!selected) return;
|
|
192
|
+
|
|
193
|
+
const title = selected.querySelector('.runwell-bundle-builder__option-title');
|
|
194
|
+
const qtyMatch = title ? title.textContent.match(/^(\d+)x/) : null;
|
|
195
|
+
const qty = qtyMatch ? parseInt(qtyMatch[1]) : 1;
|
|
196
|
+
|
|
197
|
+
const textEl = this.querySelector('.runwell-bundle-builder__atc-text');
|
|
198
|
+
const loadEl = this.querySelector('.runwell-bundle-builder__atc-loading');
|
|
199
|
+
textEl.style.display = 'none';
|
|
200
|
+
loadEl.style.display = 'inline';
|
|
201
|
+
this.disabled = true;
|
|
202
|
+
|
|
203
|
+
fetch('/cart/add.js', {
|
|
204
|
+
method: 'POST',
|
|
205
|
+
headers: { 'Content-Type': 'application/json' },
|
|
206
|
+
body: JSON.stringify({ items: [{ id: {{ section.settings.product.selected_or_first_available_variant.id | default: 0 }}, quantity: qty }] })
|
|
207
|
+
})
|
|
208
|
+
.then(r => r.json())
|
|
209
|
+
.then(() => {
|
|
210
|
+
textEl.textContent = 'ADDED!';
|
|
211
|
+
textEl.style.display = 'inline';
|
|
212
|
+
loadEl.style.display = 'none';
|
|
213
|
+
setTimeout(() => {
|
|
214
|
+
textEl.textContent = 'ADD TO CART';
|
|
215
|
+
this.disabled = false;
|
|
216
|
+
}, 2000);
|
|
217
|
+
})
|
|
218
|
+
.catch(() => {
|
|
219
|
+
textEl.textContent = 'ADD TO CART';
|
|
220
|
+
textEl.style.display = 'inline';
|
|
221
|
+
loadEl.style.display = 'none';
|
|
222
|
+
this.disabled = false;
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
</script>
|
|
227
|
+
|
|
228
|
+
{% schema %}
|
|
229
|
+
{
|
|
230
|
+
"name": "Runwell Bundle Builder",
|
|
231
|
+
"tag": "section",
|
|
232
|
+
"class": "section-runwell-bundle-builder",
|
|
233
|
+
"settings": [
|
|
234
|
+
{
|
|
235
|
+
"type": "product",
|
|
236
|
+
"id": "product",
|
|
237
|
+
"label": "Product"
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"type": "text",
|
|
241
|
+
"id": "heading",
|
|
242
|
+
"label": "Heading (fallback)",
|
|
243
|
+
"default": "Build your bundle"
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
"type": "text",
|
|
247
|
+
"id": "sale_prefix",
|
|
248
|
+
"label": "Sale heading prefix",
|
|
249
|
+
"default": "Limited time offer"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"type": "select",
|
|
253
|
+
"id": "fomo_mode",
|
|
254
|
+
"label": "FOMO mode",
|
|
255
|
+
"options": [
|
|
256
|
+
{ "value": "discount", "label": "Discount deadline" },
|
|
257
|
+
{ "value": "scarcity", "label": "Stock scarcity" },
|
|
258
|
+
{ "value": "both", "label": "Both" },
|
|
259
|
+
{ "value": "none", "label": "None (static heading)" }
|
|
260
|
+
],
|
|
261
|
+
"default": "both"
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"type": "range",
|
|
265
|
+
"id": "fomo_cycle_days",
|
|
266
|
+
"label": "FOMO cycle (days)",
|
|
267
|
+
"min": 7,
|
|
268
|
+
"max": 90,
|
|
269
|
+
"step": 1,
|
|
270
|
+
"default": 30,
|
|
271
|
+
"unit": "d"
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
"type": "range",
|
|
275
|
+
"id": "fomo_stock_count",
|
|
276
|
+
"label": "Stock scarcity count",
|
|
277
|
+
"min": 5,
|
|
278
|
+
"max": 100,
|
|
279
|
+
"step": 1,
|
|
280
|
+
"default": 47,
|
|
281
|
+
"unit": "qty"
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"type": "checkbox",
|
|
285
|
+
"id": "show_rating",
|
|
286
|
+
"label": "Show star rating",
|
|
287
|
+
"default": true
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"type": "text",
|
|
291
|
+
"id": "rating_score",
|
|
292
|
+
"label": "Rating score",
|
|
293
|
+
"default": "4.8/5"
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"type": "text",
|
|
297
|
+
"id": "rating_count",
|
|
298
|
+
"label": "Rating count",
|
|
299
|
+
"default": "2,400+"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"type": "checkbox",
|
|
303
|
+
"id": "show_trust_badges",
|
|
304
|
+
"label": "Show trust badges",
|
|
305
|
+
"default": true
|
|
306
|
+
},
|
|
307
|
+
{ "type": "text", "id": "trust_1", "label": "Trust badge 1", "default": "90-Day Guarantee" },
|
|
308
|
+
{ "type": "text", "id": "trust_2", "label": "Trust badge 2", "default": "Easy Returns" },
|
|
309
|
+
{ "type": "text", "id": "trust_3", "label": "Trust badge 3", "default": "Free Shipping" },
|
|
310
|
+
{
|
|
311
|
+
"type": "color_scheme",
|
|
312
|
+
"id": "color_scheme",
|
|
313
|
+
"label": "Color scheme",
|
|
314
|
+
"default": "scheme-1"
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"type": "range",
|
|
318
|
+
"id": "padding_top",
|
|
319
|
+
"label": "Top padding",
|
|
320
|
+
"min": 0, "max": 100, "step": 4, "default": 40, "unit": "px"
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"type": "range",
|
|
324
|
+
"id": "padding_bottom",
|
|
325
|
+
"label": "Bottom padding",
|
|
326
|
+
"min": 0, "max": 100, "step": 4, "default": 40, "unit": "px"
|
|
327
|
+
}
|
|
328
|
+
],
|
|
329
|
+
"blocks": [
|
|
330
|
+
{
|
|
331
|
+
"type": "gallery_image",
|
|
332
|
+
"name": "Gallery image",
|
|
333
|
+
"settings": [
|
|
334
|
+
{ "type": "image_picker", "id": "image", "label": "Image" },
|
|
335
|
+
{ "type": "text", "id": "alt", "label": "Alt text", "default": "Product image" }
|
|
336
|
+
]
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
"type": "bundle_option",
|
|
340
|
+
"name": "Bundle option",
|
|
341
|
+
"settings": [
|
|
342
|
+
{ "type": "text", "id": "title", "label": "Title (e.g. \"1x Product\")", "default": "1x Product" },
|
|
343
|
+
{ "type": "text", "id": "price", "label": "Price", "default": "24.99" },
|
|
344
|
+
{ "type": "text", "id": "compare_price", "label": "Compare at price", "default": "49.99" },
|
|
345
|
+
{ "type": "text", "id": "savings", "label": "Savings amount", "default": "25.00" },
|
|
346
|
+
{ "type": "checkbox", "id": "free_shipping", "label": "Free shipping badge", "default": false },
|
|
347
|
+
{ "type": "checkbox", "id": "popular", "label": "Most popular (highlighted)", "default": false },
|
|
348
|
+
{ "type": "text", "id": "free_gift_text", "label": "Free gift text" }
|
|
349
|
+
]
|
|
350
|
+
}
|
|
351
|
+
],
|
|
352
|
+
"presets": [
|
|
353
|
+
{
|
|
354
|
+
"name": "Runwell Bundle Builder",
|
|
355
|
+
"blocks": [
|
|
356
|
+
{ "type": "bundle_option", "settings": { "title": "1x Product", "price": "24.99", "compare_price": "49.99", "savings": "25.00", "free_shipping": false, "popular": false } },
|
|
357
|
+
{ "type": "bundle_option", "settings": { "title": "2x Product", "price": "39.99", "compare_price": "99.98", "savings": "59.99", "free_shipping": true, "popular": true } },
|
|
358
|
+
{ "type": "bundle_option", "settings": { "title": "3x Product", "price": "59.99", "compare_price": "149.97", "savings": "89.98", "free_shipping": true, "popular": false, "free_gift_text": "+ Free gift with purchase" } }
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
]
|
|
362
|
+
}
|
|
363
|
+
{% endschema %}
|
|
364
|
+
|
|
365
|
+
<style>
|
|
366
|
+
.section-{{ section.id }}-padding {
|
|
367
|
+
padding-top: {{ section.settings.padding_top }}px;
|
|
368
|
+
padding-bottom: {{ section.settings.padding_bottom }}px;
|
|
369
|
+
}
|
|
370
|
+
</style>
|
|
@@ -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 %}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@runwell/shopify-toolkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
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
|