Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Autocomplete] Enable global customization of different options #36971

Merged
merged 26 commits into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f5e56f6
add ownerState to renderOption
nicolas-ot Apr 23, 2023
4fde3b2
Merge branch 'master' into autocomplete-pass-getOptionLabel
nicolas-ot May 24, 2023
c211717
add ownerState as fourth params to renderOption
nicolas-ot May 24, 2023
b970c0e
add test to check previous commit
nicolas-ot May 24, 2023
70d6304
fix list missing key error in test
nicolas-ot May 24, 2023
d3e5438
fix list missing key error in test
nicolas-ot May 24, 2023
e16be9e
improve the description of params of renderOption
nicolas-ot May 24, 2023
e42043b
improve test
nicolas-ot May 29, 2023
d33cb31
run yarn docs:api
nicolas-ot May 29, 2023
e519352
add documentation
nicolas-ot May 29, 2023
3bdfd8c
update non-english documentation
nicolas-ot May 29, 2023
5ba13ce
ran yarn docs:typescript:formatted
nicolas-ot May 29, 2023
09248a4
fix test
nicolas-ot May 29, 2023
33e59b9
add useTheme to differentiate dark and light mode
nicolas-ot Jun 25, 2023
88c863d
add useTheme to differentiate dark and light mode
nicolas-ot Jun 25, 2023
206e670
improve docs and example
nicolas-ot Jun 28, 2023
2a9a078
fix test
nicolas-ot Jun 28, 2023
a367805
improve docs
nicolas-ot Jul 3, 2023
fe89284
improve docs
nicolas-ot Jul 3, 2023
9149f44
improve docs
nicolas-ot Jul 3, 2023
3229583
improve docs
nicolas-ot Jul 3, 2023
c7bcb7c
improve docs styling
nicolas-ot Jul 9, 2023
ce2478c
Merge branch 'master' into autocomplete-pass-getOptionLabel
ZeeshanTamboli Jul 10, 2023
dd3f39a
Merge branch 'master' into autocomplete-pass-getOptionLabel
ZeeshanTamboli Jul 10, 2023
9b7ffcb
Merge branch 'autocomplete-pass-getOptionLabel' of https://github.com…
ZeeshanTamboli Jul 10, 2023
4de3fc1
fix lint
ZeeshanTamboli Jul 10, 2023
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

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<ThemeProvider theme={theme}>
<Stack spacing={5} sx={{ width: 300 }}>
<MovieSelect />
<CountrySelect />
</Stack>
</ThemeProvider>
11 changes: 11 additions & 0 deletions docs/data/material/components/autocomplete/autocomplete-pt.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,17 @@ You can group the options with the `groupBy` prop. If you do so, make sure that

{{"demo": "DisabledOptions.js"}}

## Globally Customized Options

You can customize the options globally using [Themed components](/material-ui/customization/theme-components/).

To add ripple effects to all the options of the Autocomplete component,
you can define the `renderOption` property as a `defaultProps` for `Autocomplete` component in the Theme.
`renderOption` will then receive `ownerState` as the fourth parameter, which are props augmented with internal state of the component.
With that, your `Autocomplete` components can each have different options with the same styling.

{{"demo": "GloballyCustomizedOptions.js"}}

ZeeshanTamboli marked this conversation as resolved.
Show resolved Hide resolved
## `useAutocomplete`

For advanced customization use cases, a headless `useAutocomplete()` hook is exposed. It accepts almost the same options as the Autocomplete component minus all the props related to the rendering of JSX. The Autocomplete component is built on this hook.
Expand Down
11 changes: 11 additions & 0 deletions docs/data/material/components/autocomplete/autocomplete-zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,17 @@ You can group the options with the `groupBy` prop. If you do so, make sure that

{{"demo": "DisabledOptions.js"}}

## Globally Customized Options

You can customize the options globally using [Themed components](/material-ui/customization/theme-components/).

To add ripple effects to all the options of the Autocomplete component,
you can define the `renderOption` property as a `defaultProps` for `Autocomplete` component in the Theme.
`renderOption` will then receive `ownerState` as the fourth parameter, which are props augmented with internal state of the component.
With that, your `Autocomplete` components can each have different options with the same styling.

{{"demo": "GloballyCustomizedOptions.js"}}

## `useAutocomplete`

For advanced customization use cases, a headless `useAutocomplete()` hook is exposed. It accepts almost the same options as the Autocomplete component minus all the props related to the rendering of JSX. The Autocomplete component is built on this hook.
Expand Down
11 changes: 11 additions & 0 deletions docs/data/material/components/autocomplete/autocomplete.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,17 @@ The following demo shows how to use this prop to define custom markup and overri

{{"demo": "DisabledOptions.js"}}

## Globally Customized Options
ZeeshanTamboli marked this conversation as resolved.
Show resolved Hide resolved

You can customize the options globally using [Themed components](/material-ui/customization/theme-components/).
ZeeshanTamboli marked this conversation as resolved.
Show resolved Hide resolved

