Suggestion for more robust component settings
The custom components update is great! I'm already gaining a ton of benefit by slowly adding the custom components in my project to the settings and getting all the eslint hinting!
I would love to be able to be more specific with how a component behaves via it's props, and what the eslint plugin understands that to mean.
As a use case, we use Material UI for our projects, one of the available components is Typography which handles all text in the app, paragraphs and headings, etc.
Currently the way the custom components settings are setup I would need a separate component called Heading that renders h1, h2, etc. and then Paragraph to render paragraphs and other text elements.
It would be great if I could tell the plugin that Typography elements with variant="h1|h2|h3|h4|h5|h5 should be treated as headings and other Typography elements can be treated as paragraphs to get the other helpful rules such as empty heading to trigger but only when the plugin knows it should be considered a header via that variant prop on the custom component.
This could look something like
settings: {
"jsx-a11y": {
components: {
Box: "div",
Typography: [
{
props: {
variant: "h1",
},
component: "h1"
},
{
props: {
variant: "h2",
},
component: "h2"
},
...
]
},
},
},
In this way I can specify props and what values I expect and tell the plugin what it should consider those prop combinations to mean in terms of the semantic component it returns or acts like
I'd love to see something like this too! We use Primer React where some components support an as prop so it'd be great if we can map a prop value to an element type.
I don't think we've yet seen the need to support mapping of combinations of props to an element type. I worry this could potentially add complexity and conflicts but maybe it's not as complex as I'm thinking.
If we only want to support a mapping of a single prop type, the following simplified format could work too and could be implemented relatively easily. We've been experimenting with a format like this in one of our custom plugins:
settings: {
"jsx-a11y": {
components: {
Box: "div",
Typography: {
props: { variant: { undefined: "p", "p": "p", "h1":"h1", "h2":"h2" } }
}
}
}
}
This says:
<Box>is always treated asdiv. (same as now)<Typography>is treated aspsincevariantis undefined and we mapvariantnot being defined to top.<Typography variant='p'>is treated asp<Typography variant='h1'>is treated ash1<Typography variant='span'>is treated as raw type sincevariantis set but the value isn't mapped to anything in the configuration.
This wouldn't be very extensible though if there is a need to support combinations of props.
Happy to keep discussing and try to get a PR going if we land on a format!
Can you elaborate on which rules you specifically want to target with these granular settings?
@ljharb I don't believe there's currently an option to configure enable component mappings on a per rule basis. I'm thinking of this more as an enhancement of the existing component mapping setting.
@khiga8 that's not what i meant. i mean, which specific rules do you hope are impacted by this global setting?
I'm not sure what rules are impacted by heading type elements but that's my specific use case since MUI uses variants for their headings and not separate components for headings, paragraphs, etc.
Same as @jrdn91, I don't have a list of rules in mind. But take for instance, heading-has-content rule which currently does accept components like Heading. It'd be great if we could have it consider something like <Typography variant='h1'>, <Typography variant='h2'>, whether it be on a global level or a rule-level. Another example is, anchor-ambiguous-text. We have a component that can render as an anchor or a button.
Another rule that comes to mind is role-supports-aria-props. Our team would benefit a lot from being able to discourage people from using aria-label on <Text as='p'> for instance.
I'm currently working on some components that could benefit from some mappings of a component to a given role and an element with that implicit role does not exist. Most notably, we are working on a tablist component and want to map it to an element with a role of tablist. I went through the issues and don't see an issue about something like this, but was wondering if this has been discussed previously.
I can see a situation that could use an implementation similar to the getElementType utility. When queried for the element type, the settings are queried and pull the associated property in the components object if it exists. Could something similar be done in the getExplicitRole or getImplicitRole utilities?