{
    "componentChunkName": "component---src-templates-post-js",
    "path": "/build-a-combobox-component-with-useid/",
    "result": {"data":{"mdx":{"body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Build a ComboBox Component with useId\",\n  \"date\": \"2021-10-21T00:00:00.000Z\",\n  \"summary\": \"React 18 brings us a new useId hook that will be useful for accessibility. In this post, we build a ComboBox component and learn how to take advantage of this new hook.\",\n  \"image\": \"../images/better-library-dx-using-jsdoc-links.png\",\n  \"tags\": [\"javascript\", \"documentation\", \"jsdoc\"]\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"Today, we\\u2019ll learn how the seemingly subtle \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/reactwg/react-18/discussions/111\"\n  }, \"useId\"), \" hook coming to React 18 can significantly help screen readers and ensure proper accessibility for your applications. A combo box is one of those components you hope you never have to make and instead wish the platform offered a solution for. By the end of this article, we\\u2019ll have a combo box component to help users autocomplete a list of results. Let\\u2019s get started!\"), mdx(\"p\", null, \"First, we\\u2019ll reference the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.w3.org/TR/wai-aria-practices-1.1/examples/combobox/aria1.1pattern/listbox-combo.html#ex_label\"\n  }, \"wai-aria examples for combo box\"), \". To keep things simple, we\\u2019ll duplicate the first example in React. We\\u2019ll start by creating a custom \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ComboBox\"), \" component and render an input with the attributes mentioned in the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.w3.org/TR/wai-aria-practices-1.1/#combobox\"\n  }, \"spec\"), \". A combo box requires proper context, which today will be showing a list of results that users can manually choose to autocomplete their favorite fruit.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, \"function ComboBox() {\\n  return <input aria-autocomplete=\\\"list\\\" />\\n}\\n\")), mdx(\"p\", null, \"We then add our list where we\\u2019ll render results using the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"children\"), \" prop, which offers a better experience for user\\u2019s to compose options similar to how the native \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"select\"), \" element works:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, \"function ComboBox({ children, value }) {\\n  return (\\n    <>\\n      <input aria-autocomplete=\\\"list\\\" value={value} />\\n      <ul role=\\\"listbox\\\">{children}</ul>\\n    </>\\n  )\\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, \"import { useId } from 'react'\\n\\nfunction ComboBox({ children, value }) {\\n  const id = useId()\\n  return (\\n    <>\\n      <input aria-autocomplete=\\\"list\\\" aria-controls={id} value={value} />\\n      <ul role=\\\"listbox\\\" id={id}>\\n        {children}\\n      </ul>\\n    </>\\n  )\\n}\\n\")), mdx(\"p\", null, \"Next, we need to implement a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Result\"), \" component library users can provide for the results. The spec requires using a unique identifier for \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"aria-activedescendant\"), \". We can again utilize \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"useId\"), \" to generate an id for each list item we can target.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, \"import { useId } from 'react'\\n\\nfunction Result({ value }) {\\n  const id = useId()\\n  return (\\n    <li id={id} role=\\\"option\\\">\\n      {value}\\n    </li>\\n  )\\n}\\n\")));\n}\n;\nMDXContent.isMDXComponent = true;","excerpt":"Today, we'll learn how the seemingly subtle  useId  hook coming to React 18 can significantly help screen readers and ensure proper…","fields":{"readingTime":{"text":"2 min read"},"slug":"/build-a-combobox-component-with-useid/"},"frontmatter":{"date":"10/21/2021","summary":"React 18 brings us a new useId hook that will be useful for accessibility. In this post, we build a ComboBox component and learn how to take advantage of this new hook.","tags":["javascript","documentation","jsdoc"],"title":"Build a ComboBox Component with useId","image":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABd0lEQVQoz52T3XKCMBCFQ1VAqyAVEFTUMiWABXFGbS06TqfjZd//dU5nw0/V2l704iPJZnP2wAYm2SGYxf9FdVayQjC7hALy+Bmql+JuGKHhxDVNt6DhXMZpTWLXiEL0aLoLdGZZITxJoHqJKNCZLdGeplAmidir9mn81XElSIfas6UY6ZBSCpPgOSQmcss1FaU8epMLh+okhTIuqreI0QKKRwVSyKNFLUS51bxCLvOFQ/qg0jDEND6BJ58w/B30cAc92EGL9+j4a/T8Fe7nmRiJ7uOqFiJ35JIg0dqhPt9A8zZQRinU6QqKl4kEclc4i0UexWo3t7rPzABdbw0nOMKYv6IXHNCP3mHEJzxER7hJDivMILsBJCsSN4GomvCj08wK0XI5TP8Npp+jG27RX+bQeA4j+oDGj9CfDnDiPQZPL7DSA3S+BRsE3yI2LykFZZeqBWBWAGZykGsxrzBLrHLPPLvUlaB4ZWqKXUxu2f+L6z+liHN8AaFuGzJPxcFNAAAAAElFTkSuQmCC","aspectRatio":1.9047619047619047,"src":"/static/dafe6eee883b59eaca42de3e2261c7c4/ee604/better-library-dx-using-jsdoc-links.png","srcSet":"/static/dafe6eee883b59eaca42de3e2261c7c4/69585/better-library-dx-using-jsdoc-links.png 200w,\n/static/dafe6eee883b59eaca42de3e2261c7c4/497c6/better-library-dx-using-jsdoc-links.png 400w,\n/static/dafe6eee883b59eaca42de3e2261c7c4/ee604/better-library-dx-using-jsdoc-links.png 800w,\n/static/dafe6eee883b59eaca42de3e2261c7c4/f3583/better-library-dx-using-jsdoc-links.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}}}},"previous":null,"next":null},"pageContext":{"id":"7c9015f9-2e6c-51a5-8314-c2956f0106c8"}},
    "staticQueryHashes": ["3764592887"]}