如何使用 Chakra UI 和 Nuxt.js 构建可访问的前端应用程序

已发表: 2022-03-10
快速总结↬在本文中,我们将研究如何使用 Chakra UI 和 NuxtJS 构建可访问的前端应用程序。 为了继续学习,您应该熟悉将渐进式前端框架 Vue.js 与 Nuxt 一起使用。 如果没有,请参阅 Vue.js 和 NuxtJS 文档以开始使用。

对于许多人来说,网络是他们日常生活中必不可少的一部分。 他们在工作、家中甚至在路上都使用它。 网络无障碍意味着残障人士可以平等地使用网络。 因此,对于在 Web 上构建的开发人员和组织而言,在其应用程序中构建包容性和可访问性至关重要。

为了使 Web 更易于访问,您必须在应用程序中实施一些最佳实践和标准,例如遵守以下内容:

  • 第 508 条;
  • 辅助技术法;
  • 美国残疾人法案(ADA);
  • WCAG 2.0(A 和 AA 指南);
  • BBC 移动无障碍指南;
  • WAI - ARIA (Web访问性倡议——可访问丰富互联网应用)实践。

当您将项目截止日期和作为开发人员必须处理的其他限制因素考虑在内时,学习实施这些标准似乎是一项艰巨的任务。 鉴于此,让我向您介绍一个 UI 设计系统,该系统旨在帮助您使您的 Web 应用程序易于访问。

脉轮用户界面

Chakra UI 是由 Segun Adebayo 创建的设计系统和 UI 框架。 它的创建考虑了简单性、模块化、可组合性和可访问性。 Chakra UI 为您提供了创建可访问的前端应用程序所需的所有构建块。

注意虽然 Chakra UI 在底层依赖于 CSS-in-JS,但您无需了解它即可使用该库。

尽管该框架最初是为 React 创建的,但 Jonathan Bakebwa 率先将移植到 Vue。 因此,Vuejs/NuxtJS 开发人员现在可以利用 Chakra UI 创建可访问的 Web 应用程序。

脉轮用户界面的特点

Chakra UI 的创建考虑了以下原则:

  • 风格道具
    Chakra UI 可以通过使用 props 来设置组件样式或覆盖它们的样式。 这减少了对样式表或内联样式的需求。 Chakra UI 通过在后台使用 Styled Systems 实现了这种级别的灵活性。
  • 作品
    Chakra UI 中的组件已被分解为具有最少道具的较小部分,以保持较低的复杂性,并将它们组合在一起。 这将确保样式和功能是灵活和可扩展的。 例如,您可以使用CBoxCPseudoBox组件来创建新组件。
  • 无障碍
    Chakra UI 组件遵循 WAI-ARIA 指南规范并具有正确的 aria-* 属性。 您还可以在名为accessibility.md的文件中找到每个编写组件的可访问性报告。 请参阅CAccordion组件的可访问性报告。
  • 主题化
    Chakra UI 使您能够在整个应用程序中的任何组件上轻松引用主题中的值。
  • 暗模式支持
    Chakra UI 中的大多数组件都是开箱即用的暗模式兼容。

Chakra UI 如何支持可访问性

创建 Chakra UI 背后的核心原则之一是可访问性。 考虑到这一点,Chakra UI 中的所有组件都是开箱即用的,通过提供以下功能支持可访问性:

  • 键盘导航——对有运动技能障碍的用户有用,
  • 焦点管理,
  • 屏幕阅读器所需的 aria-* 属性,
  • 模态对话框的焦点捕获和恢复。
跳跃后更多! 继续往下看↓

Chakra UI 和 Nuxt 入门

注意要将 Chakra UI 与 Vue.js 一起使用,请参阅入门指南。

对于我们的演示项目,我们将构建Chakra-ui 浏览器——一个可访问的单页 Web 应用程序,用于搜索 Chakra UI 组件。

  • 在 Netlify 上查看实时项目 →

Chakra-ui Explorer 入门

