slogan3

Ontwerp een toegankelijke en gebruiksvriendelijke React UI-component

description

Met deze prompt leer je hoe je React-componenten maakt die niet alleen visueel aantrekkelijk zijn, maar ook toegankelijk voor alle gebruikers en geschikt voor verschillende schermformaten. Dit helpt problemen met gebruiksvriendelijkheid en toegankelijkheid te voorkomen en versnelt de ontwikkeling dankzij herbruikbare componenten.

prompt

Help me bij het ontwerpen van een toegankelijke en gebruiksvriendelijke UI-component in React. Beschrijf welke best practices ik moet volgen voor toegankelijkheid, responsief ...

try_prompt

generate_helper
disclaimerOnPageApi

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Hieronder vind je een overzicht van best practices en een voorbeeldimplementatie van een toegankelijke, responsieve en herbruikbare navigatiebalk met dropdown-menu's in React. **Best practices:** 1. **Toegankelijkheid (Accessibility):** - Gebruik HTML5-structuurelementen zoals `<nav>`, `<ul>`, `<li>`, en `<button>` voor semantiek. - Zorg voor keyboard-navigatie met `tabindex` en gebruik van `onKeyDown` voor menu-openings en navigatie. - Gebruik ARIA-rollen en attributen zoals `aria-haspopup`, `aria-expanded`, en `aria-controls`. - Geef visuele focus-styles voor keyboardgebruikers. - Zorg dat dropdown-menu's ook met toetsenbord te bedienen zijn. 2. **Responsief ontwerp:** - Gebruik CSS media queries of flexbox/grid voor layout. - Zorg dat de navigatie zich aanpast op verschillende schermgroottes. - Verberg menu's op kleine schermen en gebruik bijvoorbeeld een hamburger-menu. 3. **Herbruikbaarheid:** - Maak de component parametriseerbaar via props, zoals menu-items. - Scheid presentatie en logica waar mogelijk. - Gebruik React hooks voor state management. --- ### Voorbeeld React-component: Responsive Navigatie met Dropdowns ```jsx import React, { useState, useRef } from 'react'; const Navigation = ({ menuItems }) => { const [openDropdown, setOpenDropdown] = useState(null); const navRef = useRef(null); const handleToggle = (index) => { setOpenDropdown(openDropdown === index ? null : index); }; const handleKeyDown = (event, index) => { if (event.key === 'ArrowDown') { event.preventDefault(); setOpenDropdown(index); } if (event.key === 'Escape') { setOpenDropdown(null); } }; return ( <nav aria-label="Hoofdmenu" ref={navRef}> <ul style={{ display: 'flex', flexDirection: 'row', listStyle: 'none', padding: 0, margin: 0 }}> {menuItems.map((item, index) => ( <li key={item.label} style={{ position: 'relative', marginRight: '1rem' }}> {item.children ? ( <> <button aria-haspopup="true" aria-expanded={openDropdown === index} aria-controls={`dropdown-${index}`} onClick={() => handleToggle(index)} onKeyDown={(e) => handleKeyDown(e, index)} style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '0.5rem 1rem' }} > {item.label} </button> {openDropdown === index && ( <ul id={`dropdown-${index}`} role="menu" aria-hidden={false} style={{ position: 'absolute', top: '100%', left: 0, background: '#fff', border: '1px solid #ccc', listStyle: 'none', padding: 0, margin: 0, minWidth: '150px' }} > {item.children.map((child, cIndex) => ( <li key={child.label} role="menuitem"> <a href={child.href} style={{ display: 'block', padding: '0.5rem 1rem', textDecoration: 'none', color: '#000' }} > {child.label} </a> </li> ))} </ul> )} </> ) : ( <a href={item.href} style={{ padding: '0.5rem 1rem', textDecoration: 'none', color: '#000' }} > {item.label} </a> )} </li> ))} </ul> </nav> ); }; // Voorbeeld gebruik: const menuData = [ { label: 'Home', href: '/' }, { label: 'Diensten', children: [ { label: 'Consultancy', href: '/consultancy' }, { label: 'Ontwikkeling', href: '/ontwikkeling' }, ], }, { label: 'Over ons', href: '/over' }, { label: 'Contact', href: '/contact' }, ]; export default function App() { return <Navigation menuItems={menuData} />; } ``` --- ### Samenvatting: - **Toegankelijkheid:** gebruik van semantische elementen, ARIA-labels, toetsenbordondersteuning. - **Responsiviteit:** flexbox voor layout, menu-aanpassingen kunnen verder met CSS media queries. - **Herbruikbaarheid:** data-driven via props, eenvoudig aan te passen. Wil je verdere hulp of uitleg over specifieke onderdelen?
provider: deepseek
model: deepseek-chat
Zeker! Hieronder beschrijf ik de best practices en geef ik een voorbeeld van een toegiefelijke, responsieve navigatiebalk met dropdown-menu's in React. ## Best Practices ### Toegankelijkheid (a11y) 1. **Gebruik semantische HTML**: `<nav>`, `<ul>`, `<li>`, `<button>` 2. **ARIA-attributen**: `aria-label`, `aria-expanded`, `aria-haspopup` 3. **Toetsenbordnavigatie**: Ondersteun Tab, Enter, Escape en pijltjestoetsen 4. **Focus management**: Houd focus binnen dropdown wanneer geopend 5. **Screen reader ondersteuning**: Gebruik `aria-hidden` voor niet-zichtbare content ### Responsief ontwerp 1. **Mobile-first approach**: Begin met mobiel ontwerp 2. **Flexbox/Grid**: Gebruik CSS Flexbox of Grid voor lay-out 3. **Media queries**: Pas stijl aan op basis van schermgrootte 4. **Touch-friendly**: Zorg voor voldoende grootte van klikbare elementen (min. 44px) ### Herbruikbaarheid 1. **Props interface**: Duidelijke props met default waarden 2. **CSS modularisatie**: Gebruik CSS Modules of Styled Components 3. **Custom hooks**: Scheid logica waar mogelijk 4. **TypeScript**: Gebruik types voor betere documentatie ## Voorbeeldcode ```jsx import React, { useState, useRef, useEffect } from 'react'; import styles from './NavigationBar.module.css'; const NavigationBar = ({ items, logo }) => { const [activeDropdown, setActiveDropdown] = useState(null); const dropdownRef = useRef(null); // Sluit dropdown bij klik buiten of Escape useEffect(() => { const handleClickOutside = (event) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { setActiveDropdown(null); } }; const handleEscape = (event) => { if (event.key === 'Escape') { setActiveDropdown(null); } }; document.addEventListener('mousedown', handleClickOutside); document.addEventListener('keydown', handleEscape); return () => { document.removeEventListener('mousedown', handleClickOutside); document.removeEventListener('keydown', handleEscape); }; }, []); const toggleDropdown = (index) => { setActiveDropdown(activeDropdown === index ? null : index); }; const handleKeyDown = (event, index) => { switch (event.key) { case 'Enter': case ' ': event.preventDefault(); toggleDropdown(index); break; case 'ArrowDown': event.preventDefault(); if (activeDropdown === index) { // Focus eerste item in dropdown const firstItem = document.getElementById(`dropdown-${index}-item-0`); firstItem?.focus(); } break; default: break; } }; return ( <nav className={styles.navbar} aria-label="Hoofdnavigatie" ref={dropdownRef} > <div className={styles.navContainer}> {/* Logo */} <div className={styles.logo}> {logo} </div> {/* Mobile menu button */} <button className={styles.mobileMenuButton} aria-label="Menu openen" aria-expanded={activeDropdown !== null} onClick={() => toggleDropdown('mobile')} > <span></span> <span></span> <span></span>