跳到正文
册页

动作

FloatingIconButton - 浮动图标按钮

钉在屏幕角落的圆形动作。

用法

什么时候用它

需要在滚动时始终够得到的页面级操作——回到顶部、移动端目录。
TSX
import { FloatingIconButton } from '@misoto22/folio'

说明

钉在屏幕角上的一个圆形动作。

用半透明的纸面加背景模糊,而不是投影——归白没有高度层级,所以把控件和它底下的页面分开的是这层模糊和那条细线,不是一圈光晕。

结构

FloatingIconButton anatomy
部件说明
控件盒子必填一个真正的 <button type="button">,--control-h-md 见方、胶囊圆角,以 --z-drawer 的层级 position: fixed 在底部某个角。这里没有 asChild 也没有 href:它变不成链接。
图标必填children,也是盒子里唯一的东西。不渲染任何文字形状的内容,所以控件就是那个正方形的宽度,不会再宽。
底色必填90% 的 --paper 铺在一层背景模糊上,外加一条 --rule-2 细线。White Reset 没有阴影梯度,所以把它从页面上托起来的是这层模糊和这条线,不是阴影。
名称必填label,作为 aria-label 设上去。它从不渲染,所以读屏用户拿到的是名字,看得见的读者只拿到那个图形。

实践建议

推荐

  • position 要写出来——它是必填、没有默认值,取值是按阅读顺序的 start 和 end。组件自己的文档示例写的是 position="right",那不在取值里,类型也过不了。
  • 图形不是人人都认得时,用 Tooltip 包住它:label 只是 aria-label,它只为读屏用户命名这个控件,别人拿不到——而 tooltip 在触屏上不会打开,偏偏浮动控件最常出现的地方就是触屏,也常常是屏幕上唯一的入口。
  • 最多两个。start 被特意抬到 5rem、end 停在 1.5rem,这点余量刚好够放一对;第三个已经无处可去,何况这几个角还要和 cookie 条、客服入口抢位置。
  • 页面有固定页脚时,用 className 把它挪开——类名会过一遍 tailwind-merge,所以 className="bottom-24" 是替换掉那个角偏移,而不是被它压过去。

避免

  • --control-h-md 在默认密度下是 44px,在 data-density="compact" 下是 36px,所以紧凑密度的页面会把整屏唯一一个要靠拇指盲点的控件,做得比 WCAG 2.5.5 的下限还小八个像素。
  • 它是 position: fixed,所以任何带 transform、filter 或 backdrop-filter 的祖先都会变成它的包含块——把它放进用 translate 居中的 DialogContent 里,它就钉在面板的角上,而不是屏幕的角上。
  • 它待在 --z-drawer,也就是 100,而每一个可能出现在它上面的层级都比它高:遮罩 200,模态 210,锚定面板 220——--z-dropdown 现在解析到 --z-anchored,不再是这一档。所以一个开进同一个角的菜单会把这个按钮整个盖住,而不是和它并列,对话框同样盖得住它。这里没有任何东西是靠文档顺序分先后的;如果它必须和别的东西并存又要够得着,就用 className 把它挪开。

示例

back to top

一个页面级的可用手段,读者一路往下滚它都还够得着。position 是必填的、没有默认值,取值按阅读顺序分 start 和 end——end 在英文里是右边,在阿拉伯文里是左边。label 会被设成 aria-label,永远不渲染出来,所以读屏软件拿到的是名字,而看得见的读者只拿到那个图形:要么挑一个自身就承载含义的图形,要么用 Tooltip 包起来。真实使用时这个控件固定在视口上;这里外面那个盒子是为了让预览诚实,因为一个 fixed 元素落在做过 transform 的祖先里,会钉在那个祖先上,而不是屏幕上。

a tooltip name

label 就是 aria-label,别无其他:它只为读屏软件命名这个控件,不为任何别人,所以一个并不通用的图形,还得把那个词也放到屏幕上。Tooltip 就是办法,但有一条在这里比在任何地方都要紧的注意事项——Radix 遇到触摸指针会提前返回,所以这个提示在手机上永远不会打开,而手机恰恰是浮动控件最常成为视野里唯一可用手段的地方。提示和 label 是同一个字符串,所以两者不会各走各的(WCAG 2.5.3)。

two corners

两个角落,以及为什么放不下第三个。start 被抬到 5rem,end 停在 1.5rem,这正是一对控件需要的净空——何况这些角落早就在跟 cookie 条、聊天入口,以及浏览器塞在阅读起点那个角上的东西抢地方,这也是为什么抬高的是 start 那一个。控件是 --control-h-md 的正方形:默认密度下 44px,正好压在指针目标的下限上,data-density="compact" 下是 36px。把上面那个密度开关拨过去,这个拇指不用看就去按的控件,就掉到下限以下八个像素。

无障碍

  • label 是这个控件唯一的名字,所以它是必填而不是可选。
  • 44px 见方,是指针目标的下限(WCAG 2.5.8)。