假设你已经安装了 NPM,通过运行创建一个新的 Nuxt 应用程序:

 $ npx create-nuxt-app chakra-ui-explorer

或者,如果您更喜欢使用纱线,请运行:

 $ yarn create nuxt-app chakra-ui-explorer

按照安装提示完成创建 Nuxt 应用程序。

设置脉轮 UI

Chakra UI 使用 Emotion 来处理组件样式。 因此,要开始使用 Chakra UI,您需要将 Chakra UI 与 Emotion 作为对等依赖项一起安装。 对于这个项目,我们将为 Chakra UI 和 Emotion 使用官方 Nuxt 模块,这将减少开始使用 Chakra UI 时的摩擦。 让我们通过运行以下命令将它们添加到我们的项目中:

 npm i @chakra-ui/nuxt @nuxtjs/emotion

注意@nuxtjs/emotion允许在服务器构建中生成和注入组件样式。

安装这两个模块后,您需要在模块数组选项下的nuxt.config.js文件中注册它们:

 // nuxt.config.js modules: ['@chakra-ui/nuxt', '@nuxtjs/emotion'],

要完成 Chakra UI 的设置过程,我们需要在layouts/中触摸我们的默认布局组件,并从 Chakra UI 添加CThemeProviderCColorModeProviderCReset组件。

建议您使用CReset组件以确保 Chakra UI 提供的所有组件都能正常工作。

CThemeProvider组件将使您的主题可用于应用程序的每个部分,而CColorModeProvider组件负责处理应用程序的颜色模式,该模式可以处于以下两种状态之一:浅色或深色。 最后, CReset组件将删除所有浏览器默认样式。

让我们在layouts/default.vue中添加上述组件。 在我们的模板部分,让我们添加:

 <!-- layouts/default.vue --> <template> <div class="container"> <c-theme-provider> <c-color-mode-provider> <c-box as="section"> <c-reset /> <nuxt /> </c-box> </c-color-mode-provider> </c-theme-provider> </div> </template>

然后在我们的脚本部分,我们将像这样导入和注册组件:

 <script> import { CThemeProvider, CColorModeProvider, CReset, CBox } from '@chakra-ui/vue' export default { name: 'DefaultLayout', components: { CThemeProvider, CColorModeProvider, CReset, CBox } } </script>

您的default.vue布局组件应如下所示:

 <template> <div class="container"> <c-theme-provider> <c-color-mode-provider> <c-box as="section"> <c-reset /> <nuxt /> </c-box> </c-color-mode-provider> </c-theme-provider> </div> </template> <script> import { CThemeProvider, CColorModeProvider, CReset, CBox } from '@chakra-ui/vue' export default { name: 'DefaultLayout', components: { CThemeProvider, CColorModeProvider, CReset, CBox } } </script>

注意请注意,我将<c-reset /><nuxt />组件都包装在一个c-box组件中。

设置您的应用程序主题

Chakra UI 允许您为应用程序设置主题。 “主题”是指应用程序的调色板、类型比例、字体堆栈、断点、边框半径值等的设置。 由于颜色和对比度是可访问性的重要组成部分,因此使用易于感知的颜色非常重要。

开箱即用的 Chakra UI 附带一个默认主题对象,可满足您应用程序在颜色、字体等方面的大部分需求。 默认主题的设置考虑了对比度,可以轻松切换颜色模式(稍后会详细介绍)。

但是,Chakra UI 允许您扩展或完全替换默认主题。 这可以通过接受基于样式系统主题规范的主题对象来实现。

主题对象中的值会自动在您的应用程序中使用。 例如,在theme.colors中指定的颜色可以被组件中的colorborderColorbackgroundColorfillstrokestyle属性引用。

要个性化您的应用程序,您可以覆盖 Chakra UI 提供的默认主题或在其中设置新值。 为此,Chakra UI Nuxt 模块公开了一个chakra对象,该对象将接受一个extendTheme属性,该属性接受一个对象。 赋予extendTheme的对象将递归合并到 Chakra UI 默认主题对象。 让我们将我们的品牌调色板添加到 Chakra,以便我们可以在我们的应用程序中使用它。

