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

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend