Skip to content

Commit ad974f0

Browse files
LukasTyclaude
andcommitted
Drop React.AriaAttributes from DataAttributes
Every real slot inner type in MUI X already inherits React.AriaAttributes through its element or component base type (HTMLAttributes, SVGAttributes, ButtonBaseProps, PopperProps, etc.), so including aria-* in the shared DataAttributes widener was redundant. Narrow the widener to only add the data-* index signature that React's built-in types don't otherwise expose, so the helper does exactly what its name says. - DataAttributes no longer intersects React.AriaAttributes; only the `[k: `data-${string}`]` index signature plus user overrides remain. - AssertAllSlotsAcceptDataAttributes now checks a single marker (`data-x`) instead of both data-x and aria-label, and its failure message is updated accordingly. - ChartBaseCommonProps uses React.DOMAttributes (not HTMLAttributes), so aria is re-added explicitly there to preserve current behavior. - Per-package slotDataAttributes.spec.ts comments updated. Co-Authored-By: Claude Opus 4.7 <[email protected]>
1 parent cb1185c commit ad974f0

10 files changed

Lines changed: 40 additions & 43 deletions

File tree

packages/x-charts-pro/src/tests/slotDataAttributes.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { SankeyChartSlotProps } from '@mui/x-charts-pro/SankeyChart';
99
import type { ScatterChartProSlotProps } from '@mui/x-charts-pro/ScatterChartPro';
1010

1111
// Compile-time assertion: every slot in every exported SlotProps type of `x-charts-pro`
12-
// must accept `data-*` and `aria-*` attributes. The test compiles iff the assertion holds.
12+
// must accept `data-*` attributes. The test compiles if and only if the assertion holds.
1313

1414
type AssertBarChartPro = Assert<
1515
AllTrue<AssertAllSlotsAcceptDataAttributes<BarChartProSlotProps, 'BarChartPro'>>

packages/x-charts/src/models/slots/chartsBaseSlotProps.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type * as React from 'react';
22
import type { DataAttributes } from '@mui/x-internals/types';
33

44
export type ChartBaseCommonProps<T = HTMLElement> = React.DOMAttributes<T> &
5+
React.AriaAttributes &
56
DataAttributes & {
67
className?: string;
78
style?: React.CSSProperties;

packages/x-data-grid/src/tests/slotDataAttributes.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { AllTrue, Assert, AssertAllSlotsAcceptDataAttributes } from '@mui/x
22
import type { GridSlotsComponentsProps } from '@mui/x-data-grid';
33

44
// Compile-time assertion: every slot in the user-facing `slotProps` map of `x-data-grid`
5-
// must accept `data-*` and `aria-*` attributes. The test compiles iff the assertion holds.
5+
// must accept `data-*` attributes. The test compiles if and only if the assertion holds.
66

77
type AssertDataGrid = Assert<
88
AllTrue<AssertAllSlotsAcceptDataAttributes<GridSlotsComponentsProps, 'DataGrid'>>

packages/x-date-pickers-pro/src/tests/slotDataAttributes.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import type { StaticDateRangePickerSlotProps } from '@mui/x-date-pickers-pro/Sta
1616
import type { TimeRangePickerSlotProps } from '@mui/x-date-pickers-pro/TimeRangePicker';
1717

1818
// Compile-time assertion: every slot in every exported SlotProps type of `x-date-pickers-pro`
19-
// must accept `data-*` and `aria-*` attributes. The test compiles iff the assertion holds.
19+
// must accept `data-*` attributes. The test compiles if and only if the assertion holds.
2020
// A regression on any slot surfaces as a TS error pointing at the offending slot by name.
2121

2222
type AssertDateRangeCalendar = Assert<

packages/x-date-pickers/src/tests/slotDataAttributes.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import type { TimePickerSlotProps } from '@mui/x-date-pickers/TimePicker';
3030
import type { YearCalendarSlotProps } from '@mui/x-date-pickers/YearCalendar';
3131

3232
// Compile-time assertion: every slot in every exported SlotProps type of `x-date-pickers`
33-
// must accept `data-*` and `aria-*` attributes. The test compiles iff the assertion holds.
33+
// must accept `data-*` attributes. The test compiles if and only if the assertion holds.
3434
// A regression on any slot surfaces as a TS error pointing at the offending slot by name.
3535

3636
type AssertDateCalendar = Assert<

packages/x-internals/src/types/AssertSlotDataAttributes.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
Assert,
66
} from './index';
77

