76 lines
3.1 KiB
CSS
76 lines
3.1 KiB
CSS
/* ===========================================================================
|
||
a11y 工具类:skip link + prefers-reduced-motion
|
||
自动从 src/styles.css 拆分(Stage 4a)
|
||
=========================================================================== */
|
||
|
||
/* ---------- skip link (Phase M) ----------
|
||
键盘用户 Tab 时第一站直达主内容(#viewer-main),跳过 9 个工具栏按钮 +
|
||
侧栏若干入口 + 排序切换。
|
||
- 默认视觉隐藏(不占布局、不抢 mouse 焦点),focus 时滑出右上角
|
||
- 用 `:focus-visible` 而非 `:focus`:鼠标点击不触发(避免每次点击
|
||
主页都闪一下右上角)
|
||
- z-index 高于 toolbar(toolbar 顶层 100),保证焦点环可见
|
||
*/
|
||
.skip-link {
|
||
position: absolute;
|
||
top: 8px;
|
||
right: 8px;
|
||
z-index: 1000;
|
||
padding: 8px 14px;
|
||
background: var(--accent, #4f8cff);
|
||
color: #fff;
|
||
text-decoration: none;
|
||
border-radius: 6px;
|
||
font-size: var(--fs-sm);
|
||
font-weight: 500;
|
||
/* 默认视觉隐藏但保留可访问性 —— 用 transform 移到屏外,不影响
|
||
屏幕阅读器在第一个 Tab 焦点候选里看到它 */
|
||
transform: translateY(-200%);
|
||
transition: transform 120ms ease-out;
|
||
}
|
||
.skip-link:focus,
|
||
.skip-link:focus-visible {
|
||
transform: translateY(0);
|
||
outline: 2px solid #fff;
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
/* skip link target —— #viewer-main 拿到焦点时去掉默认 outline
|
||
(它是"已抵达目的地"的反馈,不是交互元素),但保留 SR focus 语义 */
|
||
.viewer:focus,
|
||
.viewer:focus-visible {
|
||
outline: none;
|
||
}
|
||
|
||
/* ---------- prefers-reduced-motion ----------
|
||
关掉持续脉冲 (dirty-pulse / halo / ai-pulse) 与一次性入场动画
|
||
(modal / toast / ai-diff / ai-chat / outline-slide)。
|
||
用 0.01ms 而非 0 / animation: none:保留渲染状态(toast/modal 还要显示),
|
||
只是让用户「感知不到」动画过程。
|
||
兜底使用 * 选择器覆盖未来新增 keyframes,避免遗漏。
|
||
|
||
关键修复:去掉 `transition-duration: 0.01ms !important` —— 之前 blanket 会
|
||
杀掉所有 hover/focus 过渡(按钮悬停高亮、tab 切换、focus 环),让前庭敏感
|
||
用户失去所有交互反馈(与禁用动画的初衷相反)。
|
||
transition 是「用户主动操作触发的短暂反馈」(平均 120ms),不是「持续脉冲」
|
||
这类持续性刺激;前者对前庭敏感用户基本无害,后者才是真正需要关的。
|
||
见 [[feedback-ui-detail-polish]] —— 体验与无障碍要兼顾。
|
||
*/
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.btn-icon.is-dirty,
|
||
.btn-icon-text.is-dirty { animation: none; }
|
||
*,
|
||
*::before,
|
||
*::after {
|
||
animation-duration: 0.01ms !important;
|
||
animation-delay: 0 !important;
|
||
}
|
||
/* 阅读进度条是 width 过渡(非 animation),上面的 .01ms 规则收不掉它。
|
||
关掉过渡让进度"瞬切",避免每帧滚动触发持续的位置变化动画(前庭敏感用户)。 */
|
||
.reading-progress-bar { transition: none; }
|
||
/* 代码块复制按钮的 hover/active 颜色过渡 + 按下缩放也一并收掉 */
|
||
.code-copy-fab { transition: none; }
|
||
.code-copy-fab:active { transform: none; }
|
||
}
|
||
|