making single page apps accessible
play

Making Single Page Apps Accessible #LaraconAU @jessbudd4 - PowerPoint PPT Presentation

Making Single Page Apps Accessible #LaraconAU @jessbudd4 @jessbudd4 = @jessbudd4 @jessbudd4 @jessbudd4 Jess Budd Front-end Developer & Accessibility Consultant @jessbudd4 Are JavaScript


  1. Making Single Page Apps Accessible #LaraconAU @jessbudd4

  2. 🚷 📲 🤖 😮 @jessbudd4

  3.  = 💶 @jessbudd4

  4. @jessbudd4

  5. 😭 @jessbudd4

  6. Jess Budd Front-end Developer & Accessibility Consultant @jessbudd4

  7. Are JavaScript frameworks bad for accessibility? @jessbudd4

  8. “ Nothing in React prevents us from building accessible web apps - Leslie Cohn-Wein, Netlify @jessbudd4

  9. What is web accessibility? @jessbudd4

  10. Removing barriers that prevent people with disabilities using your website @jessbudd4

  11. 1 in 5 Australians experience some form of disability @jessbudd4 Source: www.and.org.au/pages/disability-statistics.html

  12. 357,000 Australians have a visual impairment @jessbudd4 Source: www.and.org.au/pages/disability-statistics.html

  13. 1 in 6 Australians are affected by hearing loss @jessbudd4 Source: www.and.org.au/pages/disability-statistics.html

  14. Accessibility benefits everyone @jessbudd4

  15. @jessbudd4

  16. Who is most impacted?

  17. Keyboard users

  18. Screenreade r users

  19. Semantic HTML @jessbudd4

  20. screenshot of link list on @jessbudd4

  21. // not very accessible card component <div class="product"> <div class=“name"> Product name </div> <div class="description"> Description of product </div> <div class="button">Add to cart</div> </div>

  22. // more accessible card component <li> <h2> Product name </h2> <p> Description of product </p> <button>Add to cart</button> </li>

  23. // more accessible card component <li> <h2> Product name </h2> <p> Description of product </p> <button>Add to cart</button> </li>

  24. Divs are not buttons @jessbudd4

  25. <div tabindex="0" role="button" onKeyUp={keyUpHandler} onClick={clickHandler} class="button"> Add to cart </div>

  26. <div tabindex="0" role="button" onKeyUp={keyUpHandler} onClick={clickHandler} class="button"> Add to cart </div>

  27. <div tabindex="0" role="button" onKeyUp={keyUpHandler} onClick={clickHandler} class="button"> Add to cart </div>

  28. <div <button tabindex="0" onClick={clickHandler}> role="button" Add to cart onKeyUp={keyUpHandler} </button> onClick={clickHandler} class="button"> 👎 Add to cart </div>

  29. Give buttons some ❤ @jessbudd4

  30. Fragments for valid html @jessbudd4

  31. // not allowed render() { return ( < li>Hello</li > < li>World</li > ); }

  32. // not allowed // solution??? render() { render() { return ( return ( < li>Hello</li > < div> < li>World</li > < li>Hello</li > ); < li>World</li > } </ div> ); } 👏

  33. // fragments syntax render() { return ( < React.fragment > < li>Hello</li > < li>World</li > </ React.fragment > ); }

  34. Vue Fragments Vue-fragment @jessbudd4 www.medium.com/the-vue-point/plans-for-the-next-iteration-of-vue-js-777ffea6fabf

  35. Inputs & labels @jessbudd4

  36. // label not linked to input <label> Dog breed: </label> <input type="text" name="breed" />

  37. // explicitly linked label to input <label for="uniqueId"> Dog breed: </label> <input id="uniqueId" type="text" name=”breed” />

  38. // “for” becomes “htmlFor” in JSX <label htmlFor="uniqueId"> Dog breed: </label> <input id="uniqueId" type="text" name="breed" />

  39. What if I can't set a unique ID in advance? @jessbudd4

  40. // implicitly linked label to input <label> Dog breed: <input type="text" name="breed"/> </label>

  41. What if the design doesn’t have labels? @jessbudd4

  42. // label hidden with css is still announced <label class=“sr-only“ for=“dogBreed”> Dog breed: </label> <input id=“dogBreed” type="text" name=”breed" />

  43. Hit Area @jessbudd4

  44. Page titles @jessbudd4

  45. Click to edit

  46. // page title appears in browser tab <head> <meta charset="utf-8"> <title>Dogs Are The Best</title> <link rel="stylesheet" href="style.css"> </head>

  47. // code executes when component mounts // same as the mounted hook in Vue componentDidMount() { document.title = ‘Heckin’ Good Doggo’; }

  48. // update page title on routing componentDidMount() { document.title = ‘Heckin’ Good Doggo’; }

  49. Click to edit

  50. Visible focus styles @jessbudd4

  51. Default browser styles Safari: Firefox: Chrome: @jessbudd4

  52. Meme where am I /lost @jessbudd4

  53. Screen shot of page ??? with masses of links and question marks @jessbudd4

  54. /* don't just remove */ ❌ *:focus { outline: none; }

  55. /* don't just remove */ ❌ *:focus { outline: none; } /* replace with something! */ *:focus { ✅ /* branded focus styles here */ border: 2px dotted currentColor; }

  56. /* extend hover styles */ .button:hover, .button:focus { border: 5px solid #33ffdb; }

  57. Focus management @jessbudd4

  58. Single page applications use silent routing @jessbudd4

  59. Video of default browser behaviour @jessbudd4

  60. Move focus to new content @jessbudd4

  61. Tabindex Explained tabindex=”0" // makes element focusable in tab/DOM order tabindex=”-1" // makes elements focusable by scripting only tabindex=”5” // Danger Will Robinson! // tabindex becomes tabIndex (camelCase) in JSX

  62. Use React Refs @jessbudd4

  63. class PageHeading extends React. Component { constructer( props ) { super(props); this.content = React.createRef(); // Create Ref } componentDidMount() { this.content.focus(); // Move focus to ref } render() { return ( <h1 tabindex="-1" ref={this.content}> // Reference Doggos, Puppers and Floofers </h1> ); } }

  64. class PageHeading extends React. Component { constructer( props ) { super(props); this.content = React.createRef(); // Create Ref } componentDidMount() { this.content.focus(); // Move focus to ref } render() { return ( <h1 tabindex="-1" ref={this.content}> // Reference Doggos, Puppers and Floofers </h1> ); } }

  65. class PageHeading extends React. Component { constructer( props ) { super(props); this.content = React.createRef(); // Create Ref } componentDidMount() { this.content.focus(); // Move focus to ref } render() { return ( <h1 tabindex="-1" ref={this.content}> // Reference Doggos, Puppers and Floofers </h1> ); } }

  66. // update page title // and move users focus componentDidMount() { document.title = ‘Doggos be happy’; this.content.focus(); }

  67. Tooling & Testing @jessbudd4

  68. eslint-plugin-jsx-a11y eslint-plugin-jsx-a11y eslint-plugin-vue-a11y @jessbudd4

  69. Axe-core react-axe vue-axe @jessbudd4

  70. Google Lighthouse @jessbudd4 https://developers.google.com/web/tools/lighthouse

  71. Accessibility Insights @jessbudd4 https://accessibilityinsights.io/

  72. https://www.matuzo.at/blog/building-the-most-inaccessible-site-possible-with-a-perfect-lighthouse-score/

  73. “ Automated testing is just the first step - Manuel Matuzovic @jessbudd4

  74. Keyboard @jessbudd4

  75. What to look for Can I see where focus is? Does the tab order make sense? Can I access all required elements? Can I use advanced components? Does my focus move when needed? @jessbudd4

  76. Screenreader Voiceover (macOS) NVDA (Windows) @jessbudd4

  77. Takeaways Use Semantic HTML Link form labels with inputs Update page titles on routing Manage keyboard focus Use tooling & test your apps @jessbudd4

  78. Go forth and make the web a better place @jessbudd4

  79. Thanks! Slides at bit.ly/laracon19 @jessbudd4

Recommend


More recommend