interaction-patterns

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Interaction Patterns

交互设计模式

Codifiable UI interaction patterns that prevent common UX failures. Covers loading states, content pagination, disclosure patterns, overlays, drag-and-drop, tab overflow, and notification systems — all with accessibility baked in.
可编码的UI交互设计模式,可避免常见的UX问题。涵盖加载状态、内容分页、展示模式、覆盖层、拖拽、标签栏溢出以及通知系统——所有模式均内置无障碍支持。

Quick Reference

快速参考

RuleFileImpactWhen to Use
Skeleton Loading
rules/interaction-skeleton-loading.md
HIGHContent-shaped placeholders for async data
Infinite Scroll
rules/interaction-infinite-scroll.md
CRITICALPaginated content with a11y and keyboard support
Progressive Disclosure
rules/interaction-progressive-disclosure.md
HIGHRevealing complexity based on user need
Modal / Drawer / Inline
rules/interaction-modal-drawer-inline.md
HIGHChoosing overlay vs inline display patterns
Drag & Drop
rules/interaction-drag-drop.md
CRITICALReorderable lists with keyboard alternatives
Tabs Overflow
rules/interaction-tabs-overflow.md
MEDIUMTab bars with 7+ items or dynamic tabs
Toast Notifications
rules/interaction-toast-notifications.md
HIGHSuccess/error feedback and notification stacking
Cognitive Load Thresholds
rules/interaction-cognitive-load-thresholds.md
HIGHEnforcing Miller's Law, Hick's Law, and Doherty Threshold with numeric limits
Form UX
rules/interaction-form-ux.md
HIGHTarget sizing, label placement, error prevention, and smart defaults
Persuasion Ethics
rules/interaction-persuasion-ethics.md
HIGHDetecting dark patterns and applying ethical engagement principles
Total: 10 rules across 6 categories
规则文件影响程度适用场景
骨架屏加载
rules/interaction-skeleton-loading.md
异步数据的内容形状占位符
无限滚动
rules/interaction-infinite-scroll.md
关键带a11y及键盘支持的分页内容
渐进式展示
rules/interaction-progressive-disclosure.md
根据用户需求逐步展示复杂内容
模态框/侧边栏/内联展示
rules/interaction-modal-drawer-inline.md
选择覆盖层 vs 内联展示模式
拖拽功能
rules/interaction-drag-drop.md
关键带键盘替代方案的可重排列表
标签栏溢出处理
rules/interaction-tabs-overflow.md
包含7个以上标签或动态标签的标签栏
通知提示
rules/interaction-toast-notifications.md
成功/错误反馈及通知堆叠
认知负荷阈值
rules/interaction-cognitive-load-thresholds.md
通过数值限制执行米勒定律、希克定律和多尔蒂阈值
表单UX
rules/interaction-form-ux.md
目标尺寸、标签布局、错误预防及智能默认值
说服伦理
rules/interaction-persuasion-ethics.md
检测暗黑模式并应用伦理参与原则
总计:6大类别下的10条规则

Decision Table — Loading States

决策表——加载状态

ScenarioPatternWhy
List/card content loadingSkeletonMatches content shape, reduces perceived latency
Form submissionSpinnerIndeterminate, short-lived action
File uploadProgress barMeasurable operation with known total
Image loadingBlur placeholderPrevents layout shift, progressive reveal
Route transitionSkeletonPreserves layout while data loads
Background syncNone / subtle indicatorNon-blocking, low priority
场景模式原因
列表/卡片内容加载骨架屏匹配内容形状,降低感知延迟
表单提交加载动画不确定时长的短期操作
文件上传进度条可衡量进度的已知总任务
图片加载模糊占位符防止布局偏移,渐进式展示
路由切换骨架屏数据加载时保留布局结构
后台同步无/细微指示器非阻塞、低优先级任务

Quick Start

快速上手

Skeleton Loading

骨架屏加载

tsx
function CardSkeleton() {
  return (
    <div className="animate-pulse space-y-3">
      <div className="h-48 w-full rounded-lg bg-muted" />
      <div className="h-4 w-3/4 rounded bg-muted" />
      <div className="h-4 w-1/2 rounded bg-muted" />
    </div>
  )
}

function CardList({ items, isLoading }: { items: Item[]; isLoading: boolean }) {
  if (isLoading) {
    return (
      <div className="grid grid-cols-3 gap-4">
        {Array.from({ length: 6 }).map((_, i) => (
          <CardSkeleton key={i} />
        ))}
      </div>
    )
  }
  return (
    <div className="grid grid-cols-3 gap-4">
      {items.map((item) => <Card key={item.id} item={item} />)}
    </div>
  )
}
tsx
function CardSkeleton() {
  return (
    <div className="animate-pulse space-y-3">
      <div className="h-48 w-full rounded-lg bg-muted" />
      <div className="h-4 w-3/4 rounded bg-muted" />
      <div className="h-4 w-1/2 rounded bg-muted" />
    </div>
  )
}

