@o2vend/theme-cli 1.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +425 -0
- package/assets/Logo_o2vend.png +0 -0
- package/assets/favicon.png +0 -0
- package/assets/logo-white.png +0 -0
- package/bin/o2vend +42 -0
- package/config/widget-map.json +50 -0
- package/lib/commands/check.js +201 -0
- package/lib/commands/generate.js +33 -0
- package/lib/commands/init.js +214 -0
- package/lib/commands/optimize.js +216 -0
- package/lib/commands/package.js +208 -0
- package/lib/commands/serve.js +105 -0
- package/lib/commands/validate.js +191 -0
- package/lib/lib/api-client.js +357 -0
- package/lib/lib/dev-server.js +2618 -0
- package/lib/lib/file-watcher.js +80 -0
- package/lib/lib/hot-reload.js +106 -0
- package/lib/lib/liquid-engine.js +822 -0
- package/lib/lib/liquid-filters.js +671 -0
- package/lib/lib/mock-api-server.js +989 -0
- package/lib/lib/mock-data.js +1468 -0
- package/lib/lib/widget-service.js +321 -0
- package/package.json +70 -0
- package/test-theme/README.md +27 -0
- package/test-theme/assets/async-sections.js +446 -0
- package/test-theme/assets/cart-drawer.js +463 -0
- package/test-theme/assets/cart-manager.js +223 -0
- package/test-theme/assets/checkout-price-handler.js +368 -0
- package/test-theme/assets/components.css +4629 -0
- package/test-theme/assets/delivery-zone.css +299 -0
- package/test-theme/assets/delivery-zone.js +396 -0
- package/test-theme/assets/logo.png +0 -0
- package/test-theme/assets/sections.css +48 -0
- package/test-theme/assets/theme.css +3500 -0
- package/test-theme/assets/theme.js +3745 -0
- package/test-theme/config/settings_data.json +292 -0
- package/test-theme/config/settings_schema.json +1050 -0
- package/test-theme/layout/theme.liquid +195 -0
- package/test-theme/locales/en.default.json +260 -0
- package/test-theme/sections/content-fallback.liquid +53 -0
- package/test-theme/sections/content.liquid +57 -0
- package/test-theme/sections/footer-fallback.liquid +328 -0
- package/test-theme/sections/footer.liquid +278 -0
- package/test-theme/sections/header-fallback.liquid +1805 -0
- package/test-theme/sections/header.liquid +1145 -0
- package/test-theme/sections/hero-fallback.liquid +212 -0
- package/test-theme/sections/hero.liquid +136 -0
- package/test-theme/snippets/account-sidebar.liquid +200 -0
- package/test-theme/snippets/add-to-cart-modal.liquid +484 -0
- package/test-theme/snippets/breadcrumbs.liquid +134 -0
- package/test-theme/snippets/cart-drawer.liquid +467 -0
- package/test-theme/snippets/delivery-zone-city-selector.liquid +79 -0
- package/test-theme/snippets/delivery-zone-modal.liquid +337 -0
- package/test-theme/snippets/delivery-zone-search.liquid +78 -0
- package/test-theme/snippets/icon.liquid +105 -0
- package/test-theme/snippets/login-modal.liquid +346 -0
- package/test-theme/snippets/mega-menu.liquid +812 -0
- package/test-theme/snippets/news-thumbnail.liquid +187 -0
- package/test-theme/snippets/pagination.liquid +120 -0
- package/test-theme/snippets/price.liquid +92 -0
- package/test-theme/snippets/product-card-related.liquid +78 -0
- package/test-theme/snippets/product-card-simple.liquid +41 -0
- package/test-theme/snippets/product-card.liquid +697 -0
- package/test-theme/snippets/rating.liquid +85 -0
- package/test-theme/snippets/skeleton-collection-grid.liquid +114 -0
- package/test-theme/snippets/skeleton-product-card.liquid +124 -0
- package/test-theme/snippets/skeleton-product-grid.liquid +34 -0
- package/test-theme/snippets/social-sharing.liquid +185 -0
- package/test-theme/templates/account/dashboard.liquid +401 -0
- package/test-theme/templates/account/loyalty-redemption.liquid +405 -0
- package/test-theme/templates/account/loyalty.liquid +588 -0
- package/test-theme/templates/account/order-detail.liquid +230 -0
- package/test-theme/templates/account/orders.liquid +349 -0
- package/test-theme/templates/account/profile.liquid +758 -0
- package/test-theme/templates/account/register.liquid +232 -0
- package/test-theme/templates/account/return-orders.liquid +348 -0
- package/test-theme/templates/account/store-credit.liquid +464 -0
- package/test-theme/templates/account/subscriptions.liquid +601 -0
- package/test-theme/templates/account/wishlist.liquid +419 -0
- package/test-theme/templates/address-book.liquid +1092 -0
- package/test-theme/templates/categories.liquid +452 -0
- package/test-theme/templates/checkout.liquid +4511 -0
- package/test-theme/templates/error.liquid +384 -0
- package/test-theme/templates/index.liquid +11 -0
- package/test-theme/templates/login.liquid +185 -0
- package/test-theme/templates/order-confirmation.liquid +720 -0
- package/test-theme/templates/page.liquid +297 -0
- package/test-theme/templates/product-detail.liquid +4363 -0
- package/test-theme/templates/products.liquid +518 -0
- package/test-theme/templates/search.liquid +922 -0
- package/test-theme/theme.json.example +19 -0
- package/test-theme/widgets/brand-carousel.liquid +676 -0
- package/test-theme/widgets/brand.liquid +245 -0
- package/test-theme/widgets/carousel.liquid +843 -0
- package/test-theme/widgets/category-list-carousel.liquid +656 -0
- package/test-theme/widgets/category-list.liquid +340 -0
- package/test-theme/widgets/category.liquid +475 -0
- package/test-theme/widgets/discount-time.liquid +176 -0
- package/test-theme/widgets/footer-menu.liquid +695 -0
- package/test-theme/widgets/footer.liquid +179 -0
- package/test-theme/widgets/gallery.liquid +271 -0
- package/test-theme/widgets/header-menu.liquid +932 -0
- package/test-theme/widgets/header.liquid +159 -0
- package/test-theme/widgets/html.liquid +214 -0
- package/test-theme/widgets/news.liquid +217 -0
- package/test-theme/widgets/product-canvas.liquid +235 -0
- package/test-theme/widgets/product-carousel.liquid +502 -0
- package/test-theme/widgets/product.liquid +45 -0
- package/test-theme/widgets/recently-viewed.liquid +26 -0
- package/test-theme/widgets/shared/product-grid.liquid +339 -0
- package/test-theme/widgets/simple-product.liquid +42 -0
- package/test-theme/widgets/single-product.liquid +610 -0
- package/test-theme/widgets/spacebar-carousel.liquid +663 -0
- package/test-theme/widgets/spacebar.liquid +279 -0
- package/test-theme/widgets/splash.liquid +378 -0
- package/test-theme/widgets/testimonial-carousel.liquid +709 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Product Rating Display Snippet
|
|
3
|
+
|
|
4
|
+
Displays product rating with stars and review count.
|
|
5
|
+
Usage: {% render 'snippets/rating', product: product %}
|
|
6
|
+
{% endcomment %}
|
|
7
|
+
|
|
8
|
+
{% liquid
|
|
9
|
+
assign product = product | default: null
|
|
10
|
+
assign rating = rating | default: product.rating | default: product.averageRating | default: 0
|
|
11
|
+
assign review_count = review_count | default: product.reviewCount | default: product.reviewsCount | default: 0
|
|
12
|
+
assign show_count = show_count | default: true
|
|
13
|
+
assign max_rating = max_rating | default: 5
|
|
14
|
+
|
|
15
|
+
if rating == null or rating == empty
|
|
16
|
+
assign rating = 0
|
|
17
|
+
endif
|
|
18
|
+
|
|
19
|
+
assign rating_float = rating | times: 1.0
|
|
20
|
+
assign full_stars = rating_float | floor
|
|
21
|
+
assign has_half_star = rating_float | modulo: 1 | times: 10 | round | divided_by: 10.0
|
|
22
|
+
assign empty_stars = max_rating | minus: full_stars
|
|
23
|
+
if has_half_star > 0
|
|
24
|
+
assign empty_stars = empty_stars | minus: 1
|
|
25
|
+
endif
|
|
26
|
+
%}
|
|
27
|
+
|
|
28
|
+
<div class="rating" data-rating="{{ rating }}" aria-label="Rating: {{ rating }} out of {{ max_rating }}">
|
|
29
|
+
<div class="rating-stars" role="img" aria-label="{{ rating }} out of {{ max_rating }} stars">
|
|
30
|
+
{% for i in (1..full_stars) %}
|
|
31
|
+
<span class="rating-star rating-star-full" aria-hidden="true">★</span>
|
|
32
|
+
{% endfor %}
|
|
33
|
+
|
|
34
|
+
{% if has_half_star > 0 %}
|
|
35
|
+
<span class="rating-star rating-star-half" aria-hidden="true">★</span>
|
|
36
|
+
{% endif %}
|
|
37
|
+
|
|
38
|
+
{% for i in (1..empty_stars) %}
|
|
39
|
+
<span class="rating-star rating-star-empty" aria-hidden="true">☆</span>
|
|
40
|
+
{% endfor %}
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
{% if show_count and review_count > 0 %}
|
|
44
|
+
<span class="rating-count" data-rating-count>
|
|
45
|
+
({{ review_count }} {{ 'product.reviews' | t | default: 'review' | pluralize: review_count }})
|
|
46
|
+
</span>
|
|
47
|
+
{% endif %}
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<style>
|
|
51
|
+
.rating {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
gap: 0.5rem;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.rating-stars {
|
|
58
|
+
display: inline-flex;
|
|
59
|
+
gap: 0.125rem;
|
|
60
|
+
font-size: 1rem;
|
|
61
|
+
line-height: 1;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.rating-star {
|
|
65
|
+
color: #fbbf24;
|
|
66
|
+
font-size: 1rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.rating-star-empty {
|
|
70
|
+
color: #e5e7eb;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.rating-star-half {
|
|
74
|
+
background: linear-gradient(90deg, #fbbf24 50%, #e5e7eb 50%);
|
|
75
|
+
-webkit-background-clip: text;
|
|
76
|
+
-webkit-text-fill-color: transparent;
|
|
77
|
+
background-clip: text;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.rating-count {
|
|
81
|
+
font-size: 0.875rem;
|
|
82
|
+
color: {{ settings.color_text_light }};
|
|
83
|
+
}
|
|
84
|
+
</style>
|
|
85
|
+
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Skeleton Loader for Collection/Category Grid
|
|
3
|
+
Parameters:
|
|
4
|
+
- count: Number of skeleton cards to display (default: 6)
|
|
5
|
+
{% endcomment %}
|
|
6
|
+
|
|
7
|
+
{% assign skeletonCount = count | default: 6 %}
|
|
8
|
+
|
|
9
|
+
<div class="collections-grid skeleton-grid">
|
|
10
|
+
{% if skeletonCount >= 1 %}
|
|
11
|
+
<div class="collection-card skeleton-card">
|
|
12
|
+
<div class="collection-image-container skeleton-image">
|
|
13
|
+
<div class="skeleton-shimmer"></div>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="collection-content">
|
|
16
|
+
<div class="skeleton-text skeleton-title"></div>
|
|
17
|
+
<div class="skeleton-text skeleton-description"></div>
|
|
18
|
+
<div class="skeleton-text skeleton-meta"></div>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
{% endif %}
|
|
22
|
+
{% if skeletonCount >= 2 %}
|
|
23
|
+
<div class="collection-card skeleton-card">
|
|
24
|
+
<div class="collection-image-container skeleton-image">
|
|
25
|
+
<div class="skeleton-shimmer"></div>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="collection-content">
|
|
28
|
+
<div class="skeleton-text skeleton-title"></div>
|
|
29
|
+
<div class="skeleton-text skeleton-description"></div>
|
|
30
|
+
<div class="skeleton-text skeleton-meta"></div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
{% endif %}
|
|
34
|
+
{% if skeletonCount >= 3 %}
|
|
35
|
+
<div class="collection-card skeleton-card">
|
|
36
|
+
<div class="collection-image-container skeleton-image">
|
|
37
|
+
<div class="skeleton-shimmer"></div>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="collection-content">
|
|
40
|
+
<div class="skeleton-text skeleton-title"></div>
|
|
41
|
+
<div class="skeleton-text skeleton-description"></div>
|
|
42
|
+
<div class="skeleton-text skeleton-meta"></div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
{% endif %}
|
|
46
|
+
{% if skeletonCount >= 4 %}
|
|
47
|
+
<div class="collection-card skeleton-card">
|
|
48
|
+
<div class="collection-image-container skeleton-image">
|
|
49
|
+
<div class="skeleton-shimmer"></div>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="collection-content">
|
|
52
|
+
<div class="skeleton-text skeleton-title"></div>
|
|
53
|
+
<div class="skeleton-text skeleton-description"></div>
|
|
54
|
+
<div class="skeleton-text skeleton-meta"></div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
{% endif %}
|
|
58
|
+
{% if skeletonCount >= 5 %}
|
|
59
|
+
<div class="collection-card skeleton-card">
|
|
60
|
+
<div class="collection-image-container skeleton-image">
|
|
61
|
+
<div class="skeleton-shimmer"></div>
|
|
62
|
+
</div>
|
|
63
|
+
<div class="collection-content">
|
|
64
|
+
<div class="skeleton-text skeleton-title"></div>
|
|
65
|
+
<div class="skeleton-text skeleton-description"></div>
|
|
66
|
+
<div class="skeleton-text skeleton-meta"></div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
{% endif %}
|
|
70
|
+
{% if skeletonCount >= 6 %}
|
|
71
|
+
<div class="collection-card skeleton-card">
|
|
72
|
+
<div class="collection-image-container skeleton-image">
|
|
73
|
+
<div class="skeleton-shimmer"></div>
|
|
74
|
+
</div>
|
|
75
|
+
<div class="collection-content">
|
|
76
|
+
<div class="skeleton-text skeleton-title"></div>
|
|
77
|
+
<div class="skeleton-text skeleton-description"></div>
|
|
78
|
+
<div class="skeleton-text skeleton-meta"></div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
{% endif %}
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<style>
|
|
85
|
+
.skeleton-card .collection-image-container {
|
|
86
|
+
background: #f0f0f0;
|
|
87
|
+
position: relative;
|
|
88
|
+
overflow: hidden;
|
|
89
|
+
aspect-ratio: 1;
|
|
90
|
+
border-radius: 12px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.skeleton-card .collection-content {
|
|
94
|
+
padding: 1rem 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.skeleton-card .skeleton-title {
|
|
98
|
+
width: 80%;
|
|
99
|
+
height: 20px;
|
|
100
|
+
margin-bottom: 8px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.skeleton-card .skeleton-description {
|
|
104
|
+
width: 100%;
|
|
105
|
+
height: 14px;
|
|
106
|
+
margin-bottom: 6px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.skeleton-card .skeleton-meta {
|
|
110
|
+
width: 50%;
|
|
111
|
+
height: 12px;
|
|
112
|
+
}
|
|
113
|
+
</style>
|
|
114
|
+
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Skeleton Loader for Product Card
|
|
3
|
+
Shows animated placeholder while product data loads
|
|
4
|
+
{% endcomment %}
|
|
5
|
+
|
|
6
|
+
<div class="product-card skeleton-card">
|
|
7
|
+
<div class="product-card-image skeleton-image">
|
|
8
|
+
<div class="skeleton-shimmer"></div>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="product-card-content">
|
|
11
|
+
<div class="skeleton-text skeleton-vendor"></div>
|
|
12
|
+
<div class="skeleton-text skeleton-title"></div>
|
|
13
|
+
<div class="skeleton-text skeleton-price"></div>
|
|
14
|
+
<div class="skeleton-button"></div>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<style>
|
|
19
|
+
.skeleton-card {
|
|
20
|
+
pointer-events: none;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.skeleton-image {
|
|
24
|
+
background: #f0f0f0;
|
|
25
|
+
position: relative;
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
border-radius: 12px;
|
|
28
|
+
aspect-ratio: 1;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.skeleton-shimmer {
|
|
32
|
+
position: absolute;
|
|
33
|
+
top: 0;
|
|
34
|
+
left: -100%;
|
|
35
|
+
height: 100%;
|
|
36
|
+
width: 100%;
|
|
37
|
+
background: linear-gradient(
|
|
38
|
+
90deg,
|
|
39
|
+
transparent 0%,
|
|
40
|
+
rgba(255, 255, 255, 0.6) 50%,
|
|
41
|
+
transparent 100%
|
|
42
|
+
);
|
|
43
|
+
animation: shimmer 2s infinite;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@keyframes shimmer {
|
|
47
|
+
0% {
|
|
48
|
+
left: -100%;
|
|
49
|
+
}
|
|
50
|
+
100% {
|
|
51
|
+
left: 100%;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.skeleton-text {
|
|
56
|
+
height: 16px;
|
|
57
|
+
background: #f0f0f0;
|
|
58
|
+
border-radius: 4px;
|
|
59
|
+
position: relative;
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
margin-bottom: 8px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.skeleton-text::after {
|
|
65
|
+
content: '';
|
|
66
|
+
position: absolute;
|
|
67
|
+
top: 0;
|
|
68
|
+
left: -100%;
|
|
69
|
+
height: 100%;
|
|
70
|
+
width: 100%;
|
|
71
|
+
background: linear-gradient(
|
|
72
|
+
90deg,
|
|
73
|
+
transparent 0%,
|
|
74
|
+
rgba(255, 255, 255, 0.6) 50%,
|
|
75
|
+
transparent 100%
|
|
76
|
+
);
|
|
77
|
+
animation: shimmer 2s infinite;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.skeleton-vendor {
|
|
81
|
+
width: 60%;
|
|
82
|
+
height: 12px;
|
|
83
|
+
margin-bottom: 6px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.skeleton-title {
|
|
87
|
+
width: 90%;
|
|
88
|
+
height: 18px;
|
|
89
|
+
margin-bottom: 8px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.skeleton-price {
|
|
93
|
+
width: 50%;
|
|
94
|
+
height: 20px;
|
|
95
|
+
margin-bottom: 12px;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.skeleton-button {
|
|
99
|
+
width: 100%;
|
|
100
|
+
height: 44px;
|
|
101
|
+
background: #f0f0f0;
|
|
102
|
+
border-radius: 8px;
|
|
103
|
+
position: relative;
|
|
104
|
+
overflow: hidden;
|
|
105
|
+
margin-top: 8px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.skeleton-button::after {
|
|
109
|
+
content: '';
|
|
110
|
+
position: absolute;
|
|
111
|
+
top: 0;
|
|
112
|
+
left: -100%;
|
|
113
|
+
height: 100%;
|
|
114
|
+
width: 100%;
|
|
115
|
+
background: linear-gradient(
|
|
116
|
+
90deg,
|
|
117
|
+
transparent 0%,
|
|
118
|
+
rgba(255, 255, 255, 0.6) 50%,
|
|
119
|
+
transparent 100%
|
|
120
|
+
);
|
|
121
|
+
animation: shimmer 2s infinite;
|
|
122
|
+
}
|
|
123
|
+
</style>
|
|
124
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Skeleton Loader for Product Grid
|
|
3
|
+
Parameters:
|
|
4
|
+
- count: Number of skeleton cards to display (default: 4)
|
|
5
|
+
{% endcomment %}
|
|
6
|
+
|
|
7
|
+
{% assign skeletonCount = count | default: 4 %}
|
|
8
|
+
|
|
9
|
+
<div class="products-grid skeleton-grid">
|
|
10
|
+
{% if skeletonCount >= 1 %}{% include 'snippets/skeleton-product-card' %}{% endif %}
|
|
11
|
+
{% if skeletonCount >= 2 %}{% include 'snippets/skeleton-product-card' %}{% endif %}
|
|
12
|
+
{% if skeletonCount >= 3 %}{% include 'snippets/skeleton-product-card' %}{% endif %}
|
|
13
|
+
{% if skeletonCount >= 4 %}{% include 'snippets/skeleton-product-card' %}{% endif %}
|
|
14
|
+
{% if skeletonCount >= 5 %}{% include 'snippets/skeleton-product-card' %}{% endif %}
|
|
15
|
+
{% if skeletonCount >= 6 %}{% include 'snippets/skeleton-product-card' %}{% endif %}
|
|
16
|
+
{% if skeletonCount >= 7 %}{% include 'snippets/skeleton-product-card' %}{% endif %}
|
|
17
|
+
{% if skeletonCount >= 8 %}{% include 'snippets/skeleton-product-card' %}{% endif %}
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<style>
|
|
21
|
+
.skeleton-grid {
|
|
22
|
+
animation: fadeIn 0.3s ease-in;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@keyframes fadeIn {
|
|
26
|
+
from {
|
|
27
|
+
opacity: 0;
|
|
28
|
+
}
|
|
29
|
+
to {
|
|
30
|
+
opacity: 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
</style>
|
|
34
|
+
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Social Sharing Snippet
|
|
3
|
+
|
|
4
|
+
Displays social sharing buttons for products, articles, etc.
|
|
5
|
+
Usage: {% render 'snippets/social-sharing', url: product.url, title: product.title %}
|
|
6
|
+
{% endcomment %}
|
|
7
|
+
|
|
8
|
+
{% liquid
|
|
9
|
+
assign url = url | default: request.url
|
|
10
|
+
assign title = title | default: page.title | default: product.title | default: shop.name
|
|
11
|
+
assign description = description | default: page.description | default: product.description | default: shop.description
|
|
12
|
+
assign image = image | default: product.image | default: page.image
|
|
13
|
+
|
|
14
|
+
# Encode URL for sharing
|
|
15
|
+
assign encoded_url = url | url_encode
|
|
16
|
+
assign encoded_title = title | url_encode
|
|
17
|
+
assign encoded_description = description | truncate: 200 | url_encode
|
|
18
|
+
%}
|
|
19
|
+
|
|
20
|
+
<div class="social-sharing" data-social-sharing>
|
|
21
|
+
<span class="social-sharing-label">{{ 'general.social.share' | t | default: 'Share' }}</span>
|
|
22
|
+
<div class="social-sharing-buttons">
|
|
23
|
+
<a href="https://www.facebook.com/sharer/sharer.php?u={{ encoded_url }}"
|
|
24
|
+
class="social-sharing-button social-sharing-button--facebook"
|
|
25
|
+
target="_blank"
|
|
26
|
+
rel="noopener noreferrer"
|
|
27
|
+
aria-label="Share on Facebook">
|
|
28
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
29
|
+
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
|
|
30
|
+
</svg>
|
|
31
|
+
<span>Facebook</span>
|
|
32
|
+
</a>
|
|
33
|
+
|
|
34
|
+
<a href="https://twitter.com/intent/tweet?url={{ encoded_url }}&text={{ encoded_title }}"
|
|
35
|
+
class="social-sharing-button social-sharing-button--twitter"
|
|
36
|
+
target="_blank"
|
|
37
|
+
rel="noopener noreferrer"
|
|
38
|
+
aria-label="Share on Twitter">
|
|
39
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
40
|
+
<path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/>
|
|
41
|
+
</svg>
|
|
42
|
+
<span>Twitter</span>
|
|
43
|
+
</a>
|
|
44
|
+
|
|
45
|
+
<a href="https://pinterest.com/pin/create/button/?url={{ encoded_url }}&description={{ encoded_title }}"
|
|
46
|
+
class="social-sharing-button social-sharing-button--pinterest"
|
|
47
|
+
target="_blank"
|
|
48
|
+
rel="noopener noreferrer"
|
|
49
|
+
aria-label="Share on Pinterest">
|
|
50
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
|
51
|
+
<path d="M12.017 0C5.396 0 .029 5.367.029 11.987c0 5.079 3.158 9.417 7.618 11.174-.105-.949-.199-2.403.041-3.439.219-.937 1.406-5.957 1.406-5.957s-.359-.72-.359-1.781c0-1.663.967-2.911 2.168-2.911 1.024 0 1.518.769 1.518 1.688 0 1.029-.653 2.567-.992 3.992-.285 1.193.6 2.165 1.775 2.165 2.128 0 3.768-2.245 3.768-5.487 0-2.861-2.063-4.869-5.008-4.869-3.41 0-5.409 2.562-5.409 5.199 0 1.033.394 2.143.889 2.741.099.12.112.225.085.345-.09.375-.293 1.199-.334 1.363-.053.225-.172.271-.402.165-1.495-.69-2.433-2.878-2.433-4.646 0-3.776 2.748-7.252 7.92-7.252 4.158 0 7.392 2.967 7.392 6.923 0 4.135-2.607 7.462-6.233 7.462-1.214 0-2.357-.629-2.746-1.378l-.748 2.853c-.271 1.043-1.002 2.35-1.492 3.146C9.57 23.812 10.763 24.009 12.017 24.009c6.624 0 11.99-5.367 11.99-11.988C24.007 5.367 18.641.001 12.017.001z"/>
|
|
52
|
+
</svg>
|
|
53
|
+
<span>Pinterest</span>
|
|
54
|
+
</a>
|
|
55
|
+
|
|
56
|
+
<a href="mailto:?subject={{ encoded_title }}&body={{ encoded_url }}"
|
|
57
|
+
class="social-sharing-button social-sharing-button--email"
|
|
58
|
+
aria-label="Share via Email">
|
|
59
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
60
|
+
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
|
|
61
|
+
<polyline points="22,6 12,13 2,6"></polyline>
|
|
62
|
+
</svg>
|
|
63
|
+
<span>Email</span>
|
|
64
|
+
</a>
|
|
65
|
+
|
|
66
|
+
<button class="social-sharing-button social-sharing-button--copy"
|
|
67
|
+
data-copy-url="{{ url }}"
|
|
68
|
+
aria-label="Copy link">
|
|
69
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
70
|
+
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
|
71
|
+
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
|
72
|
+
</svg>
|
|
73
|
+
<span>Copy Link</span>
|
|
74
|
+
</button>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<style>
|
|
79
|
+
.social-sharing {
|
|
80
|
+
display: flex;
|
|
81
|
+
align-items: center;
|
|
82
|
+
gap: 1rem;
|
|
83
|
+
flex-wrap: wrap;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.social-sharing-label {
|
|
87
|
+
font-size: 0.875rem;
|
|
88
|
+
font-weight: 500;
|
|
89
|
+
color: {{ settings.color_text }};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.social-sharing-buttons {
|
|
93
|
+
display: flex;
|
|
94
|
+
gap: 0.5rem;
|
|
95
|
+
flex-wrap: wrap;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.social-sharing-button {
|
|
99
|
+
display: inline-flex;
|
|
100
|
+
align-items: center;
|
|
101
|
+
gap: 0.5rem;
|
|
102
|
+
padding: 0.5rem 1rem;
|
|
103
|
+
border: 1px solid #e5e7eb;
|
|
104
|
+
background: white;
|
|
105
|
+
color: {{ settings.color_text }};
|
|
106
|
+
text-decoration: none;
|
|
107
|
+
border-radius: 0.375rem;
|
|
108
|
+
font-size: 0.875rem;
|
|
109
|
+
transition: all 0.2s ease;
|
|
110
|
+
cursor: pointer;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.social-sharing-button:hover {
|
|
114
|
+
background: #f9fafb;
|
|
115
|
+
border-color: {{ settings.color_primary }};
|
|
116
|
+
color: {{ settings.color_primary }};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.social-sharing-button--facebook:hover {
|
|
120
|
+
background: #1877f2;
|
|
121
|
+
border-color: #1877f2;
|
|
122
|
+
color: white;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.social-sharing-button--twitter:hover {
|
|
126
|
+
background: #1da1f2;
|
|
127
|
+
border-color: #1da1f2;
|
|
128
|
+
color: white;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.social-sharing-button--pinterest:hover {
|
|
132
|
+
background: #bd081c;
|
|
133
|
+
border-color: #bd081c;
|
|
134
|
+
color: white;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.social-sharing-button--email:hover {
|
|
138
|
+
background: {{ settings.color_primary }};
|
|
139
|
+
border-color: {{ settings.color_primary }};
|
|
140
|
+
color: white;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.social-sharing-button svg {
|
|
144
|
+
flex-shrink: 0;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@media (max-width: 480px) {
|
|
148
|
+
.social-sharing {
|
|
149
|
+
flex-direction: column;
|
|
150
|
+
align-items: flex-start;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.social-sharing-button span {
|
|
154
|
+
display: none;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.social-sharing-button {
|
|
158
|
+
padding: 0.5rem;
|
|
159
|
+
width: 40px;
|
|
160
|
+
height: 40px;
|
|
161
|
+
justify-content: center;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
</style>
|
|
165
|
+
|
|
166
|
+
<script>
|
|
167
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
168
|
+
const copyButton = document.querySelector('[data-copy-url]');
|
|
169
|
+
if (copyButton) {
|
|
170
|
+
copyButton.addEventListener('click', function() {
|
|
171
|
+
const url = this.dataset.copyUrl;
|
|
172
|
+
navigator.clipboard.writeText(url).then(() => {
|
|
173
|
+
const originalText = this.querySelector('span').textContent;
|
|
174
|
+
this.querySelector('span').textContent = 'Copied!';
|
|
175
|
+
setTimeout(() => {
|
|
176
|
+
this.querySelector('span').textContent = originalText;
|
|
177
|
+
}, 2000);
|
|
178
|
+
}).catch(err => {
|
|
179
|
+
console.error('Failed to copy:', err);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
</script>
|
|
185
|
+
|