注意Chakra UI 建议使用从 50 到 900 的键将调色板添加到主题的颜色对象中。您可以使用 Coolors 和 palx 等 Web 工具来生成这些调色板。

对于我们的演示主页,我将使用石灰的品牌颜色。 为了让 Chakra UI 知道这种颜色,我将在我的项目目录的根目录中名为chakra的文件夹中创建一个customeTheme对象(你可以随意调用它)。 在这个对象中,我将定义我们的品牌调色板。

在您创建的文件夹中创建一个名为theme.js的文件,然后添加以下代码段:

 // ./chakra/theme.js const customTheme = { colors: { brand: { 50: '#f6fcee', 100: '#e2f4c8', 200: '#cbec9e', 300: '#b2e26e', 400: '#94d736', 500: '#75c800', 600: '#68b300', 700: '#599900', 800: '#477900', 900: '#294700' } } } module.exports = customTheme

现在让我们将自定义主题合并到 Chakra UI。 我们在nuxt.config.js中这样做。 首先,我们需要自定义主题对象:

 import customTheme from './chakra/theme'

接下来,我们必须指定 Chakra UI Nuxt 模块提供的chakra密钥,并将customTheme传递给extendTheme属性:

 chakra: { extendTheme: customTheme },

您的nuxt.config.js文件应如下所示:

 // nuxt.config.js import customTheme from './chakra/theme' export default { mode: 'spa', /* * Headers of the page */ head: { title: process.env.npm_package_name || '', meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: process.env.npm_package_description || '' } ], link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }] }, /* * Customize the progress-bar color */ loading: { color: '#fff' }, /* * Global CSS */ css: [], /* * Plugins to load before mounting the App */ plugins: [], /* * Nuxt.js dev-modules */ buildModules: [ // Doc: https://github.com/nuxt-community/eslint-module '@nuxtjs/eslint-module' ], /* * Nuxt.js modules */ modules: [ '@chakra-ui/nuxt', '@nuxtjs/emotion' ], chakra: { extendTheme: customTheme }, /* * Build configuration */ build: { /* * You can extend webpack config here */ extend (config, ctx) {} } }

当您使用npm run dev运行应用程序时,您的主页应该如下所示:

展示 Chakra UI 和 NuxtJS 的演示应用程序
(大预览)

现在我们已经成功安装了 Chakra UI 并添加了我们应用程序的自定义主题,让我们开始构建 Chakra-ui 浏览器。

创建我们的主导航

我们希望我们的导航有我们的品牌名称,在这种情况下,它将是Chakra-ui explorer 、2 个导航链接:文档Repo ,以及一个负责切换颜色模式的按钮。 让我们在名为NavBarcomponents目录下创建一个新组件,我们将在其中使用 Chakra UI 创建应用程序的主导航。

我们开工吧。 将以下代码段添加到NavBar.vue

 <template> <c-box as="nav" h="60px" px="4" d="flex" align-items="center" shadow="sm" > <c-link as="nuxt-link" to="/" color="brand.700" font-weight="bold" :_hover="{ color: 'brand.900' }" > Chakra-ui Explorer </c-link> <c-box as="ul" color="gray.500" d="flex" align-items="center" list-style-type="none" ml="auto" > <c-box as="li" mr="8"> <c-link color="gray.500" :_hover="{ color: 'brand.400' }" is-external href="https://vue.chakra-ui.com" > Documentation </c-link> </c-box> <c-box as="li" mr="8"> <c-link color="gray.500" :_hover="{ color: 'brand.400' }" is-external href="https://github.com/chakra-ui/chakra-ui-vue" > Repo </c-link> </c-box> <c-box as="li"> <c-icon-button variant="ghost" variant-color="gray[900]" aria-label="Switch to dark mode" icon="moon" /> </c-box> </c-box> </c-box> </template> <script> import { CBox, CLink, CIconButton } from '@chakra-ui/vue' export default { name: 'NavBar', components: { CBox, CLink, CIconButton } } </script>

