import { CodeSurfer } from "code-surfer" import myTheme from './slides-theme'
import { shadesOfPurple } from "@code-surfer/themes"
export const theme = myTheme
Guillermo Peralta
JavaScript Paraguay Meetup Mayo 2020
- eslint-plugin-jsx-a11y
- Axe accessibility - Chrome Firefox
- Tota11y - Chrome Firefox
- Accessibility Insights for Web - Chrome
- Web Developer - Chrome Firefox
- High Contrast - Chrome
- WAVE Evaluation Tool - Chrome Firefox
- Lighthouse
- VoiceOver (macOS Safari)
- ChromeVox (Extensión de Chrome)
- NVDA (Windows Chrome/Firefox)
- JAWS (Windows Chrome/Firefox)
- VoiceOver (iOS Safari)
- TalkBack (Android Chrome)
- atributo
alt
en imágenes siempre- Imágenes decorativas:
alt=""
- Imágenes con contenido:
alt="Descripción"
- Imágenes que funcionan como link
alt="Descripción"
- Imágenes decorativas:
- Element
<title>
en SVG
https://webaim.org/techniques/alttext/
- WebAIM Contrast Checker
- Firefox DevTools
<span className="w-1/2 md:w-1/3">Animal favorito: </span>
<input
type="text"
className="border-2 border-gray-600 bg-gray-100 rounded pl-3 py-1 w-1/2 md:w-48 lg:w-auto"
value={currentEntry.animal}
onChange={(e) => {
const { value } = e.target
setCurrentEntry((entry) => ({ ...entry, animal: value }))
}}
/>
<label className="w-1/2 md:w-1/3" htmlFor="animal-input">Animal favorito: </label>
<input
type="text"
id="animal-input"
className="border-2 border-gray-600 bg-gray-100 rounded pl-3 py-1 w-1/2 md:w-48 lg:w-auto"
value={currentEntry.animal}
onChange={(e) => {
const { value } = e.target
setCurrentEntry((entry) => ({ ...entry, animal: value }))
}}
required
/>
<div className="mt-8 flex lg:col-span-2">
<span className="w-1/2 md:w-1/3 lg:w-1/6">Actividades favoritas: </span>
<div className="flex flex-wrap w-1/2 md:w-auto">
<div>
<input
type="checkbox"
value="walking"
checked={currentEntry.activities.walking}
onChange={(e) => {
const { checked } = e.target
setCurrentEntry((entry) => ({
...entry,
activities: { ...entry.activities, walking: checked },
}))
}}
/>
<span className="mx-2">Caminar </span>
</div>
</div>
</div>
<fieldset className="mt-8 lg:col-span-2">
<legend className="w-1/2 md:w-1/3 lg:w-1/6 float-left">Actividades favoritas: </legend>
<div className="flex flex-wrap w-1/2 md:w-auto">
<div>
<input
type="checkbox"
id="walking-check"
value="walking"
checked={currentEntry.activities.walking}
onChange={(e) => {
const { checked } = e.target
setCurrentEntry((entry) => ({
...entry,
activities: { ...entry.activities, walking: checked },
}))
}}
/>
<label className="mx-2" htmlFor="walking-check">Caminar </label>
</div>
</div>
</fieldset>
const favoriteAnimalInput = React.useRef(null)
React.useEffect(() => {
if (currentEntry === defaultEntry && favoriteAnimalInput.current) {
favoriteAnimalInput.current.focus()
}
}, [currentEntry])
return (
//...
<input
type="text"
id="animal-input"
value={currentEntry.animal}
required
ref={favoriteAnimalInput}
/>
)
export default function QuizTable({ entries, onRemove }) {
const delButtons = React.useRef([])
return (
{// ...}
{entries.map((entry, i) => (
{// ...}
<button
type="button"
ref={el => {delButtons.current[i] = el}}
onClick={() => {
onRemove(i)
focusPrevButton(i)
}}
aria-label={altTextForEntry(entry)}
>
))}
)
}
const focusPrevButton = (i) => {
let idxToFocus = i - 1
if(i === 0 && entries.length > 1) {
// focus next item instead if there is
idxToFocus = i + 1
}
if(delButtons.current[idxToFocus]) {
delButtons.current[idxToFocus].focus()
}
}
<body>
<noscript>Necesitás JavaScript para ver esta página.</noscript>
<div id="root"></div>
</body>
<body>
<noscript>Necesitás JavaScript para ver esta página.</noscript>
<div id="root"></div>
<div class="sr-only polite-region" aria-live="polite"></div>
<div class="sr-only assertive-region" aria-live="assertive"></div>
</body>
function App() {
const [assertiveMsg, setAssertiveMsg] = React.useState('')
const [politeMsg, setPoliteMsg] = React.useState('')
React.useLayoutEffect(() => {
const assertiveEl = document.querySelector('.assertive-region')
if (assertiveEl) {
assertiveEl.textContent = assertiveMsg
}
}, [assertiveMsg])
React.useLayoutEffect(() => {
const politeEl = document.querySelector('.polite-region')
if (politeEl) {
politeEl.textContent = politeMsg
}
}, [politeMsg])
//...
}
<header>
<nav>
<main>
<section>
<h1>
,<h2>
, ...<figure>
<aside>
<article>
<footer>
import img from "./html-semantico.png"
<img src={img} style={{width: "80vw"}} alt="gráfico con ejemplo de una página con las distintas secciones remarcadas, como encabezado, sección principal, artículo y pie de página" />
- No asustarse
- Aprender algunas cositas nuevas
- Empezar desde la base
- Usar las herramientas adecuadas
- Intentar y reintentar