function CardList({ items, isLoading }: { items: Item[]; isLoading: boolean }) {
  if (isLoading) {
    return (
      <div className="grid grid-cols-3 gap-4">
        {Array.from({ length: 6 }).map((_, i) => (
          <CardSkeleton key={i} />
        ))}
      </div>
    )
  }
  return (
    <div className="grid grid-cols-3 gap-4">
      {items.map((item) => <Card key={item.id} item={item} />)}
    </div>
  )
}

Infinite Scroll with Accessibility

带无障碍支持的无限滚动

tsx
function InfiniteList({ fetchNextPage, hasNextPage, items }: Props) {
  const sentinelRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting && hasNextPage) fetchNextPage() },
      { rootMargin: "200px" }
    )
    if (sentinelRef.current) observer.observe(sentinelRef.current)
    return () => observer.disconnect()
  }, [fetchNextPage, hasNextPage])

  return (
    <div role="feed" aria-busy={isFetching}>
      {items.map((item) => (
        <article key={item.id} aria-posinset={item.index} aria-setsize={-1}>
          <ItemCard item={item} />
        </article>
      ))}
      <div ref={sentinelRef} />
      {hasNextPage && (
        <button onClick={() => fetchNextPage()}>Load more items</button>
      )}
      <div aria-live="polite" className="sr-only">
        {`Showing ${items.length} items`}
      </div>
    </div>
  )
}
tsx
function InfiniteList({ fetchNextPage, hasNextPage, items }: Props) {
  const sentinelRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting && hasNextPage) fetchNextPage() },
      { rootMargin: "200px" }
    )
    if (sentinelRef.current) observer.observe(sentinelRef.current)
    return () => observer.disconnect()
  }, [fetchNextPage, hasNextPage])

  return (
    <div role="feed" aria-busy={isFetching}>
      {items.map((item) => (
        <article key={item.id} aria-posinset={item.index} aria-setsize={-1}>
          <ItemCard item={item} />
        </article>
      ))}
      <div ref={sentinelRef} />
      {hasNextPage && (
        <button onClick={() => fetchNextPage()}>Load more items</button>
      )}
      <div aria-live="polite" className="sr-only">
        {`Showing ${items.length} items`}
      </div>
    </div>
  )
}

Rule Details

规则详情

Skeleton Loading

骨架屏加载

Content-shaped placeholders that match the final layout. Use skeleton for lists, cards, and text blocks.
Load:
rules/interaction-skeleton-loading.md
与最终布局匹配的内容形状占位符。适用于列表、卡片和文本块。
查看详情:
rules/interaction-skeleton-loading.md

Infinite Scroll

无限滚动

Accessible infinite scroll with IntersectionObserver, screen reader announcements, and "Load more" fallback.
Load:
rules/interaction-infinite-scroll.md
基于IntersectionObserver的无障碍无限滚动,包含屏幕阅读器播报及“加载更多”备选方案。
查看详情:
rules/interaction-infinite-scroll.md

Progressive Disclosure

渐进式展示

Reveal complexity progressively: tooltip, accordion, wizard, contextual panel.
Load:
rules/interaction-progressive-disclosure.md
逐步展示复杂内容:工具提示、折叠面板、向导流程、上下文面板。
查看详情:
rules/interaction-progressive-disclosure.md

Modal / Drawer / Inline

模态框/侧边栏/内联展示

Choose the right overlay pattern: modal for confirmations, drawer for detail views, inline for simple toggles.
Load:
rules/interaction-modal-drawer-inline.md
选择合适的覆盖层模式:模态框用于确认操作,侧边栏用于详情查看,内联展示用于简单切换。
查看详情:
rules/interaction-modal-drawer-inline.md

Drag & Drop

拖拽功能

Drag-and-drop with mandatory keyboard alternatives using
@dnd-kit/core
.
Load:
rules/interaction-drag-drop.md
基于
@dnd-kit/core
实现的带强制键盘替代方案的拖拽功能。
查看详情:
rules/interaction-drag-drop.md

Tabs Overflow

标签栏溢出处理

Scrollable tab bars with overflow menus for dynamic or numerous tabs.
Load:
rules/interaction-tabs-overflow.md
针对动态标签或大量标签的可滚动标签栏及溢出菜单。
查看详情:
rules/interaction-tabs-overflow.md

Toast Notifications

通知提示

Positioned, auto-dismissing notifications with ARIA roles and stacking.
Load:
rules/interaction-toast-notifications.md
带定位、自动关闭功能的通知,包含ARIA角色及堆叠支持。
查看详情:
rules/interaction-toast-notifications.md

Cognitive Load Thresholds

认知负荷阈值

Miller's Law (max 7 items per group), Hick's Law (max 1 primary CTA), and Doherty Threshold (400ms feedback) with specific, countable limits.
Load:
rules/interaction-cognitive-load-thresholds.md
米勒定律(每组最多7个选项)、希克定律(最多1个主要CTA)和多尔蒂阈值(400ms反馈)的具体数值限制。
查看详情:
rules/interaction-cognitive-load-thresholds.md

Form UX

表单UX