接下来,我们需要在我们的默认布局组件default.vue中导入这个组件并将其添加到我们的模板中,因此我们的默认布局总体上应该如下所示:

 <template> <div class="container"> <c-theme-provider> <c-color-mode-provider> <c-box as="section"> <c-reset /> <nav-bar /> <nuxt /> </c-box> </c-color-mode-provider> </c-theme-provider> </div> </template> <script> import { CThemeProvider, CColorModeProvider, CReset, CBox } from '@chakra-ui/vue' import NavBar from '@/components/NavBar' export default { name: 'DefaultLayout', components: { CThemeProvider, CColorModeProvider, CReset, CBox, NavBar } } </script>

当你现在运行你的应用程序时,你会看到:

您可以看到导航已经可以访问,甚至无需指定它。 这只能在您按键盘上的Tab键时看到; Chakra UI 处理焦点管理,而您可以专注于导航菜单上的每个链接。

as道具

从上面的NavBar.vue片段中,您会注意到as属性。 这是 Chakra UI 组件可用的功能,它允许您传递 HTML 标记或另一个组件以作为组件的基本标记连同其所有样式和道具一起呈现。 所以当我们这样做时:

 <c-box as="li"> <c-icon-button variant="ghost" variant-color="gray[900]" aria-label="Switch to dark mode" icon="moon" /> </c-box>

我们要求 Chakra UI 渲染一个<li>元素并在其中放置一个按钮组件。 您还可以在此处看到我们使用该模式:

 <c-link as="nuxt-link" to="/" color="brand.700" font-weight="bold" :_hover="{ color : 'brand.900' }"> ChakraMart </c-link>

在上述情况下,我们要求 Chakra UI 渲染 Nuxt 的 <nuxt-link /> 组件。

as属性使您能够在标记的上下文中使用正确(或错误)元素。 这意味着,您可以利用它来使用语义标记构建您的应用程序模板,这将使您的应用程序对屏幕阅读器更有意义。 因此,不用为应用程序的主要内容使用通用的div元素,而是使用as属性渲染一个main元素,告诉屏幕阅读器这是应用程序的主要内容。

注意查看 Chakra UI 组件公开的所有道具的文档。 此外,请仔细查看chakra/theme.js中的品牌颜色是如何指定的。 您可以从上面的代码片段中看到,我们将它用作 Chakra UI 提供的任何颜色。 要注意的另一件事是我们在导航栏上用于CIconButtonmoon图标。 moon图标是 Chakra UI 提供的默认图标之一。

颜色模式

Chakra UI 的功能之一是颜色模式支持。 从 Chakra-ui 浏览器导航中moon图标的使用可以看出,我们计划集成暗模式。 因此,与其把它留到最后,让我们把它结束并立即连接起来。 为此, CColorModeProvider使用 Vue 的提供/注入、提供、 $chakraColorMode$toggleColorMode函数。 $chakraColorMode返回应用程序的当前颜色模式,而$toggleColorMode将颜色模式从light切换到dark ,反之亦然。 要使用这两个函数,我们需要将它们注入到NavBar.vue组件中。 让我们在下面的<script />部分执行此操作:

 <script> <script> import { CBox, CLink, CIconButton } from '@chakra-ui/vue' export default { name: 'NavBar', inject: ['$chakraColorMode', '$toggleColorMode'], components: { CBox, CLink, CIconButton }, } </script>

让我们创建一个计算属性来返回颜色模式:

 ... computed: { colorMode () { return this.$chakraColorMode() } }

现在我们已经在NavBar.vue中注入了这两个函数,让我们修改切换颜色模式按钮。 我们将从图标开始,以便根据颜色模式显示不同的图标。 我们的CIconButton组件现在在这种状态下看起来像这样:

 <c-icon-button variant="ghost" variant-color="gray[900]" aria-label="Switch to dark mode" :icon="colorMode == 'light' ? 'moon' : 'sun'" />

