One of React's basics are props. They are used to pass data from a parent component to its child components. While they are a great way to handle flow of data, sometimes we tend to overuse them, leading to increasing code complexity and reduced readability. It may make the component harder to maintain, understand and reuse.
In this short article I'd like to propose one way to handle this problem, taking advantage of the ARIA Attributes.
❌ The problem
Sometimes we need to pass some props to our components for styling purposes. In this example, we need to create a Radio Button, which changes its border color depending of whether it's checked or not (in this case we're using styled-components).
type ComponentProps = {
$checked: boolean
}
const Component = styled.input<ComponentProps>`
// Some styles...
${({ $checked }) =>
$checked
? css`
border-color: 1px solid blue;
`
: css`
border-color: 1px solid grey;
`
}
`
// Some code
return
<>
<Component
$checked={!!value}
checked={!!value}
id="component"
type="radio"
/>
<label for="component">Radio input</label>
</>
Since we already have the checked
prop (html input has it natively), we'd have to create another prop if we wanted to apply some styles depending on it: $checked
. We also need to type our component so Typescript knows that it has this new prop.
This technique adds a lot of unnecessary code and, moreover, it isn't accessible at all. Let's fix that.
✅ The solution
There are certain situations where we can avoid creating these props by ourselves. Instead, we can accomplish the same behaviour with ARIA Attributes.
const Component = styled.input`
// Some styles...
border-color: 1px solid grey;
&[aria-checked='true'] {
border-color: 1px solid blue;
}
`
// Some code
return
<>
<Component
aria-checked={!!value}
checked={!!value}
id="component"
type="radio"
/>
<label for="component">Radio input</label>
</>
Notice that we're using the aria-checked
attribute here. Not only we're avoiding creating unnecessary props, but also our application is much more accessible, keeping also the behaviour as close to native as possible.
Another examples where this approach might be useful:
-
aria-expanded
for a dropdown component. -
aria-disabled
when we want to disable operations over a certain element. -
aria-selected
for an element selected in a tablist. - etc.
Take into account that, as said before, this only applies for certain situations. Some ARIA Attributes might not provide the intented utility. You must be careful and responsible, taking accessibility seriously. Use this approach wisely.
The main point of this article is to state that, most of the times, is better to remain as close to native as possible, rather than creating unnecessary code.
I hope you liked it!
Top comments (1)
Thanks for the tip. I always forget to utilize aria attributes for things like this.