zz design system
mono & squared
组件 / 浮层

浮层

浮层是唯一允许脱离文档流的三个组件。它们不靠投影说话,而是用 1px 描边加--zz-elevation 表达「浮起来」,层级全部取自同一套 token:--zz-z-dropdown 200、--zz-z-modal 300、--zz-z-tooltip 400。

Modal · 模态对话框

遮罩是 --zz-bg-deep 的 72% 混合,压住下面整页(包括顶栏);面板居中, 最大宽 32rem、内距 1.5rem。打开时焦点进入面板,关闭后回到触发按钮,Esc 与点遮罩都能关。

Tooltip · 工具提示

纯 CSS,没有脚本:气泡是宿主的 ::after,文字来自content: attr(data-tooltip)。悬停或键盘焦点进入后 150ms 出现, 离开立刻收起,因此扫过一排按钮时不会闪出一串气泡。

悬停在文字上也会出现

Dropdown · 下拉菜单

用原生 <details> + <summary>:无 JS 时照样能开合, 键盘的 Enter / Space 也是浏览器自带的。脚本只补点击外部关闭与 Esc 关闭。

更多操作
贴右对齐

用法

---
import Modal from '@/components/ui/Modal.astro'
import Tooltip from '@/components/ui/Tooltip.astro'
import Dropdown from '@/components/ui/Dropdown.astro'
---

<Modal id="publish" label="发布前确认" trigger="发布站点">
  <h3 class="zz-modal__title">发布前确认</h3>
  <p class="zz-modal__desc">将替换线上版本。</p>
  <div class="zz-modal__actions">
    <button class="zz-btn zz-btn--ghost zz-btn--md" data-zz-modal-close>取消</button>
    <button class="zz-btn zz-btn--default zz-btn--md" data-zz-modal-close>开始发布</button>
  </div>
</Modal>

<Tooltip label="复制到剪贴板">复制</Tooltip>

<Dropdown label="更多操作">
  <a class="zz-dropdown__item" href="/docs">查看文档</a>
  <button class="zz-dropdown__item zz-dropdown__item--danger" data-zz-dropdown-close>删除</button>
</Dropdown>

类名与 token

类名 / token作用
.zz-modal全屏遮罩:fixed inset 0、--zz-z-modal、--zz-bg-deep 72% 混合底
.zz-modal__panel面板:最大宽 32rem、内距 1.5rem、--zz-surface 底 + --zz-elevation
.zz-modal__title / __desc / __actions面板内部的标题、说明与右对齐按钮行
[data-zz-modal-open]外部触发按钮,值是要打开的容器 id
[data-zz-modal-close]关闭按钮;[data-zz-modal-autofocus] 指定初始焦点
.zz-tooltip + [data-tooltip]宿主:相对定位 + 行内弹性;气泡由 ::after 用 attr() 渲染
.zz-dropdown<details> 容器:相对定位,summary 去掉默认三角
.zz-dropdown__menu菜单面板:绝对定位、--zz-z-dropdown、最小宽 10rem、--zz-surface 底
.zz-dropdown__item菜单项:弹性行、内距 0.375rem 0.625rem、0.8125rem,悬停 --zz-surface-2
.zz-dropdown__item--danger危险项:--zz-danger 文字,悬停 12% 危险色底
.zz-dropdown__chev / .zz-dropdown__sep展开时旋转 180° 的箭头;菜单里的分隔线
--zz-z-dropdown | --zz-z-modal | --zz-z-tooltip200 / 300 / 400,浮层只能用这三个值
--zz-elevation深色下是 1px 零模糊描边,亮色下补一层极轻投影

可访问性

  • 面板是 role="dialog" + aria-modal="true",必须有可访问名称(aria-label 或可见标题)。
  • 打开时焦点进入面板(优先 [data-zz-modal-autofocus]),Tab 在面板内循环;关闭后焦点回到触发按钮。
  • Esc 关闭最后打开的那一层;点遮罩关闭只在按下与抬起都落在遮罩上时生效,从面板里拖拽不会误关。
  • prefers-reduced-motion: reduce 下去掉遮罩淡入与面板的 scale(0.96) 动画,只保留显隐切换。
  • 提示气泡是纯 CSS 伪元素,读屏不保证播报;关键信息要写在可见文案或元素自身的 aria-label 里,气泡只做补充。
  • 下拉菜单用原生 <details>,展开状态与键盘操作由浏览器提供,因此不要加 role="menu";菜单项用真实的 <a> / <button>。
  • 焦点环沿用全局 :focus-visible,浮层里也不要用 outline: none 抹掉。