To add ripple effects to all the options of the Autocomplete component,
you can define the `renderOption` property as a `defaultProps` for `Autocomplete` component in the Theme.
`renderOption` will then receive `ownerState` as the fourth parameter, which are props augmented with internal state of the component.
With that, your `Autocomplete` components can each have different options with the same styling.
ZeeshanTamboli marked this conversation as resolved.
Show resolved Hide resolved

{{"demo": "GloballyCustomizedOptions.js"}}

## `useAutocomplete`

For advanced customization use cases, a headless `useAutocomplete()` hook is exposed.
Expand Down
2 changes: 1 addition & 1 deletion docs/translations/api-docs/autocomplete/autocomplete.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"readOnly": "If <code>true</code>, the component becomes readonly. It is also supported for multiple tags where the tag cannot be deleted.",
"renderGroup": "Render the group.<br><br><strong>Signature:</strong><br><code>function(params: AutocompleteRenderGroupParams) =&gt; ReactNode</code><br><em>params:</em> The group to render.",
"renderInput": "Render the input.<br><br><strong>Signature:</strong><br><code>function(params: object) =&gt; ReactNode</code><br>",
"renderOption": "Render the option, use <code>getOptionLabel</code> by default.<br><br><strong>Signature:</strong><br><code>function(props: object, option: T, state: object) =&gt; ReactNode</code><br><em>props:</em> The props to apply on the li element.<br><em>option:</em> The option to render.<br><em>state:</em> The state of the component.",
"renderOption": "Render the option, use <code>getOptionLabel</code> by default.<br><br><strong>Signature:</strong><br><code>function(props: object, option: T, state: object, ownerState: object) =&gt; ReactNode</code><br><em>props:</em> The props to apply on the li element.<br><em>option:</em> The option to render.<br><em>state:</em> The state of each option.<br><em>ownerState:</em> The state of the Autocomplete component.",
"renderTags": "Render the selected value.<br><br><strong>Signature:</strong><br><code>function(value: Array&lt;T&gt;, getTagProps: function, ownerState: object) =&gt; ReactNode</code><br><em>value:</em> The <code>value</code> provided to the component.<br><em>getTagProps:</em> A tag props getter.<br><em>ownerState:</em> The state of the Autocomplete component.",
"selectOnFocus": "If <code>true</code>, the input&#39;s text is selected on focus. It helps the user clear the selected value.",
"size": "The size of the component.",
Expand Down
4 changes: 3 additions & 1 deletion packages/mui-material/src/Autocomplete/Autocomplete.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,15 @@ export interface AutocompleteProps<
*
* @param {object} props The props to apply on the li element.
* @param {T} option The option to render.
* @param {object} state The state of the component.
ZeeshanTamboli marked this conversation as resolved.
Show resolved Hide resolved
* @param {object} state The state of each option.
* @param {object} ownerState The state of the Autocomplete component.
* @returns {ReactNode}
*/
renderOption?: (
props: React.HTMLAttributes<HTMLLIElement>,
option: T,
state: AutocompleteRenderOptionState,
ownerState: AutocompleteOwnerState<T, Multiple, DisableClearable, FreeSolo, ChipComponent>,
) => React.ReactNode;
/**
* Render the selected value.
Expand Down
18 changes: 12 additions & 6 deletions packages/mui-material/src/Autocomplete/Autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -552,11 +552,16 @@ const Autocomplete = React.forwardRef(function Autocomplete(inProps, ref) {
const renderListOption = (option, index) => {
const optionProps = getOptionProps({ option, index });

return renderOption({ ...optionProps, className: classes.option }, option, {
selected: optionProps['aria-selected'],
index,
inputValue,
});
return renderOption(
{ ...optionProps, className: classes.option },
option,
{
selected: optionProps['aria-selected'],
index,
inputValue,
},
ownerState,
);
};

const clearIndicatorSlotProps = slotProps.clearIndicator ?? componentsProps.clearIndicator;
Expand Down Expand Up @@ -1064,7 +1069,8 @@ Autocomplete.propTypes /* remove-proptypes */ = {
*
* @param {object} props The props to apply on the li element.
* @param {T} option The option to render.
* @param {object} state The state of the component.
* @param {object} state The state of each option.
* @param {object} ownerState The state of the Autocomplete component.
* @returns {ReactNode}
*/
renderOption: PropTypes.func,
Expand Down
21 changes: 21 additions & 0 deletions packages/mui-material/src/Autocomplete/Autocomplete.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3001,6 +3001,27 @@ describe('<Autocomplete />', () => {
});
});

describe('prop: renderOption', () => {
it('should pass getOptionLabel through ownerState in renderOption callback', () => {
render(
<Autocomplete
open
options={[{ name: 'Max' }]}
getOptionLabel={(option) => option.name}
renderInput={(params) => <TextField {...params} autoFocus />}
renderOption={(props, option, optionState, ownerState) => (
<li key={option.name} data-testid="optionLi">
{ownerState.getOptionLabel(option)}
</li>
)}
/>,
);

const renderedOption = screen.getByTestId('optionLi');
expect(renderedOption).to.have.text('Max');
});
});

// https://github.com/mui/material-ui/issues/36212
it('should preserve scrollTop position of the listbox when adding new options on mobile', function test() {
if (/jsdom/.test(window.navigator.userAgent)) {
Expand Down