目前,我们使用aria-label属性来告诉屏幕阅读器切换到暗模式。 让我们修改它以支持明暗模式:

 <c-icon-button variant="ghost" variant-color="gray[900]" :aria-label="`Switch to ${colorMode == 'light' ? 'dark : 'light'} mode`" :icon="colorMode == 'light' ? 'moon' : 'sun'" />

最后,我们将在按钮上添加一个单击事件处理程序,以使用$toggleColorMode函数来切换应用程序的颜色模式。 像这样:

 <c-icon-button variant="ghost" variant-color="gray[900]" :aria-label="`Switch to ${colorMode == 'light' ? 'dark' : 'light'} mode`" :icon="colorMode == 'light' ? 'moon' : 'sun'" @click="$toggleColorMode" />

为了测试我们的颜色模式设置是否有效,我将添加颜色模式的插值和CIconButton旁边的文本来切换我们的颜色模式。 像这样:

 <c-box as="li"> <c-icon-button variant="ghost" variant-color="gray[900]" :aria-label="`Switch to ${colorMode == 'light' ? 'dark' : 'light'} mode`" :icon="colorMode == 'light' ? 'moon' : 'sun'" @click="$toggleColorMode" /> Current mode: {{ colorMode }} </c-box>

这是我们的应用程序当前的样子:

所以我们已经完成了在 Chakra UI 中设置颜色模式的繁重工作。 所以现在我们可以根据颜色模式为我们的应用程序设置样式。 让我们去default.vue并使用CColorModeProvider提供的颜色模式插槽属性来设置我们的应用程序的样式。 让我们先在default.vue中修改我们的模板。

 <template> <div class="container"> <c-theme-provider> <c-color-mode-provider #default="{ colorMode }"> <c-box v-bind="mainStyles[colorMode]" w="100vw" h="100vh" as="section" > <c-reset /> <nav-bar /> <nuxt /> </c-box> </c-color-mode-provider> </c-theme-provider> </div> </template>

我们从 CColorModeProvider 提供的 slot props 属性中CColorModeProvider colorMode然后将其作为动态键传递给我们稍后将创建的mainStyle对象。 这个想法是根据colorMode值使用一组不同的样式。 我还使用速记道具的宽度和高度 - wh分别设置我们的CBox组件的宽度和高度。 让我们在脚本部分定义这个mainStyles对象:

 <script> import { CThemeProvider, CColorModeProvider, CReset, CBox } from '@chakra-ui/vue' import NavBar from '@/components/NavBar' export default { name: 'DefaultLayout', components: { CThemeProvider, CColorModeProvider, CReset, CBox, NavBar }, data () { return { mainStyles: { dark: { bg: 'gray.900', color: 'whiteAlpha.900' }, light: { bg: 'whiteAlpha.900', color: 'gray.900' } } } } } </script>

Chakra-ui 浏览器现在支持黑暗模式!

现在我们有了导航栏,并且成功地为我们的应用程序设置了暗模式支持,让我们关注pages/目录中的index.vue ,在那里可以找到我们应用程序的核心。 我们将从添加一个CBox组件开始,如下所示:

 <c-box as="main" d="flex" direction="column" align-items="center" p="10" > </c-box>

然后我们将在其中添加CInput组件。 我们的index.vue页面组件将如下所示:

 <template> <c-box as="main" d="flex" align-items="center" direction="column" w="auto" p="16" > <c-input placeholder="Search components..." size="lg" mb="5" is-full-width /> </c-box> </template> <script> import { CBox, CInput } from '@chakra-ui/vue' export default { components: { CBox, CInput } } </script>

这是我们的应用程序现在的样子:

您可以从上面的截屏视频中看到CInput元素如何自动知道它何时处于黑暗模式并进行相应调整,即使我们没有明确设置它也是如此。 此外,用户可以点击 tab 键来关注该CInput组件。

添加组件列表

