Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/reference/generated/tabs-panel.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "A panel displayed when the corresponding tab is active.\nRenders a `<div>` element.",
"props": {
"value": {
"type": "Tabs.Tab.Value",
"type": "any",
"description": "The value of the TabPanel. It will be shown when the Tab with the corresponding value is selected.\nIf not provided, it will fall back to the index of the panel.\nIt is recommended to explicitly provide it, as it's required for the tab panel to be rendered on the server."
},
"className": {
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/generated/tabs-root.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
"description": "Groups the tabs and the corresponding panels.\nRenders a `<div>` element.",
"props": {
"defaultValue": {
"type": "Tabs.Tab.Value",
"type": "any",
"default": "0",
"description": "The default value. Use when the component is not controlled.\nWhen the value is `null`, no Tab will be active."
},
"value": {
"type": "Tabs.Tab.Value",
"type": "any",
"description": "The value of the currently active `Tab`. Use when the component is controlled.\nWhen the value is `null`, no Tab will be active."
},
"onValueChange": {
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/generated/tabs-tab.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "An individual interactive tab button that toggles the corresponding panel.\nRenders a `<button>` element.",
"props": {
"value": {
"type": "Tabs.Tab.Value",
"type": "any",
"description": "The value of the Tab.\nWhen not specified, the value is the child position index."
},
"nativeButton": {
Expand Down
10 changes: 10 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,22 @@ export default defineConfig(
'react-hooks/refs': 'off',
},
},
{
files: [`packages/*/src/**/*${EXTENSION_TS}`],
ignores: [`**/*${EXTENSION_TEST_FILE}`, `test/**/*${EXTENSION_TS}`],
rules: {
'material-ui/add-undef-to-optional': 'error',
},
},
{
files: [
// matching the pattern of the test runner
`**/*${EXTENSION_TEST_FILE}`,
],
extends: createTestConfig({ useMocha: false }),
rules: {
'material-ui/add-undef-to-optional': 'off',
},
},
baseSpecRules,
{
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"@babel/plugin-transform-react-constant-elements": "^7.27.1",
"@base-ui-components/monorepo-tests": "workspace:*",
"@mui/internal-netlify-cache": "^0.0.2-canary.1",
"@mui/internal-code-infra": "^0.0.3-canary.51",
"@mui/internal-code-infra": "https://pkg.pr.new/mui/mui-public/@mui/internal-code-infra@e8d266b",
"@mui/internal-test-utils": "^2.0.15",
"@next/eslint-plugin-next": "15.5.6",
"@octokit/rest": "^22.0.1",
Expand Down
4 changes: 3 additions & 1 deletion packages/react/src/accordion/item/AccordionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,9 @@ export interface AccordionItemProps
/**
* Event handler called when the panel is opened or closed.
*/
onOpenChange?: (open: boolean, eventDetails: AccordionItem.ChangeEventDetails) => void;
onOpenChange?:
| ((open: boolean, eventDetails: AccordionItem.ChangeEventDetails) => void)
| undefined;
}

export type AccordionItemChangeEventReason = typeof REASONS.triggerPress | typeof REASONS.none;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface AccordionItemContext {
open: boolean;
state: AccordionItem.State;
setTriggerId: (id: string | undefined) => void;
triggerId?: string;
triggerId?: string | undefined;
}

export const AccordionItemContext = React.createContext<AccordionItemContext | undefined>(
Expand Down
20 changes: 11 additions & 9 deletions packages/react/src/accordion/root/AccordionRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,54 +177,56 @@ export interface AccordionRootProps extends BaseUIComponentProps<'div', Accordio
*
* To render an uncontrolled accordion, use the `defaultValue` prop instead.
*/
value?: AccordionValue;
value?: AccordionValue | undefined;
/**
* The uncontrolled value of the item(s) that should be initially expanded.
*
* To render a controlled accordion, use the `value` prop instead.
*/
defaultValue?: AccordionValue;
defaultValue?: AccordionValue | undefined;
/**
* Whether the component should ignore user interaction.
* @default false
*/
disabled?: boolean;
disabled?: boolean | undefined;
/**
* Allows the browser’s built-in page search to find and expand the panel contents.
*
* Overrides the `keepMounted` prop and uses `hidden="until-found"`
* to hide the element without removing it from the DOM.
* @default false
*/
hiddenUntilFound?: boolean;
hiddenUntilFound?: boolean | undefined;
/**
* Whether to keep the element in the DOM while the panel is closed.
* This prop is ignored when `hiddenUntilFound` is used.
* @default false
*/
keepMounted?: boolean;
keepMounted?: boolean | undefined;
/**
* Whether to loop keyboard focus back to the first item
* when the end of the list is reached while using the arrow keys.
* @default true
*/
loopFocus?: boolean;
loopFocus?: boolean | undefined;
/**
* Event handler called when an accordion item is expanded or collapsed.
* Provides the new value as an argument.
*/
onValueChange?: (value: AccordionValue, eventDetails: AccordionRootChangeEventDetails) => void;
onValueChange?:
| ((value: AccordionValue, eventDetails: AccordionRootChangeEventDetails) => void)
| undefined;
/**
* Whether multiple items can be open at the same time.
* @default true
*/
multiple?: boolean;
multiple?: boolean | undefined;
/**
* The visual orientation of the accordion.
* Controls whether roving focus uses left/right or up/down arrow keys.
* @default 'vertical'
*/
orientation?: Orientation;
orientation?: Orientation | undefined;
}

export type AccordionRootChangeEventReason = typeof REASONS.triggerPress | typeof REASONS.none;
Expand Down
8 changes: 5 additions & 3 deletions packages/react/src/alert-dialog/root/AlertDialogRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,22 @@ export interface AlertDialogRootProps<Payload = unknown>
/**
* Event handler called when the dialog is opened or closed.
*/
onOpenChange?: (open: boolean, eventDetails: AlertDialogRoot.ChangeEventDetails) => void;
onOpenChange?:
| ((open: boolean, eventDetails: AlertDialogRoot.ChangeEventDetails) => void)
| undefined;
/**
* A ref to imperative actions.
* - `unmount`: When specified, the dialog will not be unmounted when closed.
* Instead, the `unmount` function must be called to unmount the dialog manually.
* Useful when the dialog's animation is controlled by an external library.
*/
actionsRef?: React.RefObject<AlertDialogRoot.Actions>;
actionsRef?: React.RefObject<AlertDialogRoot.Actions> | undefined;
/**
* A handle to associate the popover with a trigger.
* If specified, allows external triggers to control the popover's open state.
* Can be created with the AlertDialog.createHandle() method.
*/
handle?: DialogHandle<Payload>;
handle?: DialogHandle<Payload> | undefined;
}

export type AlertDialogRootActions = DialogRoot.Actions;
Expand Down
45 changes: 26 additions & 19 deletions packages/react/src/autocomplete/root/AutocompleteRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function AutocompleteRoot<ItemValue>(
* The items to be displayed in the list.
* Can be either a flat array of items or an array of groups with items.
*/
items?: readonly ItemValue[];
items?: readonly ItemValue[] | undefined;
},
): React.JSX.Element;
export function AutocompleteRoot<ItemValue>(
Expand Down Expand Up @@ -181,64 +181,69 @@ export interface AutocompleteRootProps<ItemValue>
* - `none`: items are static (not filtered), and the input value will not change based on the active item.
* @default 'list'
*/
mode?: 'list' | 'both' | 'inline' | 'none';
mode?: ('list' | 'both' | 'inline' | 'none') | undefined;
/**
* Whether the first matching item is highlighted automatically.
* - `true`: highlight after the user types and keep the highlight while the query changes.
* - `'always'`: always highlight the first item.
* @default false
*/
autoHighlight?: boolean | 'always';
autoHighlight?: (boolean | 'always') | undefined;
/**
* Whether the highlighted item should be preserved when the pointer leaves the list.
* @default false
*/
keepHighlight?: boolean;
keepHighlight?: boolean | undefined;
/**
* Whether moving the pointer over items should highlight them.
* @default true
*/
highlightItemOnHover?: boolean;
highlightItemOnHover?: boolean | undefined;
/**
* The uncontrolled input value of the autocomplete when it's initially rendered.
*
* To render a controlled autocomplete, use the `value` prop instead.
*/
defaultValue?: AriaCombobox.Props<
React.ComponentProps<'input'>['defaultValue'],
'none'
>['defaultInputValue'];
defaultValue?:
| AriaCombobox.Props<React.ComponentProps<'input'>['defaultValue'], 'none'>['defaultInputValue']
| undefined;
/**
* The input value of the autocomplete. Use when controlled.
*/
value?: AriaCombobox.Props<React.ComponentProps<'input'>['value'], 'none'>['inputValue'];
value?:
| AriaCombobox.Props<React.ComponentProps<'input'>['value'], 'none'>['inputValue']
| undefined;
/**
* Event handler called when the input value of the autocomplete changes.
*/
onValueChange?: (value: string, eventDetails: AutocompleteRootChangeEventDetails) => void;
onValueChange?:
| ((value: string, eventDetails: AutocompleteRootChangeEventDetails) => void)
| undefined;
/**
* Whether clicking an item should submit the autocomplete's owning form.
* By default, clicking an item via a pointer or <kbd>Enter</kbd> key does not submit the owning form.
* Useful when the autocomplete is used as a single-field form search input.
* @default false
*/
submitOnItemClick?: AriaCombobox.Props<ItemValue, 'none'>['submitOnItemClick'];
submitOnItemClick?: AriaCombobox.Props<ItemValue, 'none'>['submitOnItemClick'] | undefined;
/**
* When the item values are objects (`<Autocomplete.Item value={object}>`), this function converts the object value to a string representation for both display in the input and form submission.
* If the shape of the object is `{ value, label }`, the label will be used automatically without needing to specify this prop.
*/
itemToStringValue?: (itemValue: ItemValue) => string;
itemToStringValue?: ((itemValue: ItemValue) => string) | undefined;
/**
* A ref to imperative actions.
* - `unmount`: When specified, the autocomplete will not be unmounted when closed.
* Instead, the `unmount` function must be called to unmount the autocomplete manually.
* Useful when the autocomplete's animation is controlled by an external library.
*/
actionsRef?: React.RefObject<AutocompleteRootActions>;
actionsRef?: React.RefObject<AutocompleteRootActions> | undefined;
/**
* Event handler called when the popup is opened or closed.
*/
onOpenChange?: (open: boolean, eventDetails: AutocompleteRootChangeEventDetails) => void;
onOpenChange?:
| ((open: boolean, eventDetails: AutocompleteRootChangeEventDetails) => void)
| undefined;
/**
* Callback fired when an item is highlighted or unhighlighted.
* Receives the highlighted item value (or `undefined` if no item is highlighted) and event details with a `reason` property describing why the highlight changed.
Expand All @@ -247,10 +252,12 @@ export interface AutocompleteRootProps<ItemValue>
* - `'pointer'`: the highlight changed due to pointer hovering.
* - `'none'`: the highlight changed programmatically.
*/
onItemHighlighted?: (
highlightedValue: ItemValue | undefined,
eventDetails: AutocompleteRootHighlightEventDetails,
) => void;
onItemHighlighted?:
| ((
highlightedValue: ItemValue | undefined,
eventDetails: AutocompleteRootHighlightEventDetails,
) => void)
| undefined;
}

export namespace AutocompleteRoot {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/avatar/fallback/AvatarFallback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export interface AvatarFallbackProps extends BaseUIComponentProps<'span', Avatar
/**
* How long to wait before showing the fallback. Specified in milliseconds.
*/
delay?: number;
delay?: number | undefined;
}

export namespace AvatarFallback {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/avatar/image/AvatarImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export interface AvatarImageProps extends BaseUIComponentProps<'img', AvatarRoot
/**
* Callback fired when the loading status changes.
*/
onLoadingStatusChange?: (status: ImageLoadingStatus) => void;
onLoadingStatusChange?: ((status: ImageLoadingStatus) => void) | undefined;
}

export namespace AvatarImage {
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/avatar/image/useImageLoadingStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import { NOOP } from '../../utils/noop';
export type ImageLoadingStatus = 'idle' | 'loading' | 'loaded' | 'error';

interface UseImageLoadingStatusOptions {
referrerPolicy?: React.HTMLAttributeReferrerPolicy;
crossOrigin?: React.ImgHTMLAttributes<HTMLImageElement>['crossOrigin'];
referrerPolicy?: React.HTMLAttributeReferrerPolicy | undefined;
crossOrigin?: React.ImgHTMLAttributes<HTMLImageElement>['crossOrigin'] | undefined;
}

export function useImageLoadingStatus(
Expand Down
6 changes: 3 additions & 3 deletions packages/react/src/button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ interface ButtonCommonProps {
/**
* Whether the button should ignore user interaction.
*/
disabled?: boolean;
disabled?: boolean | undefined;
/**
* Whether the button should be focusable when disabled.
* @default false
*/
focusableWhenDisabled?: boolean;
focusableWhenDisabled?: boolean | undefined;
}

type NonNativeAttributeKeys =
Expand All @@ -79,7 +79,7 @@ interface ButtonNativeProps
extends NativeButtonProps,
ButtonCommonProps,
Omit<BaseUIComponentProps<'button', ButtonState>, 'disabled'> {
nativeButton?: true;
nativeButton?: true | undefined;
}

interface ButtonNonNativeProps
Expand Down
12 changes: 7 additions & 5 deletions packages/react/src/checkbox-group/CheckboxGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,27 +175,29 @@ export interface CheckboxGroupProps extends BaseUIComponentProps<'div', Checkbox
*
* To render an uncontrolled checkbox group, use the `defaultValue` prop instead.
*/
value?: string[];
value?: string[] | undefined;
/**
* Names of the checkboxes in the group that should be initially ticked.
*
* To render a controlled checkbox group, use the `value` prop instead.
*/
defaultValue?: string[];
defaultValue?: string[] | undefined;
/**
* Event handler called when a checkbox in the group is ticked or unticked.
* Provides the new value as an argument.
*/
onValueChange?: (value: string[], eventDetails: CheckboxGroupChangeEventDetails) => void;
onValueChange?:
| ((value: string[], eventDetails: CheckboxGroupChangeEventDetails) => void)
| undefined;
/**
* Names of all checkboxes in the group. Use this when creating a parent checkbox.
*/
allValues?: string[];
allValues?: string[] | undefined;
/**
* Whether the component should ignore user interaction.
* @default false
*/
disabled?: boolean;
disabled?: boolean | undefined;
}

export type CheckboxGroupChangeEventReason = typeof REASONS.none;
Expand Down
14 changes: 8 additions & 6 deletions packages/react/src/checkbox-group/useCheckboxGroupParent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,14 @@ export function useCheckboxGroupParent(
}

export interface UseCheckboxGroupParentParameters {
allValues?: string[];
value?: string[];
onValueChange?: (
value: string[],
eventDetails: BaseUIChangeEventDetails<BaseUIEventReasons['none']>,
) => void;
allValues?: string[] | undefined;
value?: string[] | undefined;
onValueChange?:
| ((
value: string[],
eventDetails: BaseUIChangeEventDetails<BaseUIEventReasons['none']>,
) => void)
| undefined;
}

export interface UseCheckboxGroupParentReturnValue {
Expand Down
Loading
Loading