From fb87c9b166be5bcfa2c8b7797a79d34554335643 Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Sun, 22 Mar 2020 21:32:44 +0100 Subject: [PATCH] polish :) --- docs/pages/api-docs/autocomplete.md | 3 +- .../{FilterMaxTags.js => LimitTags.js} | 22 +++++---- .../{FilterMaxTags.tsx => LimitTags.tsx} | 6 +-- .../components/autocomplete/autocomplete.md | 34 +++++++------- .../src/Autocomplete/Autocomplete.d.ts | 12 ++++- .../src/Autocomplete/Autocomplete.js | 33 +++++++++---- .../src/Autocomplete/Autocomplete.test.js | 46 ++++++------------- 7 files changed, 80 insertions(+), 76 deletions(-) rename docs/src/pages/components/autocomplete/{FilterMaxTags.js => LimitTags.js} (94%) rename docs/src/pages/components/autocomplete/{FilterMaxTags.tsx => LimitTags.tsx} (97%) diff --git a/docs/pages/api-docs/autocomplete.md b/docs/pages/api-docs/autocomplete.md index c7c5761fa951a1..f70c2f82aafb48 100644 --- a/docs/pages/api-docs/autocomplete.md +++ b/docs/pages/api-docs/autocomplete.md @@ -41,11 +41,11 @@ You can learn more about the difference by [reading this guide](/guides/minimizi | disabled | bool | false | If `true`, the input will be disabled. | | disableListWrap | bool | false | If `true`, the list box in the popup will not wrap focus. | | disablePortal | bool | false | Disable the portal behavior. The children stay within it's parent DOM hierarchy. | -| filterMaxTags | number | | The number of tags that will be visible. Set `-1` to display them all. | | filterOptions | func | | A filter function that determines the options that are eligible.

**Signature:**
`function(options: T[], state: object) => undefined`
*options:* The options to render.
*state:* The state of the component. | | filterSelectedOptions | bool | false | If `true`, hide the selected options from the list box. | | forcePopupIcon | 'auto'
| bool
| 'auto' | Force the visibility display of the popup icon. | | freeSolo | bool | false | If `true`, the Autocomplete is free solo, meaning that the user input is not bound to provided options. | +| getLimitTagsText | func | (more) => `+${more}` | The label to display when the tags are truncated (`limitTags`).

**Signature:**
`function(more: number) => ReactNode`
*more:* The number of truncated tags. | | getOptionDisabled | func | | Used to determine the disabled state for a given option. | | getOptionLabel | func | (x) => x | Used to determine the string value for a given option. It's used to fill the input (and the list box options if `renderOption` is not provided). | | getOptionSelected | func | | Used to determine if an option is selected. Uses strict equality by default. | @@ -53,6 +53,7 @@ You can learn more about the difference by [reading this guide](/guides/minimizi | id | string | | This prop is used to help implement the accessibility logic. If you don't provide this prop. It falls back to a randomly generated id. | | includeInputInList | bool | false | If `true`, the highlight can move to the input. | | inputValue | string | | The input value. | +| limitTags | number | -1 | The maximum number of tags that will be visible when not focused. Set `-1` to disable the limit. | | ListboxComponent | elementType | 'ul' | The component used to render the listbox. | | ListboxProps | object | | Props applied to the Listbox element. | | loading | bool | false | If `true`, the component is in a loading state. | diff --git a/docs/src/pages/components/autocomplete/FilterMaxTags.js b/docs/src/pages/components/autocomplete/LimitTags.js similarity index 94% rename from docs/src/pages/components/autocomplete/FilterMaxTags.js rename to docs/src/pages/components/autocomplete/LimitTags.js index 8354edf95e82b3..8de5628b5330e2 100644 --- a/docs/src/pages/components/autocomplete/FilterMaxTags.js +++ b/docs/src/pages/components/autocomplete/LimitTags.js @@ -4,29 +4,31 @@ import Autocomplete from '@material-ui/lab/Autocomplete'; import { makeStyles } from '@material-ui/core/styles'; import TextField from '@material-ui/core/TextField'; -const useStyles = makeStyles((theme) => ({ - root: { - width: 500, - '& > * + *': { - marginTop: theme.spacing(3), +const useStyles = makeStyles( + (theme) => ({ + root: { + width: 500, + '& > * + *': { + marginTop: theme.spacing(3), + }, }, - }, -})); + }), +); -export default function FilterMaxTags() { +export default function LimitTags() { const classes = useStyles(); return (
option.title} defaultValue={[top100Films[13], top100Films[12], top100Films[11]]} renderInput={(params) => ( - + )} />
diff --git a/docs/src/pages/components/autocomplete/FilterMaxTags.tsx b/docs/src/pages/components/autocomplete/LimitTags.tsx similarity index 97% rename from docs/src/pages/components/autocomplete/FilterMaxTags.tsx rename to docs/src/pages/components/autocomplete/LimitTags.tsx index a64ea509b30b77..8c7c8ea8a5af8a 100644 --- a/docs/src/pages/components/autocomplete/FilterMaxTags.tsx +++ b/docs/src/pages/components/autocomplete/LimitTags.tsx @@ -15,20 +15,20 @@ const useStyles = makeStyles((theme: Theme) => }), ); -export default function FilterMaxTags() { +export default function LimitTags() { const classes = useStyles(); return (
option.title} defaultValue={[top100Films[13], top100Films[12], top100Films[11]]} renderInput={(params) => ( - + )} />
diff --git a/docs/src/pages/components/autocomplete/autocomplete.md b/docs/src/pages/components/autocomplete/autocomplete.md index dd8c560324d011..dd174a00644a76 100644 --- a/docs/src/pages/components/autocomplete/autocomplete.md +++ b/docs/src/pages/components/autocomplete/autocomplete.md @@ -100,12 +100,6 @@ Also known as tags, the user is allowed to enter more than one value. {{"demo": "pages/components/autocomplete/Tags.js"}} -## Filter Max Tags - -Do you want to show only a few tags? Use the `filterMaxTags` prop. - -{{"demo": "pages/components/autocomplete/FilterMaxTags.js"}} - ### Fixed options In the event that you need to lock certain tag so that they can't be removed in the interface, you can set the chips disabled. @@ -116,6 +110,12 @@ In the event that you need to lock certain tag so that they can't be removed in {{"demo": "pages/components/autocomplete/CheckboxesTags.js"}} +### Limit tags + +You can use the `limitTags` prop to limit the number of displayed options when not focused. + +{{"demo": "pages/components/autocomplete/LimitTags.js"}} + ## Sizes Fancy smaller inputs? Use the `size` prop. @@ -149,14 +149,13 @@ import { createFilterOptions } from '@material-ui/lab/Autocomplete'; #### Arguments -1. `config` (_Object_ [optional]): - -- `config.ignoreAccents` (_Boolean_ [optional]): Defaults to `true`. Remove diacritics. -- `config.ignoreCase` (_Boolean_ [optional]): Defaults to `true`. Lowercase everything. -- `config.matchFrom` (_'any' | 'start'_ [optional]): Defaults to `'any'`. -- `config.stringify` (_Func_ [optional]): Controls how an option is converted into a string so that it can be matched against the input text fragment. -- `config.trim` (_Boolean_ [optional]): Defaults to `false`. Remove trailing spaces. -- `config.limit` (_Number_ [optional]): Default to null. Limit the number of suggested options to be shown. For example, if `config.limit` is `100`, only the first `100` matching options are shown. It can be useful if a lot of options match and virtualization wasn't set up. +1. `config` (*Object* [optional]): + - `config.ignoreAccents` (*Boolean* [optional]): Defaults to `true`. Remove diacritics. + - `config.ignoreCase` (*Boolean* [optional]): Defaults to `true`. Lowercase everything. + - `config.matchFrom` (*'any' | 'start'* [optional]): Defaults to `'any'`. + - `config.stringify` (*Func* [optional]): Controls how an option is converted into a string so that it can be matched against the input text fragment. + - `config.trim` (*Boolean* [optional]): Defaults to `false`. Remove trailing spaces. + - `config.limit` (*Number* [optional]): Default to null. Limit the number of suggested options to be shown. For example, if `config.limit` is `100`, only the first `100` matching options are shown. It can be useful if a lot of options match and virtualization wasn't set up. #### Returns @@ -170,7 +169,7 @@ const filterOptions = createFilterOptions({ stringify: option => option.title, }); -; + ``` {{"demo": "pages/components/autocomplete/Filter.js", "defaultCodeOpen": false}} @@ -182,9 +181,10 @@ For richer filtering mechanisms, like fuzzy matching, it's recommended to look a ```jsx import matchSorter from 'match-sorter'; -const filterOptions = (options, { inputValue }) => matchSorter(options, inputValue); +const filterOptions = (options, { inputValue }) => + matchSorter(options, inputValue); -; + ``` ## Virtualization diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.d.ts b/packages/material-ui-lab/src/Autocomplete/Autocomplete.d.ts index d6f46b985446b9..d60dea008cc3c7 100644 --- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.d.ts +++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.d.ts @@ -84,9 +84,12 @@ export interface AutocompleteProps */ forcePopupIcon?: true | false | 'auto'; /** - * The number of tags that will be visible. Set `-1` to display them all. + * The label to display when the tags are truncated (`limitTags`). + * + * @param {number} more The number of truncated tags. + * @returns {ReactNode} */ - filterMaxTags?: number; + getLimitTagsText?: (more: number) => React.ReactNode; /** * The component used to render the listbox. */ @@ -105,6 +108,11 @@ export interface AutocompleteProps * For localization purposes, you can use the provided [translations](/guides/localization/). */ loadingText?: React.ReactNode; + /** + * The maximum number of tags that will be visible when not focused. + * Set `-1` to disable the limit. + */ + limitTags?: number; /** * Text to display when there are no options. * diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.js index 1752ae671bb095..7d55e59da3f3de 100644 --- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.js +++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.js @@ -257,6 +257,7 @@ const Autocomplete = React.forwardRef(function Autocomplete(props, ref) { filterSelectedOptions = false, forcePopupIcon = 'auto', freeSolo = false, + getLimitTagsText = (more) => `+${more}`, getOptionDisabled, getOptionLabel = (x) => x, getOptionSelected, @@ -264,12 +265,12 @@ const Autocomplete = React.forwardRef(function Autocomplete(props, ref) { id: idProp, includeInputInList = false, inputValue: inputValueProp, + limitTags = -1, ListboxComponent = 'ul', ListboxProps, loading = false, loadingText = 'Loading…', multiple = false, - filterMaxTags, noOptionsText = 'No options', onChange, onClose, @@ -341,11 +342,15 @@ const Autocomplete = React.forwardRef(function Autocomplete(props, ref) { } } - if (filterMaxTags && Array.isArray(startAdornment)) { - const more = startAdornment.length - filterMaxTags; - if (filterMaxTags && !focused && more > 0) { - startAdornment = startAdornment.splice(0, filterMaxTags); - startAdornment.push({` + ${more} more`}); + if (limitTags && Array.isArray(startAdornment)) { + const more = startAdornment.length - limitTags; + if (limitTags && !focused && more > 0) { + startAdornment = startAdornment.splice(0, limitTags); + startAdornment.push( + + {getLimitTagsText(more)} + , + ); } } @@ -581,10 +586,6 @@ Autocomplete.propTypes = { * The children stay within it's parent DOM hierarchy. */ disablePortal: PropTypes.bool, - /** - * The number of tags that will be visible. Set `-1` to display them all. - */ - filterMaxTags: PropTypes.number, /** * A filter function that determines the options that are eligible. * @@ -605,6 +606,13 @@ Autocomplete.propTypes = { * If `true`, the Autocomplete is free solo, meaning that the user input is not bound to provided options. */ freeSolo: PropTypes.bool, + /** + * The label to display when the tags are truncated (`limitTags`). + * + * @param {number} more The number of truncated tags. + * @returns {ReactNode} + */ + getLimitTagsText: PropTypes.func, /** * Used to determine the disabled state for a given option. */ @@ -640,6 +648,11 @@ Autocomplete.propTypes = { * The input value. */ inputValue: PropTypes.string, + /** + * The maximum number of tags that will be visible when not focused. + * Set `-1` to disable the limit. + */ + limitTags: PropTypes.number, /** * The component used to render the listbox. */ diff --git a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js index e0b009be6712f5..2b3fe008b9e15b 100644 --- a/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js +++ b/packages/material-ui-lab/src/Autocomplete/Autocomplete.test.js @@ -97,48 +97,28 @@ describe('', () => { }); }); - describe('prop: filterMaxTags', () => { - it('show only the max number of items', () => { - const { queryByTestId, getAllByRole } = render( - } - />, - ); - - const tags = getAllByRole('button'); - expect(queryByTestId('more')).to.be.exist; - expect(tags[0].textContent).to.be.equal('one'); - expect(tags[1].textContent).to.be.equal('two'); - expect(tags[2].textContent).to.not.be.equal('three'); - }); - + describe('prop: limitTags', () => { it('show all items on focus', () => { - const { getAllByRole, queryByTestId, getByRole } = render( + const { container, getAllByRole, getByRole } = render( } + renderInput={(params) => } />, ); - const input = getByRole('textbox'); - expect(getAllByRole('button')[2].textContent).to.not.be.equal('three'); - expect(queryByTestId('more')).to.exist; + let tags; + tags = getAllByRole('button'); + expect(container.textContent).to.equal('onetwo+1'); + expect(tags.length).to.be.equal(4); - input.focus(); - const tags = getAllByRole('button'); - expect(queryByTestId('more')).to.not.exist; - expect(tags[0].textContent).to.be.equal('one'); - expect(tags[1].textContent).to.be.equal('two'); - expect(tags[2].textContent).to.be.equal('three'); + getByRole('textbox').focus(); + tags = getAllByRole('button'); + expect(container.textContent).to.equal('onetwothree'); + expect(tags.length).to.be.equal(5); }); });