zz-shopify-components 0.3.1-beta.1 → 0.3.1-beta.10
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/assets/zz-components.css +3 -1
- package/assets/zz-components.js +3 -3
- package/assets/zz-http-request.js +27 -0
- package/assets/zz-modal.js +418 -0
- package/blocks/zz-button.liquid +13 -1
- package/blocks/zz-normal-swiper.liquid +246 -0
- package/docs/zz-modal.md +186 -0
- package/package.json +1 -1
- package/sections/zz-flex-layout-section.liquid +6 -1
- package/sections/zz-modal.liquid +157 -0
- package/sections/zz-navigation-tab-v3.liquid +5 -5
- package/sections/zz-shopping-card-list.liquid +0 -3
- package/sections/zz-swiper-banner.liquid +856 -0
- package/sections/zz-video-collapse-swiper.liquid +3 -30
- package/sections/zz-video-tab-swiper.liquid +0 -9
- package/snippets/zz-button.liquid +4 -1
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
{% assign block_size = block.blocks.size %}
|
|
2
|
+
|
|
3
|
+
<style>
|
|
4
|
+
#shopify-block-{{block.id}} {
|
|
5
|
+
background: {{ block.settings.bg_color }};
|
|
6
|
+
width: 100%;
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
overflow: hidden;
|
|
9
|
+
position: relative;
|
|
10
|
+
}
|
|
11
|
+
#shopify-block-{{block.id}} .zz-normal-swiper {
|
|
12
|
+
width: 100%;
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
position: relative;
|
|
16
|
+
letter-spacing: 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#shopify-block-{{block.id}} .swiper-button-next:after,
|
|
20
|
+
#shopify-block-{{block.id}} .swiper-button-prev:after {
|
|
21
|
+
display: none;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#shopify-block-{{block.id}} .zz-normal-swiper .swiper-pagination-bullets {
|
|
25
|
+
bottom: 16px;
|
|
26
|
+
}
|
|
27
|
+
#shopify-block-{{block.id}} .zz-normal-swiper .swiper-pagination-bullet {
|
|
28
|
+
margin: 0 4px;
|
|
29
|
+
width: 6px;
|
|
30
|
+
height: 6px;
|
|
31
|
+
border-radius: 6px;
|
|
32
|
+
background: {{ block.settings.mb_pagination_color | color_modify: 'alpha', 0.3 }};
|
|
33
|
+
opacity: 1;
|
|
34
|
+
transition: 0.3s;
|
|
35
|
+
}
|
|
36
|
+
#shopify-block-{{block.id}} .zz-normal-swiper .swiper-pagination-bullet-active {
|
|
37
|
+
background: {{ block.settings.mb_pagination_color }};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@media screen and (min-width: 1024px) {
|
|
41
|
+
#shopify-block-{{block.id}} .zz-normal-swiper .swiper-pagination-bullets {
|
|
42
|
+
bottom: 24px;
|
|
43
|
+
}
|
|
44
|
+
#shopify-block-{{block.id}} .zz-normal-swiper .swiper-pagination-bullet {
|
|
45
|
+
margin: 0 6px;
|
|
46
|
+
width: 10px;
|
|
47
|
+
height: 10px;
|
|
48
|
+
border-radius: 10px;
|
|
49
|
+
background: {{ block.settings.pagination_color | color_modify: 'alpha', 0.3 }};
|
|
50
|
+
}
|
|
51
|
+
#shopify-block-{{block.id}} .zz-normal-swiper .swiper-pagination-bullet-active {
|
|
52
|
+
background: {{ block.settings.pagination_color }};
|
|
53
|
+
}
|
|
54
|
+
#shopify-block-{{block.id}} .swiper-button-next,
|
|
55
|
+
#shopify-block-{{block.id}} .swiper-button-prev {
|
|
56
|
+
width: 48px;
|
|
57
|
+
height: 48px;
|
|
58
|
+
top: 50%;
|
|
59
|
+
transform: translateY(-50%);
|
|
60
|
+
}
|
|
61
|
+
#shopify-block-{{block.id}} .swiper-button-prev { left: 16px; }
|
|
62
|
+
#shopify-block-{{block.id}} .swiper-button-next { right: 16px; }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@media screen and (max-width: 1023px) {
|
|
66
|
+
{% if block.settings.show_navigation_mobile == false %}
|
|
67
|
+
#shopify-block-{{block.id}} .swiper-button-next,
|
|
68
|
+
#shopify-block-{{block.id}} .swiper-button-prev { display: none; }
|
|
69
|
+
{% endif %}
|
|
70
|
+
}
|
|
71
|
+
</style>
|
|
72
|
+
|
|
73
|
+
<div
|
|
74
|
+
class='zz-normal-swiper swiper zz-normal-swiper-{{ block.id }}'
|
|
75
|
+
>
|
|
76
|
+
<div class='zz-swiper-wrapper swiper-wrapper'>
|
|
77
|
+
{% for block in block.blocks %}
|
|
78
|
+
<div class='swiper-slide'>
|
|
79
|
+
{% render block %}
|
|
80
|
+
</div>
|
|
81
|
+
{% endfor %}
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
{% if block.settings.show_navigation %}
|
|
85
|
+
<div class='swiper-button-prev {% if block_size <= 1 %} tw-hidden {% endif %}'>
|
|
86
|
+
{% render 'zz-prev-next-btn', type: 'prev', color_type: block.settings.prev_next_type %}
|
|
87
|
+
</div>
|
|
88
|
+
<div class='swiper-button-next {% if block_size <= 1 %} tw-hidden {% endif %}'>
|
|
89
|
+
{% render 'zz-prev-next-btn', type: 'next', color_type: block.settings.prev_next_type %}
|
|
90
|
+
</div>
|
|
91
|
+
{% endif %}
|
|
92
|
+
|
|
93
|
+
{% if block.settings.pagination_type != 'none' %}
|
|
94
|
+
<div class='swiper-pagination'></div>
|
|
95
|
+
{% endif %}
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<script>
|
|
99
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
100
|
+
const block = document.getElementById('shopify-block-{{block.id}}');
|
|
101
|
+
const swiperWrapper = block.querySelector('.zz-swiper-wrapper');
|
|
102
|
+
{% comment %} const slides = swiperWrapper ? swiperWrapper.querySelectorAll(':scope > div') : [];
|
|
103
|
+
slides.forEach((slide) => slide.classList.add('swiper-slide'));
|
|
104
|
+
swiperWrapper.classList.add('swiper-wrapper'); {% endcomment %}
|
|
105
|
+
|
|
106
|
+
const swiperSelector = '.zz-normal-swiper-{{ block.id }}';
|
|
107
|
+
let instance = null;
|
|
108
|
+
let initialized = false;
|
|
109
|
+
|
|
110
|
+
const options = {
|
|
111
|
+
loop: {{ block.settings.loop | json }},
|
|
112
|
+
speed: {{ block.settings.speed | default: 500 }},
|
|
113
|
+
autoHeight: {{ block.settings.auto_height | json }},
|
|
114
|
+
centeredSlides: {{ block.settings.centered_slides | json }},
|
|
115
|
+
watchOverflow: true,
|
|
116
|
+
spaceBetween: {{ block.settings.space_between | default: 8 }},
|
|
117
|
+
{% if block.settings.pagination_type != 'none' %}
|
|
118
|
+
pagination: {
|
|
119
|
+
el: '#shopify-block-{{block.id}} .swiper-pagination',
|
|
120
|
+
clickable: true,
|
|
121
|
+
type: '{{ block.settings.pagination_type }}',
|
|
122
|
+
},
|
|
123
|
+
{% endif %}
|
|
124
|
+
{% if block.settings.show_navigation %}
|
|
125
|
+
navigation: {
|
|
126
|
+
nextEl: '#shopify-block-{{block.id}} .swiper-button-next',
|
|
127
|
+
prevEl: '#shopify-block-{{block.id}} .swiper-button-prev',
|
|
128
|
+
},
|
|
129
|
+
{% endif %}
|
|
130
|
+
{% if block.settings.autoplay %}
|
|
131
|
+
autoplay: {
|
|
132
|
+
delay: {{ block.settings.autoplay_delay | default: 4000 }},
|
|
133
|
+
disableOnInteraction: false,
|
|
134
|
+
pauseOnMouseEnter: true,
|
|
135
|
+
},
|
|
136
|
+
{% endif %}
|
|
137
|
+
breakpoints: {
|
|
138
|
+
0: {
|
|
139
|
+
slidesPerView: {{ block.settings.slides_per_view_mb | default: 1 }},
|
|
140
|
+
slidesPerGroup: {{ block.settings.slides_per_group_mb | default: 1 }},
|
|
141
|
+
},
|
|
142
|
+
1024: {
|
|
143
|
+
slidesPerView: {{ block.settings.slides_per_view_pc | default: 3 }},
|
|
144
|
+
slidesPerGroup: {{ block.settings.slides_per_group_pc | default: 1 }},
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
function initSwiper() {
|
|
150
|
+
if (initialized) return;
|
|
151
|
+
initialized = true;
|
|
152
|
+
instance = new Swiper(swiperSelector, options);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const root = block.querySelector(swiperSelector);
|
|
156
|
+
const io = new IntersectionObserver((entries) => {
|
|
157
|
+
entries.forEach((entry) => {
|
|
158
|
+
if (entry.isIntersecting) {
|
|
159
|
+
if (!initialized) initSwiper();
|
|
160
|
+
{% if block.settings.autoplay %}
|
|
161
|
+
if (instance && instance.autoplay) instance.autoplay.start();
|
|
162
|
+
{% endif %}
|
|
163
|
+
} else {
|
|
164
|
+
{% if block.settings.autoplay %}
|
|
165
|
+
if (instance && instance.autoplay) instance.autoplay.stop();
|
|
166
|
+
{% endif %}
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}, { threshold: 0.2 });
|
|
170
|
+
|
|
171
|
+
if (root) io.observe(root);
|
|
172
|
+
});
|
|
173
|
+
</script>
|
|
174
|
+
|
|
175
|
+
{% schema %}
|
|
176
|
+
{
|
|
177
|
+
"name": "ZZ Normal Swiper",
|
|
178
|
+
"class": "zz-normal-swiper-block",
|
|
179
|
+
"settings": [
|
|
180
|
+
{ "type": "color", "id": "bg_color", "default": "#ffffff", "label": "背景色" },
|
|
181
|
+
{ "type": "checkbox", "id": "loop", "label": "循环播放", "default": true },
|
|
182
|
+
{ "type": "range", "id": "speed", "label": "切换速度(ms)", "default": 500, "min": 100, "max": 5000, "step": 50 },
|
|
183
|
+
{ "type": "range", "id": "space_between", "label": "卡片间距(px)", "default": 8, "min": 0, "max": 80, "step": 2 },
|
|
184
|
+
{ "type": "checkbox", "id": "centered_slides", "label": "居中显示", "default": false },
|
|
185
|
+
{ "type": "checkbox", "id": "auto_height", "label": "自适应高度", "default": false },
|
|
186
|
+
|
|
187
|
+
{ "type": "checkbox", "id": "autoplay", "label": "自动播放", "default": false },
|
|
188
|
+
{ "type": "range", "id": "autoplay_delay", "label": "自动播放间隔(ms)", "default": 4000, "min": 1000, "max": 9500, "step": 500, "visible_if": "{{ block.settings.autoplay == true }}" },
|
|
189
|
+
|
|
190
|
+
{ "type": "select", "id": "pagination_type", "label": "分页器", "options": [
|
|
191
|
+
{ "value": "none", "label": "隐藏" },
|
|
192
|
+
{ "value": "bullets", "label": "圆点" },
|
|
193
|
+
{ "value": "fraction", "label": "分式" },
|
|
194
|
+
{ "value": "progressbar", "label": "进度条" }
|
|
195
|
+
], "default": "bullets" },
|
|
196
|
+
{ "type": "color", "id": "pagination_color", "default": "#000000", "label": "分页器颜色(PC)" },
|
|
197
|
+
{ "type": "color", "id": "mb_pagination_color", "default": "#000000", "label": "分页器颜色(Mobile)" },
|
|
198
|
+
|
|
199
|
+
{ "type": "checkbox", "id": "show_navigation", "label": "显示左右导航", "default": true },
|
|
200
|
+
{ "type": "checkbox", "id": "show_navigation_mobile", "label": "移动端显示导航", "default": false, "visible_if": "{{ block.settings.show_navigation == true }}" },
|
|
201
|
+
{ "type": "select", "id": "prev_next_type", "label": "导航颜色主题", "options": [ { "value": "dark", "label": "黑色" }, { "value": "light", "label": "白色" } ], "default": "dark" },
|
|
202
|
+
|
|
203
|
+
{ "type": "range", "id": "slides_per_view_mb", "label": "可见数(Mobile)", "default": 1, "min": 1, "max": 3, "step": 1 },
|
|
204
|
+
{ "type": "range", "id": "slides_per_group_mb", "label": "每次滑动(Mobile)", "default": 1, "min": 1, "max": 3, "step": 1 },
|
|
205
|
+
{ "type": "range", "id": "slides_per_view_pc", "label": "可见数(PC)", "default": 3, "min": 1, "max": 6, "step": 1 },
|
|
206
|
+
{ "type": "range", "id": "slides_per_group_pc", "label": "每次滑动(PC)", "default": 1, "min": 1, "max": 6, "step": 1 }
|
|
207
|
+
],
|
|
208
|
+
"blocks": [
|
|
209
|
+
{
|
|
210
|
+
"type": "@theme"
|
|
211
|
+
}
|
|
212
|
+
],
|
|
213
|
+
"presets": [
|
|
214
|
+
{
|
|
215
|
+
"name": "ZZ Normal Swiper",
|
|
216
|
+
"category": "ZZ Components",
|
|
217
|
+
"settings": {
|
|
218
|
+
"bg_color": "#ffffff",
|
|
219
|
+
"loop": true,
|
|
220
|
+
"speed": 500,
|
|
221
|
+
"space_between": 8,
|
|
222
|
+
"centered_slides": false,
|
|
223
|
+
"auto_height": false,
|
|
224
|
+
"autoplay": false,
|
|
225
|
+
"autoplay_delay": 4000,
|
|
226
|
+
"pagination_type": "bullets",
|
|
227
|
+
"pagination_color": "#000000",
|
|
228
|
+
"mb_pagination_color": "#000000",
|
|
229
|
+
"show_navigation": true,
|
|
230
|
+
"show_navigation_mobile": false,
|
|
231
|
+
"prev_next_type": "dark",
|
|
232
|
+
"slides_per_view_mb": 1,
|
|
233
|
+
"slides_per_group_mb": 1,
|
|
234
|
+
"slides_per_view_pc": 3,
|
|
235
|
+
"slides_per_group_pc": 1
|
|
236
|
+
},
|
|
237
|
+
"blocks": [
|
|
238
|
+
{ "type": "zz-flex-layout-block" },
|
|
239
|
+
{ "type": "zz-flex-layout-block" },
|
|
240
|
+
{ "type": "zz-flex-layout-block" }
|
|
241
|
+
]
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
{% endschema %}
|
package/docs/zz-modal.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
轻量、高性能、可扩展、可访问(a11y)的 Web Component 弹窗,基于原生 `<dialog>` 能力并内置降级方案。
|
|
2
|
+
|
|
3
|
+
### 特性
|
|
4
|
+
- 原生 `<dialog>`:内建焦点管理、`aria-modal`,退化时提供焦点陷阱与交互保障
|
|
5
|
+
- 高性能:零依赖、轻量动画、滚动锁、Backdrop 点击关闭、ESC 关闭
|
|
6
|
+
- 可扩展:Shadow DOM、`::part(...)`、CSS 变量、事件、编程式 API
|
|
7
|
+
- 易用:全局触发器 `[data-zz-modal-target]`、`[data-zz-modal-close]`
|
|
8
|
+
- 移动端 Drawer:加 `sheet-on-mobile` 时,小屏(≤768px)自下而上贴底弹出
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
### 快速开始(Shopify / Theme Section)
|
|
13
|
+
在 Section 中确保加载脚本(`sections/zz-modal.liquid` 已内置):
|
|
14
|
+
|
|
15
|
+
```liquid
|
|
16
|
+
<script defer id="zz-modal-js" src="{{ 'zz-modal.js' | asset_url }}"></script>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
无 JS 安全:
|
|
20
|
+
```css
|
|
21
|
+
zz-modal:not(:defined) { display: none !important; }
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Section 中通过 CSS 变量响应式配置:
|
|
25
|
+
```css
|
|
26
|
+
#your-modal-id {
|
|
27
|
+
--zz-modal-radius: {{ section.settings.radius_mobile }}px;
|
|
28
|
+
--zz-modal-padding: {{ section.settings.padding_mobile }}px;
|
|
29
|
+
--zz-modal-width: {{ section.settings.width_mobile }};
|
|
30
|
+
}
|
|
31
|
+
@media (min-width: 768px) {
|
|
32
|
+
#your-modal-id {
|
|
33
|
+
--zz-modal-radius: {{ section.settings.radius_pc }}px;
|
|
34
|
+
--zz-modal-padding: {{ section.settings.padding_pc }}px;
|
|
35
|
+
--zz-modal-width: {{ section.settings.width_pc }};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Section 设置项(当前实现):
|
|
41
|
+
- 基本:`modal_id`(必填,挂到 `<zz-modal id="...">` 上)
|
|
42
|
+
- 显隐:`show_header`、`show_footer`
|
|
43
|
+
- 行为:`no_backdrop_close`(禁用遮罩点击关闭)
|
|
44
|
+
- 文案:`header_text`、`footer_text`
|
|
45
|
+
- 尺寸(移动/PC):`width_mobile`、`width_pc`(支持 `px` 或 `vw`)
|
|
46
|
+
- 圆角(移动/PC):`radius_mobile`、`radius_pc`(单位 px)
|
|
47
|
+
- 内边距(移动/PC):`padding_mobile`、`padding_pc`(单位 px)
|
|
48
|
+
|
|
49
|
+
> 当 slot 为空时,组件会自动隐藏 Header/Footer(属性 `no-header-auto` / `no-footer-auto`)。
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### 基本用法
|
|
54
|
+
|
|
55
|
+
触发按钮 + 弹窗结构:
|
|
56
|
+
```html
|
|
57
|
+
<button data-zz-modal-target="#demo-modal">Open Modal</button>
|
|
58
|
+
|
|
59
|
+
<zz-modal id="demo-modal">
|
|
60
|
+
<div slot="header">标题</div>
|
|
61
|
+
<div>这里是内容</div>
|
|
62
|
+
<div slot="footer">
|
|
63
|
+
<button data-zz-modal-close>取消</button>
|
|
64
|
+
<button data-zz-modal-close>确定</button>
|
|
65
|
+
</div>
|
|
66
|
+
<!-- 内置关闭按钮也可用:shadow 内提供 part="close-button" 按钮 -->
|
|
67
|
+
<!-- 任何带 data-zz-modal-close 的元素都会关闭当前弹窗 -->
|
|
68
|
+
<!-- 任意元素 data-zz-modal-target="#id" 可打开对应弹窗 -->
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
移动端 Drawer 用法(≤768px 时贴底弹出):
|
|
72
|
+
```html
|
|
73
|
+
<zz-modal id="m1" sheet-on-mobile>
|
|
74
|
+
<div slot="header">标题</div>
|
|
75
|
+
<div>内容</div>
|
|
76
|
+
<div slot="footer"><button data-zz-modal-close>关闭</button></div>
|
|
77
|
+
<!-- Drawer 下 body 会自动为底部预留安全区 padding -->
|
|
78
|
+
</zz-modal>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### 编程式 API
|
|
84
|
+
```js
|
|
85
|
+
const modal = document.querySelector('#demo-modal');
|
|
86
|
+
modal.show(); // 打开
|
|
87
|
+
modal.hide(); // 关闭
|
|
88
|
+
modal.toggle(); // 切换
|
|
89
|
+
// 等价别名:modal.showModal() / modal.close()
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
### 属性(Attributes)
|
|
95
|
+
- `open`:受控显示状态(加上即显示,移除即关闭)
|
|
96
|
+
- `no-esc-close`:禁用 ESC 关闭
|
|
97
|
+
- `no-backdrop-close`:禁用点击遮罩关闭
|
|
98
|
+
- `no-scroll-lock`:禁用页面滚动锁
|
|
99
|
+
- `inert-others`:打开时让页面其它区域 inert(更强的可访问隔离)
|
|
100
|
+
- `no-header` / `no-footer`:强制隐藏 Header/Footer(无视 slot 内容)
|
|
101
|
+
- `no-header-auto` / `no-footer-auto`:组件自动加的属性,用于在对应 slot 为空时隐藏区域
|
|
102
|
+
- `sheet-on-mobile`:仅在小屏(≤768px)启用底部 Drawer 模式
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### 事件(Events)
|
|
107
|
+
- `zz-modal:open`
|
|
108
|
+
- `zz-modal:close`
|
|
109
|
+
|
|
110
|
+
监听示例:
|
|
111
|
+
```js
|
|
112
|
+
document.querySelector('#demo-modal')
|
|
113
|
+
.addEventListener('zz-modal:open', () => console.log('opened'));
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
### 样式定制
|
|
119
|
+
|
|
120
|
+
CSS 变量:
|
|
121
|
+
- `--zz-modal-width`(默认 `min(720px, 92vw)`)
|
|
122
|
+
- `--zz-modal-max-width`(默认 `90vw`)
|
|
123
|
+
- `--zz-modal-max-height`(默认 `85vh`)
|
|
124
|
+
- `--zz-modal-radius`(默认 `12px`)
|
|
125
|
+
- `--zz-modal-padding`(默认 `16px`)
|
|
126
|
+
- `--zz-modal-background`(默认 `#fff`)
|
|
127
|
+
- `--zz-modal-shadow`(默认 `0 20px 60px rgba(0,0,0,0.2)`)
|
|
128
|
+
- `--zz-modal-backdrop`(默认 `rgba(0,0,0,0.5)`)
|
|
129
|
+
- `--zz-modal-backdrop-filter`(默认 `blur(0px)`)
|
|
130
|
+
- `--zz-modal-z-index`(默认 `9999`)
|
|
131
|
+
- `--zz-sheet-width`(Drawer 模式宽度,默认 `100%`)
|
|
132
|
+
|
|
133
|
+
Shadow Parts:
|
|
134
|
+
- `dialog`、`backdrop`、`panel`、`header`、`body`、`footer`、`close-button`
|
|
135
|
+
|
|
136
|
+
示例:
|
|
137
|
+
```css
|
|
138
|
+
/* 外部覆盖内部部件样式 */
|
|
139
|
+
zz-modal::part(dialog) { max-width: 720px; }
|
|
140
|
+
zz-modal::part(panel) { border-radius: 16px; }
|
|
141
|
+
|
|
142
|
+
/* 使用变量 */
|
|
143
|
+
#demo-modal { --zz-modal-background: #111; color: #fff; }
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### 可访问性(a11y)
|
|
149
|
+
- 原生 `<dialog>` 优先,具备 `aria-modal`,ESC 关闭、焦点管理
|
|
150
|
+
- 降级路径提供基本焦点陷阱与键盘导航保障
|
|
151
|
+
- `inert-others` 可在打开时禁用页面其他区域交互
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
### 无 JS 安全
|
|
156
|
+
网络不佳或脚本未加载时隐藏 Light DOM,避免内容外露:
|
|
157
|
+
```css
|
|
158
|
+
zz-modal:not(:defined) { display: none !important; }
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
### 多实例
|
|
164
|
+
```html
|
|
165
|
+
<button data-zz-modal-target="#m1">打开 1</button>
|
|
166
|
+
<button data-zz-modal-target="#m2">打开 2</button>
|
|
167
|
+
|
|
168
|
+
<zz-modal id="m1">...</zz-modal>
|
|
169
|
+
<zz-modal id="m2">...</zz-modal>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
### 常见问题
|
|
175
|
+
- 遮罩点击无效?检查是否设置了 `no-backdrop-close`。
|
|
176
|
+
- 页面滚动未锁定?移除 `no-scroll-lock` 或确认 CSS 未覆盖 `overflow`。
|
|
177
|
+
- Header/Footer 不显示?若未显式设置 `show_header/show_footer`,请确保 slot 有内容;或移除 `no-header/no-footer`。
|
|
178
|
+
- 移动端仍居中?确认 `<zz-modal>` 标签加了 `sheet-on-mobile`,并且视口宽度 ≤ 768px。
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### 变更位置
|
|
183
|
+
- 组件实现:`assets/zz-modal.js`
|
|
184
|
+
- Section:`sections/zz-modal.liquid`
|
|
185
|
+
|
|
186
|
+
|
package/package.json
CHANGED
|
@@ -184,6 +184,11 @@
|
|
|
184
184
|
"label": "模块id",
|
|
185
185
|
"info": "用于定位到本模块"
|
|
186
186
|
},
|
|
187
|
+
{
|
|
188
|
+
"type": "text",
|
|
189
|
+
"id": "module_id",
|
|
190
|
+
"label": "唯一id",
|
|
191
|
+
},
|
|
187
192
|
],
|
|
188
193
|
"blocks": [
|
|
189
194
|
{
|
|
@@ -262,7 +267,7 @@
|
|
|
262
267
|
}
|
|
263
268
|
</style>
|
|
264
269
|
|
|
265
|
-
<div
|
|
270
|
+
<div id="{{ section.settings.module_id }}"
|
|
266
271
|
class="responsive-section-layout {{ section.settings.animation }}"
|
|
267
272
|
{% if section.settings.module_name != blank %}data-zz-module-name="{{ section.settings.module_name }}"{% endif %}>
|
|
268
273
|
{% content_for 'blocks' %}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
zz-modal:not(:defined) { display: none !important; }
|
|
3
|
+
/* Responsive modal variables from section settings */
|
|
4
|
+
#{{ section.settings.modal_id }} {
|
|
5
|
+
--zz-modal-radius: {{ section.settings.radius_mobile }}px;
|
|
6
|
+
--zz-modal-padding: {{ section.settings.padding_mobile }}px;
|
|
7
|
+
--zz-modal-width: {{ section.settings.width_mobile }};
|
|
8
|
+
}
|
|
9
|
+
@media (min-width: 768px) {
|
|
10
|
+
#{{ section.settings.modal_id }} {
|
|
11
|
+
--zz-modal-radius: {{ section.settings.radius_pc }}px;
|
|
12
|
+
--zz-modal-padding: {{ section.settings.padding_pc }}px;
|
|
13
|
+
--zz-modal-width: {{ section.settings.width_pc }};
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
|
|
18
|
+
<zz-modal {% if section.settings.sheet_on_mobile %} sheet-on-mobile {% endif %} {% if section.settings.no_backdrop_close %} no-backdrop-close {% endif %} id="{{ section.settings.modal_id }}"{% unless section.settings.show_header %} no-header{% endunless %}{% unless section.settings.show_footer %} no-footer{% endunless %}>
|
|
19
|
+
{% if section.settings.show_header %}
|
|
20
|
+
<div slot="header" class="tw-text-[24px] tw-font-semibold">{{ section.settings.header_text }}</div>
|
|
21
|
+
{% endif %}
|
|
22
|
+
{% content_for 'blocks' %}
|
|
23
|
+
{% if section.settings.show_footer %}
|
|
24
|
+
<div slot="footer" class="tw-flex tw-justify-end tw-gap-2 tw-pt-8">
|
|
25
|
+
<button class=" tw-text-[16px] " data-zz-modal-close>{{ section.settings.footer_text }}</button>
|
|
26
|
+
</div>
|
|
27
|
+
{% endif %}
|
|
28
|
+
</zz-modal>
|
|
29
|
+
|
|
30
|
+
<script>
|
|
31
|
+
(function(){
|
|
32
|
+
var id = 'zz-modal-js';
|
|
33
|
+
if (!document.getElementById(id)) {
|
|
34
|
+
var s = document.createElement('script');
|
|
35
|
+
s.id = id;
|
|
36
|
+
s.src = '{{ 'zz-modal.js' | asset_url }}';
|
|
37
|
+
s.defer = true;
|
|
38
|
+
document.head.appendChild(s);
|
|
39
|
+
}
|
|
40
|
+
})();
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
{% schema %}
|
|
44
|
+
{
|
|
45
|
+
"name": "ZZ Modal",
|
|
46
|
+
"settings": [
|
|
47
|
+
{
|
|
48
|
+
"type": "text",
|
|
49
|
+
"id": "modal_id",
|
|
50
|
+
"label": "弹窗id (必填)",
|
|
51
|
+
"default": "demo-modal"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"type": "checkbox",
|
|
55
|
+
"id": "show_header",
|
|
56
|
+
"label": "显示 Header",
|
|
57
|
+
"default": false
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"type": "text",
|
|
61
|
+
"id": "header_text",
|
|
62
|
+
"label": "弹窗标题",
|
|
63
|
+
"visible_if": "{{ section.settings.show_header }}",
|
|
64
|
+
"default": "弹窗标题"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"type": "checkbox",
|
|
68
|
+
"id": "sheet_on_mobile",
|
|
69
|
+
"label": "移动端变为底部抽屉模式",
|
|
70
|
+
"default": true
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"type": "checkbox",
|
|
74
|
+
"id": "show_footer",
|
|
75
|
+
"label": "显示 Footer",
|
|
76
|
+
"default": false
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"type": "text",
|
|
80
|
+
"id": "footer_text",
|
|
81
|
+
"label": "弹窗底部按钮文案",
|
|
82
|
+
"visible_if": "{{ section.settings.show_footer }}",
|
|
83
|
+
"default": "Close"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"type": "checkbox",
|
|
87
|
+
"id": "no_backdrop_close",
|
|
88
|
+
"label": "是否禁用遮罩点击关闭",
|
|
89
|
+
"default": false
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
{
|
|
93
|
+
"type": "text",
|
|
94
|
+
"id": "width_mobile",
|
|
95
|
+
"label": "移动端宽度(如 92vw 或 360px)",
|
|
96
|
+
"default": "92vw"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"type": "text",
|
|
100
|
+
"id": "width_pc",
|
|
101
|
+
"label": "PC 端宽度(如 720px 或 60vw)",
|
|
102
|
+
"default": "720px"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"type": "range",
|
|
106
|
+
"id": "radius_mobile",
|
|
107
|
+
"label": "移动端圆角(px)",
|
|
108
|
+
"min": 0,
|
|
109
|
+
"max": 40,
|
|
110
|
+
"step": 1,
|
|
111
|
+
"default": 12
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"type": "range",
|
|
115
|
+
"id": "radius_pc",
|
|
116
|
+
"label": "PC 端圆角(px)",
|
|
117
|
+
"min": 0,
|
|
118
|
+
"max": 40,
|
|
119
|
+
"step": 1,
|
|
120
|
+
"default": 12
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"type": "range",
|
|
124
|
+
"id": "padding_mobile",
|
|
125
|
+
"label": "移动端内边距(px)",
|
|
126
|
+
"min": 0,
|
|
127
|
+
"max": 48,
|
|
128
|
+
"step": 2,
|
|
129
|
+
"default": 16
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"type": "range",
|
|
133
|
+
"id": "padding_pc",
|
|
134
|
+
"label": "PC 端内边距(px)",
|
|
135
|
+
"min": 0,
|
|
136
|
+
"max": 64,
|
|
137
|
+
"step": 2,
|
|
138
|
+
"default": 20
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
],
|
|
142
|
+
"blocks": [
|
|
143
|
+
{
|
|
144
|
+
"type": "@theme",
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"presets": [
|
|
148
|
+
{
|
|
149
|
+
"name": "ZZ Modal",
|
|
150
|
+
"category": "ZZ Components"
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
{% endschema %}
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
@@ -205,7 +205,7 @@
|
|
|
205
205
|
tab.addEventListener('click', () => {
|
|
206
206
|
const id = tab.dataset.target;
|
|
207
207
|
const target = document.querySelector(`[data-zz-module-name="${id}"]`);
|
|
208
|
-
const headerHeight = isDesktop ? 64 :
|
|
208
|
+
const headerHeight = isDesktop ? 64 : 50;
|
|
209
209
|
const offsetTop = target.offsetTop - headerHeight;
|
|
210
210
|
scrollPaginationToCenter();
|
|
211
211
|
window.scrollTo(0, offsetTop);
|
|
@@ -247,8 +247,8 @@
|
|
|
247
247
|
if(isDesktop) {
|
|
248
248
|
currentSection.style.top = iptipsBoxHeight + 'px';
|
|
249
249
|
} else {
|
|
250
|
-
// 后期移动端要加上导航栏的高度
|
|
251
|
-
currentSection.style.top = iptipsBoxHeight +
|
|
250
|
+
// 后期移动端要加上导航栏的高度 50
|
|
251
|
+
currentSection.style.top = iptipsBoxHeight + 50 + 'px';
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
} else {
|
|
@@ -256,7 +256,7 @@
|
|
|
256
256
|
if(isDesktop) {
|
|
257
257
|
currentSection.style.top = '0px';
|
|
258
258
|
} else {
|
|
259
|
-
currentSection.style.top = '
|
|
259
|
+
currentSection.style.top = '50px';
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
262
|
} else {
|
|
@@ -371,7 +371,7 @@
|
|
|
371
371
|
@media screen and (max-width: 1024px) {
|
|
372
372
|
#shopify-section-{{ section.id }} {
|
|
373
373
|
z-index: 499;
|
|
374
|
-
top:
|
|
374
|
+
top: 50px;
|
|
375
375
|
}
|
|
376
376
|
#shopify-section-{{ section.id }} .{{ btn_class }} {
|
|
377
377
|
height: 28px;
|
|
@@ -143,9 +143,6 @@
|
|
|
143
143
|
<div class='swiper zz-shopping-cart-list-swiper'>
|
|
144
144
|
<div class='swiper-wrapper'>
|
|
145
145
|
{% for block in section.blocks %}
|
|
146
|
-
{%- comment %}<locksmith:881a>{% endcomment -%}
|
|
147
|
-
{%- capture var %}{% render 'locksmith-variables', scope: 'subject', subject: block.settings.product, subject_parent: section, variable: 'transparent' %}{% endcapture %}{% if var == "true" %}{% else %}{% continue %}{% endif -%}
|
|
148
|
-
{%- comment %}</locksmith:881a>{% endcomment -%}
|
|
149
146
|
<div class='swiper-slide {% if block_size > 1 %} max-lg:tw-pb-[60px] {% endif %}'>
|
|
150
147
|
<div class='banner-item tw-rounded-[10px] lg:tw-rounded-[16px] tw-flex tw-flex-col tw-justify-between'>
|
|
151
148
|
<div class='tw-h-[168px] lg:tw-h-[214px] tw-overflow-hidden tw-rounded-t-[10px] lg:tw-rounded-t-[16px] tw-flex-shrink-0'>
|