因此,Chakra-ui 浏览器的想法(如前所述)是向用户展示 Chakra UI 中所有可用的组件,以便我们可以拥有这些组件的列表以及将用户带到文档的链接的组件。 为此,我将在项目目录的根目录下创建一个名为data的文件夹,然后创建一个名为index.js的文件。 在index.js中,我将导出一个包含组件名称的对象数组。 以下是文件的外观:

 // ./data/index.js export const components = [ { name: 'Accordion' }, { name: 'Alert' }, { name: 'AlertDialog' }, { name: 'AspectRatioBox' }, { name: 'AspectRatioBox' }, { name: 'Avatar' }, { name: 'Badge' }, { name: 'Box' }, { name: 'Breadcrumb' }, { name: 'Button' }, { name: 'Checkbox' }, { name: 'CircularProgress' }, { name: 'CloseButton' }, { name: 'Code' }, { name: 'Collapse' }, { name: 'ControlBox' }, { name: 'Divider' }, { name: 'Drawer' }, { name: 'Editable' }, { name: 'Flex' }, { name: 'Grid' }, { name: 'Heading' }, { name: 'Icon' }, { name: 'IconButton' }, { name: 'IconButton' }, { name: 'Input' }, { name: 'Link' }, { name: 'List' }, { name: 'Menu' }, { name: 'Modal' }, { name: 'NumberInput' }, { name: 'Popover' }, { name: 'Progress' }, { name: 'PseudoBox' }, { name: 'Radio' }, { name: 'SimpleGrid' }, { name: 'Select' }, { name: 'Slider' }, { name: 'Spinner' }, { name: 'Stat' }, { name: 'Stack' }, { name: 'Switch' }, { name: 'Tabs' }, { name: 'Tag' }, { name: 'Text' }, { name: 'Textarea' }, { name: 'Toast' }, { name: 'Tooltip' } ]

为了完成我们的实现,我将把上面的数组导入pages/index.vue并对其进行迭代以显示所有组件。 此外,我们将让用户能够使用搜索框过滤组件。 这是完整的实现:

 // pages/index.vue <template> <c-box as="main" d="flex" align-items="space-between" flex-direction="column" w="auto" p="16" > <c-input v-model="search" placeholder="Search components..." size="lg" mb="10" is-full-width /> <c-grid template-columns="repeat(4, 1fr)" gap="3" p="5"> <c-box v-for="(chakraComponent, index) of filteredComponents" :key="index" h="10"> {{ chakraComponent.name }} <c-badge> <c-link is-external :href="lowercase(`https://vue.chakra-ui.com/${chakraComponent.name}`)" > <c-icon name="info" size="18px" /> </c-link> </c-badge> </c-box> </c-grid> </c-box> </template> <script> import { CBox, CInput, CGrid, CLink, CBadge, CIcon } from '@chakra-ui/vue' import { components as chakraComponents } from '../data' export default { components: { CBox, CInput, CGrid, CBadge, CIcon, CLink }, data () { return { search: '' } }, computed: { filteredComponents () { return chakraComponents.filter((component) => { return this.lowercase(component.name).includes(this.lowercase(this.search)) }) } }, methods: { lowercase (value) { return value.toLowerCase() } } } </script>

现在我们的应用程序看起来像这样:

您现在可以看到组件列表的暗模式是如何自动进行的,以及如何为链接添加焦点管理(默认情况下)以帮助可访问性。

测试脉轮 UI

最后,让我们通过在其上运行 Lighthouse 可访问性测试来看看我们的应用程序的得分情况。 请注意,此测试基于 Axe 用户影响评估。 以下是测试的截屏视频。 您也可以按照以下步骤自行运行测试。

从上面的截屏视频中,您可以看到我们的 Chakra UI 应用在灯塔可访问性测试中的得分为85

结论

在本文中,我们谈到了构建可访问界面的需求,并且我们还通过为 Chakra UI 组件构建了一个资源管理器(Chakra-ui explorer),了解了如何使用 Chakra UI 从头开始​​构建可访问的应用程序。

  • 查看 Netlify 上的实时应用程序 →
  • 链接到回购 →