Building Accessible & Reusable React Components: Best Practices for Modern Web Development

Abhay Kumar - Sep 5 - - Dev Community

In the rapidly evolving world of web development, creating accessible and reusable components is crucial. This is not just about writing clean code—it's about ensuring that your web applications are usable by everyone, including people with disabilities. Accessibility (a11y) and reusability are essential practices that can elevate the quality of your React applications. This blog will guide you through the best practices for building accessible and reusable React components.

1. The Importance of Accessibility in Web Development

Accessibility is the practice of making your web applications usable by as many people as possible, including those with disabilities. According to the World Health Organization, over 1 billion people globally live with some form of disability. Therefore, ensuring your web applications are accessible is not just a good practice—it's an ethical responsibility.

Key Accessibility Concepts:

Semantic HTML: Use HTML elements according to their intended purpose.

ARIA: Accessible Rich Internet Applications (ARIA) provides extra information to assistive technologies.

Keyboard Navigation: Ensure all interactive elements can be navigated using a keyboard.

2. Creating Accessible React Components

When building React components, start with accessibility in mind. Here are a few key practices:

a. Use Semantic HTML

Start by using the correct HTML elements for their intended purpose. This improves accessibility out of the box. For example, a button element should be used for actions, not a div.

Example:

const AccessibleButton = ({ onClick, label }) => (
  <button onClick={onClick} aria-label={label}>
    {label}
  </button>
);
Enter fullscreen mode Exit fullscreen mode

In the above example, the button element is semantically correct for an action, and aria-label provides a descriptive label for screen readers.
b. Implement ARIA Roles and Properties
ARIA roles, states, and properties help in making custom components accessible.

Example:

const Modal = ({ isOpen, onClose, children }) => {
  if (!isOpen) return null;

  return (
    <div role="dialog" aria-modal="true" aria-labelledby="modal-title">
      <h2 id="modal-title">Modal Title</h2>
      <button onClick={onClose} aria-label="Close modal">
        Close
      </button>
      {children}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

In this example, the role="dialog" and aria-modal="true" make it clear to assistive technologies that this is a modal window.

c. Ensure Keyboard Navigation

Your components should be navigable using a keyboard. This is particularly important for users who cannot use a mouse.

Example:

const AccessibleLink = ({ href, label }) => (
  <a href={href} tabIndex="0" aria-label={label}>
    {label}
  </a>
);
Enter fullscreen mode Exit fullscreen mode

The tabIndex="0" ensures that the link is focusable via the keyboard, and aria-label provides an accessible name for screen readers.

3. Designing Reusable React Components

Reusability is about creating components that can be used across different parts of your application without modification. This not only speeds up development but also ensures consistency across your UI.

a. Break Down Components

Instead of creating large, monolithic components, break them down into smaller, independent pieces.

Example:

const Button = ({ children, onClick }) => (
  <button onClick={onClick}>
    {children}
  </button>
);

const IconButton = ({ icon, label, onClick }) => (
  <Button onClick={onClick}>
    <span aria-hidden="true">{icon}</span>
    {label}
  </Button>
);
Enter fullscreen mode Exit fullscreen mode

Here, the IconButton component reuses the Button component, demonstrating modular design.

b. Use Props Effectively

Props should be used to make components configurable and reusable. The goal is to make the component adaptable to various contexts.

Example:

const Card = ({ title, content, footer }) => (
  <div className="card">
    <h3>{title}</h3>
    <p>{content}</p>
    {footer && <div className="card-footer">{footer}</div>}
  </div>
);
Enter fullscreen mode Exit fullscreen mode

In this Card component, props like title, content, and footer allow it to be reused in different contexts with different data.

c. Composition Over Inheritance

Favor composition over inheritance when designing reusable components. Composition allows you to create complex components by combining simpler ones.

Example:

const Dialog = ({ title, content, actions }) => (
  <div role="dialog" aria-labelledby="dialog-title">
    <h2 id="dialog-title">{title}</h2>
    <div>{content}</div>
    <div>{actions}</div>
  </div>
);

const ConfirmationDialog = ({ onConfirm, onCancel }) => (
  <Dialog
    title="Are you sure?"
    content="This action cannot be undone."
    actions={
      <>
        <button onClick={onCancel}>Cancel</button>
        <button onClick={onConfirm}>Confirm</button>
      </>
    }
  />
);
Enter fullscreen mode Exit fullscreen mode

Here, ConfirmationDialog composes the Dialog component to create a specific type of dialog.

4. Testing for Accessibility

It's important to test your components for accessibility. Here are a few tools you can use:

Lighthouse: A Chrome DevTools tool that audits your app for accessibility issues.

axe-core: An accessibility engine that can be integrated into your testing setup.

Screen Readers: Test your components with screen readers like NVDA or VoiceOver.

Conclusion
Building accessible and reusable React components requires a thoughtful approach, but the benefits are clear. By ensuring your components are accessible, you make your web applications available to a broader audience. Reusability, on the other hand, leads to cleaner, more maintainable code. Together, these practices will help you create high-quality React applications that are both inclusive and efficient.

🔗 Connect with me on LinkedIn:
Let's connect and discuss more about React, web development, and performance enhancement!

Follow me: Abhay Kumar

. . . . . . . . . . .