fix(webapp): enforce accessible control names (#4696)

## Summary

Require accessible names for dashboard controls.

Filter menu action items and chart color controls now expose explicit
names. The chart legend action uses a native button, while lint depth
and spacer-cell configuration match the rendered control structure.

Base: [#4695](https://github.com/triggerdotdev/trigger.dev/pull/4695)
This commit is contained in:
Chris Arderne
2026-08-19 16:35:44 +01:00
committed by GitHub
parent 3a091eb764
commit 646141199e
8 changed files with 18 additions and 11 deletions
+7 -1
View File
@@ -77,7 +77,13 @@
"jsx-a11y/alt-text": "error",
"jsx-a11y/aria-role": "error",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/control-has-associated-label": "off",
"jsx-a11y/control-has-associated-label": [
"error",
{
"depth": 4,
"ignoreElements": ["audio", "canvas", "embed", "input", "textarea", "tr", "td", "video"]
}
],
"jsx-a11y/label-has-associated-control": "error",
"jsx-a11y/no-autofocus": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off",
@@ -568,6 +568,7 @@ function SeriesColorPicker({
<PopoverTrigger asChild>
<button
type="button"
aria-label="Change series color"
className="shrink-0 rounded p-0.5 hover:bg-background-raised"
title="Change series color"
>
@@ -572,17 +572,20 @@ export interface SelectButtonItemProps extends Omit<Ariakit.SelectItemProps, "on
icon?: React.ReactNode;
checkIcon?: React.ReactNode;
shortcut?: ShortcutDefinition;
accessibleLabel: string;
onClick: React.ComponentProps<"button">["onClick"];
}
export function SelectButtonItem({
checkIcon = <Ariakit.SelectItemCheck className="size-8 flex-none text-white" />,
accessibleLabel,
onClick,
...props
}: SelectButtonItemProps) {
const render = (
<button
type="button"
aria-label={accessibleLabel}
onClick={onClick}
className={cn("block w-full text-left", selectItemClasses, props.className)}
/>
@@ -302,17 +302,10 @@ type ViewAllDataRowProps = {
function ViewAllDataRow({ remainingCount, onViewAll }: ViewAllDataRowProps) {
return (
<div
<button
type="button"
className="relative flex w-full cursor-pointer items-center justify-between gap-2 rounded px-2 py-1 transition hover:bg-background-dimmed"
onClick={onViewAll}
role="button"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
onViewAll?.();
}
}}
>
<div className="relative flex w-full items-center justify-between gap-3">
<div className="flex items-center gap-1.5">
@@ -321,7 +314,7 @@ function ViewAllDataRow({ remainingCount, onViewAll }: ViewAllDataRowProps) {
</div>
<span className="self-start text-indigo-500">View all</span>
</div>
</div>
</button>
);
}
@@ -546,6 +546,7 @@ function MainMenu({ searchValue, trigger, clearSearchValue, setFilterType }: Men
{filtered.map((type, index) => (
<SelectButtonItem
key={type.name}
accessibleLabel={type.title}
onClick={() => {
clearSearchValue();
setFilterType(type.name);
@@ -236,6 +236,7 @@ function MainMenu({ searchValue, trigger, clearSearchValue, setFilterType }: Men
{filtered.map((type, index) => (
<SelectButtonItem
key={type.name}
accessibleLabel={type.title}
onClick={() => {
clearSearchValue();
setFilterType(type.name);
@@ -165,6 +165,7 @@ function MainMenu({ trigger, clearSearchValue, setFilterType }: MenuProps) {
{filterTypes.map((type, index) => (
<SelectButtonItem
key={type.name}
accessibleLabel={type.title}
onClick={() => {
clearSearchValue();
setFilterType(type.name);
@@ -124,6 +124,7 @@ function MainMenu({ searchValue, clearSearchValue, setFilterType, trigger, short
{filtered.map((type, index) => (
<SelectButtonItem
key={type.name}
accessibleLabel={type.title}
onClick={() => {
clearSearchValue();
setFilterType(type.name);