Fitts's Law touch targets (44px mobile), top-aligned labels, Poka-Yoke error prevention with blur-only validation, and smart defaults.
Load:
rules/interaction-form-ux.md
基于菲茨定律的触摸目标(移动端44px)、顶部对齐标签、防错设计的失焦验证及智能默认值。
查看详情:
rules/interaction-form-ux.md

Persuasion Ethics

说服伦理

13 dark pattern red flags to detect and reject, the Hook Model ethical test (aware, reversible, user-benefits), and EU DSA Art. 25 compliance.
Load:
rules/interaction-persuasion-ethics.md
13种需识别并拒绝的暗黑模式红牌、钩子模型伦理测试(知情、可逆、用户受益)以及欧盟DSA第25条合规要求。
查看详情:
rules/interaction-persuasion-ethics.md

Key Principles

核心原则

  1. Keyboard parity — Every mouse interaction MUST have a keyboard equivalent. No drag-only, no hover-only.
  2. Skeleton over spinner — Use content-shaped placeholders for data loading; reserve spinners for indeterminate actions.
  3. Native HTML first — Prefer
    <dialog>
    ,
    <details>
    ,
    role="feed"
    over custom implementations.
  4. Progressive enhancement — Features should work without JS where possible, then enhance with interaction.
  5. Announce state changes — Use
    aria-live
    regions to announce dynamic content changes to screen readers.
  6. Respect scroll position — Back navigation must restore scroll position; infinite scroll must not lose user's place.
  1. 键盘对等性——所有鼠标交互必须有对应的键盘操作方式。不允许仅支持拖拽或仅支持悬停的交互。
  2. 优先使用骨架屏而非加载动画——数据加载时使用内容形状占位符;加载动画仅用于不确定时长的操作。
  3. 优先使用原生HTML——优先使用
    <dialog>
    <details>
    role="feed"
    而非自定义实现。
  4. 渐进式增强——功能应在无JS环境下可正常使用,再通过交互进行增强。
  5. 播报状态变化——使用
    aria-live
    区域向屏幕阅读器播报动态内容变化。
  6. 尊重滚动位置——返回导航必须恢复滚动位置;无限滚动不得丢失用户当前位置。

Anti-Patterns (FORBIDDEN)

反模式(禁止使用)

  • Spinner for content loading — Spinners give no spatial hint. Use skeletons matching the content shape.
  • Infinite scroll without Load More — Screen readers and keyboard users cannot reach footer content. Always provide a button fallback.
  • Modal for browsable content — Modals trap focus and block interaction. Use drawers or inline expansion for browsing.
  • Drag-only reorder — Excludes keyboard and assistive tech users. Always provide arrow key + Enter alternatives.
  • Toast without ARIA role — Toasts are invisible to screen readers. Use
    role="status"
    for success,
    role="alert"
    for errors.
  • Auto-dismiss error toasts — Users need time to read errors. Never auto-dismiss error notifications.
  • 内容加载使用加载动画——加载动画无法提供空间提示。应使用匹配内容形状的骨架屏。
  • 无限滚动无“加载更多”按钮——屏幕阅读器和键盘用户无法触达页脚内容。必须提供按钮备选方案。
  • 可浏览内容使用模态框——模态框会锁定焦点并阻止交互。浏览内容应使用侧边栏或内联展开。
  • 仅支持拖拽的重排功能——排除了键盘及辅助技术用户。必须提供方向键+回车的替代方案。
  • 无ARIA角色的通知提示——通知提示对屏幕阅读器不可见。成功提示使用
    role="status"
    ,错误提示使用
    role="alert"
  • 错误提示自动关闭——用户需要时间阅读错误信息。禁止自动关闭错误通知。

Detailed Documentation

详细文档

ResourceDescription
references/loading-states-decision-tree.mdDecision tree for skeleton vs spinner vs progress bar
references/interaction-pattern-catalog.mdCatalog of 15+ interaction patterns with when-to-use guidance
references/keyboard-interaction-matrix.mdKeyboard shortcuts matrix for all interactive patterns (WAI-ARIA APG)
资源说明
references/loading-states-decision-tree.md骨架屏vs加载动画vs进度条的决策树
references/interaction-pattern-catalog.md包含15+种交互模式及适用场景的目录
references/keyboard-interaction-matrix.md所有交互模式的键盘快捷键矩阵(符合WAI-ARIA APG)

Related Skills

相关技能

  • ork:ui-components
    — shadcn/ui component patterns and CVA variants
  • ork:animation-motion-design
    — Motion library and View Transitions API
  • ork:accessibility
    — WCAG compliance, ARIA patterns, screen reader support
  • ork:responsive-patterns
    — Responsive layout and container query patterns
  • ork:performance
    — Core Web Vitals and runtime performance optimization
  • ork:ui-components
    — shadcn/ui组件模式及CVA变体
  • ork:animation-motion-design
    — 动效库及View Transitions API
  • ork:accessibility
    — WCAG合规、ARIA模式、屏幕阅读器支持
  • ork:responsive-patterns
    — 响应式布局及容器查询模式
  • ork:performance
    — Core Web Vitals及运行时性能优化