8-
// A typical slot-props interface using the helper — every slot must accept data-*/aria-*.
8+
// A typical slot-props interface using the helper — every slot must accept data-*.
99
interface GoodSlotProps {
1010
day?: SlotComponentPropsFromProps<{ onClick?: () => void }>;
1111
calendarHeader?: SlotComponentPropsFromProps<'div'>;
@@ -22,5 +22,5 @@ interface BadSlotProps {
2222
legacy?: { required: string };
2323
}
2424

25-
// @ts-expect-error FAIL [Bad.legacy]: slot must accept data-* and aria-* attributes. Use SlotComponentPropsFromProps.
25+
// @ts-expect-error FAIL [Bad.legacy]: slot must accept data-* attributes. Use SlotComponentPropsFromProps.
2626
type AssertBadSlotProps = Assert<AllTrue<AssertAllSlotsAcceptDataAttributes<BadSlotProps, 'Bad'>>>;

packages/x-internals/src/types/AssertSlotDataAttributes.ts

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,38 @@
11
// `V extends any` is the "force-distribution" idiom: it keeps `V` naked in the outer
22
// conditional so the check distributes across union variants. That matters for slot
33
// types shaped as `T | (T & DataAttributes)` (the `WithDataAttributes` widening) — the
4-
// assertion passes as soon as one branch exposes both keys, while a non-widened branch
5-
// failing on its own is fine.
4+
// assertion passes as soon as one branch exposes the marker key, while a non-widened
5+
// branch failing on its own is fine.
66
//
7-
// `'data-x'` and `'aria-label'` are used as marker keys. `'data-x'` matches the
7+
// `'data-x'` is used as the marker key: it matches the
88
// ` [k: `data-${string}`]: ... ` template-literal index signature exposed by
9-
// `DataAttributes`, and `'aria-label'` stands in for the `React.AriaAttributes` shape
10-
// (whose keys are otherwise all optional, which would make a direct structural check
11-
// trivially satisfied). Both markers are present only when the variant has been widened via
12-
// `DataAttributes`.
13-
type AcceptsDataAndAria<V> = V extends any
14-
? 'data-x' extends keyof V
15-
? 'aria-label' extends keyof V
16-
? true
17-
: false
18-
: false
19-
: never;
9+
// `DataAttributes`, and is present only when the variant has been widened via
10+
// `DataAttributes`. `aria-*` is not checked here — every real slot inner type in
11+
// MUI X inherits `React.AriaAttributes` through its element or component base type,
12+
// so aria coverage is a structural property of the inner type, not something this
13+
// widener needs to re-verify.
14+
type AcceptsDataAttributes<V> = V extends any ? ('data-x' extends keyof V ? true : false) : never;
2015

2116
type CheckVariant<V> = V extends (...args: any[]) => infer R
22-
? AcceptsDataAndAria<R>
23-
: AcceptsDataAndAria<V>;
17+
? AcceptsDataAttributes<R>
18+
: AcceptsDataAttributes<V>;
2419

2520
type SlotAcceptsDataAttributes<T> = true extends CheckVariant<NonNullable<T>> ? true : false;
2621

2722
/**
2823
* Maps each slot of a `*SlotProps` type to either `true` or a failure message
29-
* identifying the slot that does not accept `data-*` / `aria-*` attributes.
24+
* identifying the slot that does not accept `data-*` attributes.
3025
*
31-
* The check probes each slot's value type for both the
26+
* The check probes each slot's value type for the
3227
* `` [key: `data-${string}`]: ... `` index signature (covering arbitrary
33-
* `data-*` keys) and `'aria-label'` as the marker aria attribute (standing in
34-
* for the full `React.AriaAttributes` surface). The check distributes across
35-
* union variants and unwraps function variants to their return type; any
36-
* variant providing both signatures — typically via an intersection with
37-
* `DataAttributes` — passes.
28+
* `data-*` keys). The check distributes across union variants and unwraps
29+
* function variants to their return type; any variant providing the signature
30+
* — typically via an intersection with `DataAttributes` — passes.
3831
*/
3932
export type AssertAllSlotsAcceptDataAttributes<T, Name extends string = 'Component'> = {
4033
[K in keyof T]-?: SlotAcceptsDataAttributes<T[K]> extends true
4134
? true
42-
: `FAIL [${Name}.${Extract<K, string>}]: slot must accept data-* and aria-* attributes. Use SlotComponentPropsFromProps.`;
35+
: `FAIL [${Name}.${Extract<K, string>}]: slot must accept data-* attributes. Use SlotComponentPropsFromProps.`;
4336
};
4437

4538
/**
Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import type * as React from 'react';
2-
31
type DataAttributeValue = string | number | boolean | undefined;
42

53
/**
@@ -16,22 +14,27 @@ type DataAttributeValue = string | number | boolean | undefined;
1614
export interface DataAttributesOverrides {}
1715

1816
/**
19-
* Union of all `data-*` and `aria-*` attributes accepted on slot props.
20-
* `aria-*` keys reuse React's typed `AriaAttributes` so standard keys keep
21-
* their value constraints (e.g. `aria-expanded: boolean | 'true' | 'false'`).
17+
* Index signature for arbitrary `data-*` attributes, merged with any
18+
* strongly-typed overrides declared via `DataAttributesOverrides`.
19+
*
20+
* `aria-*` keys are intentionally not included here: every slot inner type
21+
* used in MUI X already inherits `React.AriaAttributes` through its element
22+
* or component base type (`HTMLAttributes`, `SVGAttributes`, `ButtonBaseProps`,
23+
* etc.), so widening with them would be redundant. `data-*` is the only thing
24+
* the host React types don't expose as a typed key, so it's the only thing
25+
* this helper adds.
2226
*/
23-
export type DataAttributes = React.AriaAttributes &
24-
DataAttributesOverrides & {
25-
[k: `data-${string}`]: DataAttributeValue;
26-
};
27+
export type DataAttributes = DataAttributesOverrides & {
28+
[k: `data-${string}`]: DataAttributeValue;
29+
};
2730

2831
/**
29-
* Widens a slot-props type to also accept `data-*` and `aria-*` attributes.
32+
* Widens a slot-props type to also accept arbitrary `data-*` attributes.
3033
*
3134
* Implemented as a union between the original type and the intersected widened
3235
* form — `T | (T & DataAttributes)` — so that pre-typed values remain
3336
* assignable to the original branch without having to declare a `data-*`
3437
* index signature themselves, while object literals can pick up the widened
35-
* branch and include `data-*` / `aria-*` keys.
38+
* branch and include `data-*` keys.
3639
*/
3740
export type WithDataAttributes<T> = T | (T & DataAttributes);

packages/x-tree-view-pro/src/tests/slotDataAttributes.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { AllTrue, Assert, AssertAllSlotsAcceptDataAttributes } from '@mui/x
22
import type { RichTreeViewProSlotProps } from '@mui/x-tree-view-pro/RichTreeViewPro';
33

44
// Compile-time assertion: every slot in every exported SlotProps type of `x-tree-view-pro`
5-
// must accept `data-*` and `aria-*` attributes. The test compiles iff the assertion holds.
5+
// must accept `data-*` attributes. The test compiles if and only if the assertion holds.
66

77
type AssertRichTreeViewPro = Assert<
88
AllTrue<

packages/x-tree-view/src/tests/slotDataAttributes.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { TreeItemSlotProps } from '@mui/x-tree-view/TreeItem';
55
import type { TreeItemIconSlotProps } from '@mui/x-tree-view/TreeItemIcon';
66

77
// Compile-time assertion: every slot in every exported SlotProps type of `x-tree-view`
8-
// must accept `data-*` and `aria-*` attributes. The test compiles iff the assertion holds.
8+
// must accept `data-*` attributes. The test compiles if and only if the assertion holds.
99

1010
type AssertRichTreeView = Assert<
1111
AllTrue<AssertAllSlotsAcceptDataAttributes<RichTreeViewSlotProps<{}, false>, 'RichTreeView'>>

0 commit comments

Comments
 (0)