UNPKG

zz-shopify-components

Version:

Reusable Shopify components for theme projects

187 lines (147 loc) 5.9 kB
轻量、高性能、可扩展、可访问(a11y)的 Web Component 弹窗,基于原生 `<dialog>` 能力并内置降级方案。 ### 特性 - 原生 `<dialog>`:内建焦点管理、`aria-modal`,退化时提供焦点陷阱与交互保障 - 高性能:零依赖、轻量动画、滚动锁、Backdrop 点击关闭、ESC 关闭 - 可扩展:Shadow DOM、`::part(...)`、CSS 变量、事件、编程式 API - 易用:全局触发器 `[data-zz-modal-target]``[data-zz-modal-close]` - 移动端 Drawer:加 `sheet-on-mobile` 时,小屏(≤768px)自下而上贴底弹出 --- ### 快速开始(Shopify / Theme Section) 在 Section 中确保加载脚本(`sections/zz-modal.liquid` 已内置): ```liquid <script defer id="zz-modal-js" src="{{ 'zz-modal.js' | asset_url }}"></script> ``` 无 JS 安全: ```css zz-modal:not(:defined) { display: none !important; } ``` Section 中通过 CSS 变量响应式配置: ```css #your-modal-id { --zz-modal-radius: {{ section.settings.radius_mobile }}px; --zz-modal-padding: {{ section.settings.padding_mobile }}px; --zz-modal-width: {{ section.settings.width_mobile }}; } @media (min-width: 768px) { #your-modal-id { --zz-modal-radius: {{ section.settings.radius_pc }}px; --zz-modal-padding: {{ section.settings.padding_pc }}px; --zz-modal-width: {{ section.settings.width_pc }}; } } ``` Section 设置项(当前实现): - 基本:`modal_id`(必填,挂到 `<zz-modal id="...">` 上) - 显隐:`show_header``show_footer` - 行为:`no_backdrop_close`(禁用遮罩点击关闭) - 文案:`header_text``footer_text` - 尺寸(移动/PC):`width_mobile``width_pc`(支持 `px``vw`- 圆角(移动/PC):`radius_mobile``radius_pc`(单位 px) - 内边距(移动/PC):`padding_mobile``padding_pc`(单位 px) > 当 slot 为空时,组件会自动隐藏 Header/Footer(属性 `no-header-auto` / `no-footer-auto`)。 --- ### 基本用法 触发按钮 + 弹窗结构: ```html <button data-zz-modal-target="#demo-modal">Open Modal</button> <zz-modal id="demo-modal"> <div slot="header">标题</div> <div>这里是内容</div> <div slot="footer"> <button data-zz-modal-close>取消</button> <button data-zz-modal-close>确定</button> </div> <!-- 内置关闭按钮也可用:shadow 内提供 part="close-button" 按钮 --> <!-- 任何带 data-zz-modal-close 的元素都会关闭当前弹窗 --> <!-- 任意元素 data-zz-modal-target="#id" 可打开对应弹窗 --> ``` 移动端 Drawer 用法(≤768px 时贴底弹出): ```html <zz-modal id="m1" sheet-on-mobile> <div slot="header">标题</div> <div>内容</div> <div slot="footer"><button data-zz-modal-close>关闭</button></div> <!-- Drawer 下 body 会自动为底部预留安全区 padding --> </zz-modal> ``` --- ### 编程式 API ```js const modal = document.querySelector('#demo-modal'); modal.show(); // 打开 modal.hide(); // 关闭 modal.toggle(); // 切换 // 等价别名:modal.showModal() / modal.close() ``` --- ### 属性(Attributes) - `open`:受控显示状态(加上即显示,移除即关闭) - `no-esc-close`:禁用 ESC 关闭 - `no-backdrop-close`:禁用点击遮罩关闭 - `no-scroll-lock`:禁用页面滚动锁 - `inert-others`:打开时让页面其它区域 inert(更强的可访问隔离) - `no-header` / `no-footer`:强制隐藏 Header/Footer(无视 slot 内容) - `no-header-auto` / `no-footer-auto`:组件自动加的属性,用于在对应 slot 为空时隐藏区域 - `sheet-on-mobile`:仅在小屏(≤768px)启用底部 Drawer 模式 --- ### 事件(Events) - `zz-modal:open` - `zz-modal:close` 监听示例: ```js document.querySelector('#demo-modal') .addEventListener('zz-modal:open', () => console.log('opened')); ``` --- ### 样式定制 CSS 变量: - `--zz-modal-width`(默认 `min(720px, 92vw)`- `--zz-modal-max-width`(默认 `90vw`- `--zz-modal-max-height`(默认 `85vh`- `--zz-modal-radius`(默认 `12px`- `--zz-modal-padding`(默认 `16px`- `--zz-modal-background`(默认 `#fff`- `--zz-modal-shadow`(默认 `0 20px 60px rgba(0,0,0,0.2)`- `--zz-modal-backdrop`(默认 `rgba(0,0,0,0.5)`- `--zz-modal-backdrop-filter`(默认 `blur(0px)`- `--zz-modal-z-index`(默认 `9999`- `--zz-sheet-width`(Drawer 模式宽度,默认 `100%`) Shadow Parts: - `dialog``backdrop``panel``header``body``footer``close-button` 示例: ```css /* 外部覆盖内部部件样式 */ zz-modal::part(dialog) { max-width: 720px; } zz-modal::part(panel) { border-radius: 16px; } /* 使用变量 */ #demo-modal { --zz-modal-background: #111; color: #fff; } ``` --- ### 可访问性(a11y) - 原生 `<dialog>` 优先,具备 `aria-modal`,ESC 关闭、焦点管理 - 降级路径提供基本焦点陷阱与键盘导航保障 - `inert-others` 可在打开时禁用页面其他区域交互 --- ### 无 JS 安全 网络不佳或脚本未加载时隐藏 Light DOM,避免内容外露: ```css zz-modal:not(:defined) { display: none !important; } ``` --- ### 多实例 ```html <button data-zz-modal-target="#m1">打开 1</button> <button data-zz-modal-target="#m2">打开 2</button> <zz-modal id="m1">...</zz-modal> <zz-modal id="m2">...</zz-modal> ``` --- ### 常见问题 - 遮罩点击无效?检查是否设置了 `no-backdrop-close`- 页面滚动未锁定?移除 `no-scroll-lock` 或确认 CSS 未覆盖 `overflow`- Header/Footer 不显示?若未显式设置 `show_header/show_footer`,请确保 slot 有内容;或移除 `no-header/no-footer`- 移动端仍居中?确认 `<zz-modal>` 标签加了 `sheet-on-mobile`,并且视口宽度 ≤ 768px。 --- ### 变更位置 - 组件实现:`assets/zz-modal.js` - Section:`sections/zz-modal.liquid`