通过 headless UI tailwindcss 实现完全可访问的菜单组件
本博客重点介绍使用 tailwindcss 的 tailwind Labs 创建者提供的使用Headless UI在菜单组件中实现可访问性的最佳实践指导。
为什么可访问性很重要?
正如2021年一样,网络应该让更多人能够访问信息并进行互动。此外,通过网络技术,残障人士在阅读印刷、音频和视觉媒体方面遇到的障碍可以更容易克服,因此也应该为他们提供平等的访问渠道和机会。此外,这有助于在谷歌搜索结果中呈现最佳效果,并根据可用性进行排名,从而提升您的用户体验和产品。
我们将使用,
无头用户界面
- Tailwind CSS、Tailwind UI 和 Refactoring UI 的创建者。
Tailwindcss
- 通过不同的实用程序类,无需离开 HTML 即可快速构建现代网站。
HeadlessUI Dev 是一组完全无样式、完全可访问的 UI 组件,旨在与 Tailwind CSS 完美集成。
让我们从无头 UI 构建菜单组件
菜单用于导航并提供功能,是网页可操作性的关键部分。
用于 ReactJs
# npm
npm install @headlessui/react
# Yarn
yarn add @headlessui/react
基本示例
菜单按钮是使用菜单Menu.Button
、、Menu.Items
和Menu.Item
组件构建的。
单击 Menu.Button 时将自动打开/关闭 Menu.Items,当菜单打开时,项目列表将获得焦点并可通过键盘自动导航。
import { Menu } from "@headlessui/react";
function MyDropdown() {
return (
<Menu>
{/* Render no wrapper, instead pass in a button manually. */}
<Menu.Button as={React.Fragment}>
<button>More</button>
</Menu.Button>
<Menu.Items>
<Menu.Item>
{({ active }) => (
<a
className={`${active && "bg-blue-500"}`}
href="/account-settings"
>
Account settings
</a>
)}
</Menu.Item>
{/* ... */}
</Menu.Items>
</Menu>
);
}
上述代码是使用 headlessUI 实现的无样式组件。
有趣的是,如果我们看到下面生成的 HTML 版本,我们可以看到可访问性标签,并且通过使用 tailwindcss,可以使用内联类使其成为漂亮的 UI。
<div class="w-56 text-right fixed top-16">
<div class="relative inline-block text-left">
<div>
<button class="inline-flex justify-center w-full px-4 py-2 text-sm font-medium text-white bg-black rounded-md bg-opacity-20 hover:bg-opacity-30 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75" id="headlessui-menu-button-1" type="button" aria-haspopup="true">
Options <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5 ml-2 -mr-1 text-violet-200 hover:text-violet-100" aria-hidden="true"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
</button>
</div>
</div>
</div>
我们可以在button
标签中看到
type="button" aria-haspopup="true
此外,在下拉内容中
<div class="absolute right-0 w-56 mt-2 origin-top-right bg-white divide-y divide-gray-100 rounded-md shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
aria-labelledby="headlessui-menu-button-1" id="headlessui-menu-items-10" role="menu" tabindex="0">
<div class="px-1 py-1 " role="none">
<button class="text-gray-900 group flex rounded-md items-center w-full px-2 py-2 text-sm" id="headlessui-menu-item-11" role="menuitem"
tabindex="-1">
<svg class="w-5 h-5 mr-2" aria-hidden="true" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 13V16H7L16 7L13 4L4 13Z" fill="#EDE9FE" stroke="#A78BFA" stroke-width="2"></path>
</svg>
Edit
</button>
<button class="text-gray-900 group flex rounded-md items-center w-full px-2 py-2 text-sm" id="headlessui-menu-item-12" role="menuitem"
tabindex="-1">
<svg class="w-5 h-5 mr-2" aria-hidden="true" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 4H12V12H4V4Z" fill="#EDE9FE" stroke="#A78BFA" stroke-width="2"></path>
<path d="M8 8H16V16H8V8Z" fill="#EDE9FE" stroke="#A78BFA" stroke-width="2"></path>
</svg>
Duplicate
</button>
</div>
</div>
分解代码:
在下拉内容块中,我们有
<div class="..." aria-labelledby="headlessui-menu-button-1" id="headlessui-menu-items-10" role="menu" tabindex="0">...</div>
并且它的子 div 结构具有
<div class="..." role="none">
<button class="..." id="headlessui-menu-item-11" role="menuitem" tabindex="-1">...</button>
</div>
最终可访问性说明
1. 焦点管理:
点击Menu.Button
可切换菜单并聚焦于Menu.Items
组件。焦点会一直停留在打开的菜单中,直到按下 Esc 键或用户点击菜单外部。关闭菜单后,焦点将返回到Menu.Button
。
2. 鼠标交互
:点击Menu.Button
可切换菜单。点击已打开菜单之外的任意位置将关闭该菜单。
4. 其他
所有相关的 ARIA 属性均自动管理。
有关菜单中实现的所有辅助功能的完整参考,请参阅菜单按钮的 ARIA 规范。
参考
请查看https://headlessui.dev/react/menu了解更多详细信息,因为所有信息和代码示例在文档中都有更好的解释。
结论
👏👏 毫无疑问,https://headlessui.dev/是我开发 React 或 VueJs 项目的首选。我建议你在自己的项目中尝试一下,享受它带来的乐趣!
我从 tailwindcss 开发伊始就一直在编写它的类。这个框架的演变速度让我惊叹不已。非常感谢Adam Wathan和Steve Schoger开发了如此优秀的产品。请务必关注他们。
如果您有任何问题或疑问,请随时分享您的想法和意见并给我留言。
到那时,
继续黑客攻击,干杯