Skip to content

Commit

Permalink
polish
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviertassinari committed Mar 25, 2020
1 parent 0994ea6 commit 0c0a22e
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 148 deletions.
2 changes: 1 addition & 1 deletion docs/pages/api-docs/autocomplete.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ You can learn more about the difference by [reading this guide](/guides/minimizi
| <span class="prop-name">disableClearable</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, the input can't be cleared. |
| <span class="prop-name">disableCloseOnSelect</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, the popup won't close when a value is selected. |
| <span class="prop-name">disabled</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, the input will be disabled. |
| <span class="prop-name">disabledItemsFocusable</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, will allow focus on disabled items. |
| <span class="prop-name">disableListWrap</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, the list box in the popup will not wrap focus. |
| <span class="prop-name">disablePortal</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | Disable the portal behavior. The children stay within it's parent DOM hierarchy. |
| <span class="prop-name">enableFocusForDisabledItems</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, will allow focus on disabled items. |
| <span class="prop-name">filterOptions</span> | <span class="prop-type">func</span> | | A filter function that determines the options that are eligible.<br><br>**Signature:**<br>`function(options: T[], state: object) => undefined`<br>*options:* The options to render.<br>*state:* The state of the component. |
| <span class="prop-name">filterSelectedOptions</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, hide the selected options from the list box. |
| <span class="prop-name">forcePopupIcon</span> | <span class="prop-type">'auto'<br>&#124;&nbsp;bool</span> | <span class="prop-default">'auto'</span> | Force the visibility display of the popup icon. |
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/api-docs/menu-list.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ the focus is placed inside the component it is fully keyboard accessible.
| <span class="prop-name">autoFocus</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, will focus the `[role="menu"]` container and move into tab order. |
| <span class="prop-name">autoFocusItem</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, will focus the first menuitem if `variant="menu"` or selected item if `variant="selectedMenu"`. |
| <span class="prop-name">children</span> | <span class="prop-type">node</span> | | MenuList contents, normally `MenuItem`s. |
| <span class="prop-name">disabledItemsFocusable</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, will allow focus on disabled items. |
| <span class="prop-name">disableListWrap</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, the menu items will not wrap focus. |
| <span class="prop-name">enableFocusForDisabledItems</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, will allow focus on disabled items. |
| <span class="prop-name">variant</span> | <span class="prop-type">'menu'<br>&#124;&nbsp;'selectedMenu'</span> | <span class="prop-default">'selectedMenu'</span> | The variant to use. Use `menu` to prevent selected items from impacting the initial focus and the vertical alignment relative to the anchor element. |

The `ref` is forwarded to the root element.
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/components/autocomplete/LimitTags.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function LimitTags() {
<Autocomplete
multiple
limitTags={2}
id="tags-standard"
id="limit-tags"
options={top100Films}
getOptionLabel={(option) => option.title}
defaultValue={[top100Films[13], top100Films[12], top100Films[11]]}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/components/autocomplete/LimitTags.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default function LimitTags() {
<Autocomplete
multiple
limitTags={2}
id="tags-standard"
id="limit-tags"
options={top100Films}
getOptionLabel={(option) => option.title}
defaultValue={[top100Films[13], top100Films[12], top100Films[11]]}
Expand Down
10 changes: 5 additions & 5 deletions packages/material-ui-lab/src/Autocomplete/Autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,9 @@ const Autocomplete = React.forwardRef(function Autocomplete(props, ref) {
disableClearable = false,
disableCloseOnSelect = false,
disabled = false,
disabledItemsFocusable = false,
disableListWrap = false,
disablePortal = false,
enableFocusForDisabledItems = false,
filterOptions,
filterSelectedOptions = false,
forcePopupIcon = 'auto',
Expand Down Expand Up @@ -578,6 +578,10 @@ Autocomplete.propTypes = {
* If `true`, the input will be disabled.
*/
disabled: PropTypes.bool,
/**
* If `true`, will allow focus on disabled items.
*/
disabledItemsFocusable: PropTypes.bool,
/**
* If `true`, the list box in the popup will not wrap focus.
*/
Expand All @@ -587,10 +591,6 @@ Autocomplete.propTypes = {
* The children stay within it's parent DOM hierarchy.
*/
disablePortal: PropTypes.bool,
/**
* If `true`, will allow focus on disabled items.
*/
enableFocusForDisabledItems: PropTypes.bool,
/**
* A filter function that determines the options that are eligible.
*
Expand Down
24 changes: 12 additions & 12 deletions packages/material-ui-lab/src/useAutocomplete/useAutocomplete.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ export interface UseAutocompleteCommonProps<T> {
*/
disableCloseOnSelect?: boolean;
/**
* If `true`, the list box in the popup will not wrap focus.
* If `true`, will allow focus on disabled items.
*/
disableListWrap?: boolean;
disabledItemsFocusable?: boolean;
/**
* If `true`, will allow focus on disabled items.
* If `true`, the list box in the popup will not wrap focus.
*/
enableFocusForDisabledItems?: boolean;
disableListWrap?: boolean;
/**
* A filter function that determines the options that are eligible.
*
Expand Down Expand Up @@ -184,6 +184,10 @@ export type AutocompleteCloseReason = 'toggleInput' | 'escape' | 'select-option'
export type AutocompleteInputChangeReason = 'input' | 'reset' | 'clear';

export interface UseAutocompleteMultipleProps<T> extends UseAutocompleteCommonProps<T> {
/**
* The default input value. Use when the component is not controlled.
*/
defaultValue?: T[];
/**
* If `true`, `value` must be an array and the menu will support multiple selections.
*/
Expand All @@ -195,10 +199,6 @@ export interface UseAutocompleteMultipleProps<T> extends UseAutocompleteCommonPr
* You can customize the equality behavior with the `getOptionSelected` prop.
*/
value?: T[];
/**
* The default input value. Use when the component is not controlled.
*/
defaultValue?: T[];
/**
* Callback fired when the value changes.
*
Expand All @@ -215,6 +215,10 @@ export interface UseAutocompleteMultipleProps<T> extends UseAutocompleteCommonPr
}

export interface UseAutocompleteSingleProps<T> extends UseAutocompleteCommonProps<T> {
/**
* The default input value. Use when the component is not controlled.
*/
defaultValue?: T;
/**
* If `true`, `value` must be an array and the menu will support multiple selections.
*/
Expand All @@ -226,10 +230,6 @@ export interface UseAutocompleteSingleProps<T> extends UseAutocompleteCommonProp
* You can customize the equality behavior with the `getOptionSelected` prop.
*/
value?: T | null;
/**
* The default input value. Use when the component is not controlled.
*/
defaultValue?: T;
/**
* Callback fired when the value changes.
*
Expand Down
22 changes: 15 additions & 7 deletions packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ export default function useAutocomplete(props) {
defaultValue = props.multiple ? [] : null,
disableClearable = false,
disableCloseOnSelect = false,
disabledItemsFocusable = false,
disableListWrap = false,
enableFocusForDisabledItems = false,
filterOptions = defaultFilterOptions,
filterSelectedOptions = false,
freeSolo = false,
Expand Down Expand Up @@ -313,11 +313,12 @@ export default function useAutocomplete(props) {
const option = listboxRef.current.querySelector(`[data-option-index="${nextFocus}"]`);

// Same logic as MenuList.js
const nextFocusDisabled = enableFocusForDisabledItems
const nextFocusDisabled = disabledItemsFocusable
? false
: option && (option.disabled || option.getAttribute('aria-disabled') === 'true');

if ((option && !option.hasAttribute('tabindex')) || nextFocusDisabled) {
// Move to the next element.
nextFocus += direction === 'next' ? 1 : -1;
} else {
return nextFocus;
Expand Down Expand Up @@ -641,9 +642,16 @@ export default function useAutocomplete(props) {
break;
}
if (highlightedIndexRef.current !== -1 && popupOpen) {
const option = filteredOptions[highlightedIndexRef.current];
const disabled = getOptionDisabled ? getOptionDisabled(option) : false;

if (disabled) {
return;
}

// We don't want to validate the form.
event.preventDefault();
selectNewValue(event, filteredOptions[highlightedIndexRef.current], 'select-option');
selectNewValue(event, option, 'select-option');

// Move the selection to the end.
if (autoComplete) {
Expand Down Expand Up @@ -1012,13 +1020,13 @@ useAutocomplete.propTypes = {
*/
disableCloseOnSelect: PropTypes.bool,
/**
* If `true`, the list box in the popup will not wrap focus.
* If `true`, will allow focus on disabled items.
*/
disableListWrap: PropTypes.bool,
disabledItemsFocusable: PropTypes.bool,
/**
* If `true`, will allow focus on disabled items.
* If `true`, the list box in the popup will not wrap focus.
*/
enableFocusForDisabledItems: PropTypes.bool,
disableListWrap: PropTypes.bool,
/**
* A filter function that determins the options that are eligible.
*
Expand Down
9 changes: 7 additions & 2 deletions packages/material-ui/src/ButtonBase/ButtonBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ const ButtonBase = React.forwardRef(function ButtonBase(props, ref) {
false,
);

const handleFocus = useEventCallback(event => {
const handleFocus = useEventCallback((event) => {
// Fix for https://github.com/facebook/react/issues/7769
if (!buttonRef.current) {
buttonRef.current = event.currentTarget;
Expand Down Expand Up @@ -212,7 +212,12 @@ const ButtonBase = React.forwardRef(function ButtonBase(props, ref) {
}

// Keyboard accessibility for non interactive elements
if (event.target === event.currentTarget && isNonNativeButton() && event.key === 'Enter') {
if (
event.target === event.currentTarget &&
isNonNativeButton() &&
event.key === 'Enter' &&
!disabled
) {
event.preventDefault();
if (onClick) {
onClick(event);
Expand Down
4 changes: 4 additions & 0 deletions packages/material-ui/src/MenuList/MenuList.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export interface MenuListProps extends StandardProps<ListProps, MenuListClassKey
* MenuList contents, normally `MenuItem`s.
*/
children?: React.ReactNode;
/**
* If `true`, will allow focus on disabled items.
*/
disabledItemsFocusable?: boolean;
/**
* If `true`, the menu items will not wrap focus.
*/
Expand Down
44 changes: 22 additions & 22 deletions packages/material-ui/src/MenuList/MenuList.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function moveFocus(
list,
currentFocus,
disableListWrap,
enableFocusForDisabledItems,
disabledItemsFocusable,
traversalFunction,
textCriteria,
) {
Expand All @@ -61,28 +61,28 @@ function moveFocus(
// Prevent infinite loop.
if (nextFocus === list.firstChild) {
if (wrappedOnce) {
return false;
return;
}
wrappedOnce = true;
}

const nextFocusDisabled = enableFocusForDisabledItems
// Same logic as useAutocomplete.js
const nextFocusDisabled = disabledItemsFocusable
? false
: nextFocus.disabled || nextFocus.getAttribute('aria-disabled') === 'true';

if (
!nextFocusDisabled &&
nextFocus.hasAttribute('tabindex') &&
textCriteriaMatches(nextFocus, textCriteria)
!nextFocus.hasAttribute('tabindex') ||
!textCriteriaMatches(nextFocus, textCriteria) ||
nextFocusDisabled
) {
// Move to the next element.
nextFocus = traversalFunction(list, nextFocus, disableListWrap);
} else {
nextFocus.focus();
return true;
return;
}

// Move to the next element.
nextFocus = traversalFunction(list, nextFocus, disableListWrap);
}

return false;
}

const useEnhancedEffect = typeof window === 'undefined' ? React.useEffect : React.useLayoutEffect;
Expand All @@ -102,8 +102,8 @@ const MenuList = React.forwardRef(function MenuList(props, ref) {
autoFocusItem = false,
children,
className,
disabledItemsFocusable = false,
disableListWrap = false,
enableFocusForDisabledItems = false,
onKeyDown,
variant = 'selectedMenu',
...other
Expand Down Expand Up @@ -156,16 +156,16 @@ const MenuList = React.forwardRef(function MenuList(props, ref) {
if (key === 'ArrowDown') {
// Prevent scroll of the page
event.preventDefault();
moveFocus(list, currentFocus, disableListWrap, enableFocusForDisabledItems, nextItem);
moveFocus(list, currentFocus, disableListWrap, disabledItemsFocusable, nextItem);
} else if (key === 'ArrowUp') {
event.preventDefault();
moveFocus(list, currentFocus, disableListWrap, enableFocusForDisabledItems, previousItem);
moveFocus(list, currentFocus, disableListWrap, disabledItemsFocusable, previousItem);
} else if (key === 'Home') {
event.preventDefault();
moveFocus(list, null, disableListWrap, enableFocusForDisabledItems, nextItem);
moveFocus(list, null, disableListWrap, disabledItemsFocusable, nextItem);
} else if (key === 'End') {
event.preventDefault();
moveFocus(list, null, disableListWrap, enableFocusForDisabledItems, previousItem);
moveFocus(list, null, disableListWrap, disabledItemsFocusable, previousItem);
} else if (key.length === 1) {
const criteria = textCriteriaRef.current;
const lowerKey = key.toLowerCase();
Expand All @@ -187,7 +187,7 @@ const MenuList = React.forwardRef(function MenuList(props, ref) {
if (
criteria.previousKeyMatched &&
(keepFocusOnCurrent ||
moveFocus(list, currentFocus, false, enableFocusForDisabledItems, nextItem, criteria))
moveFocus(list, currentFocus, false, disabledItemsFocusable, nextItem, criteria))
) {
event.preventDefault();
} else {
Expand Down Expand Up @@ -293,13 +293,13 @@ MenuList.propTypes = {
*/
className: PropTypes.string,
/**
* If `true`, the menu items will not wrap focus.
* If `true`, will allow focus on disabled items.
*/
disableListWrap: PropTypes.bool,
disabledItemsFocusable: PropTypes.bool,
/**
* If `true`, will allow focus on disabled items.
* If `true`, the menu items will not wrap focus.
*/
enableFocusForDisabledItems: PropTypes.bool,
disableListWrap: PropTypes.bool,
/**
* @ignore
*/
Expand Down
Loading

0 comments on commit 0c0a22e

Please sign in to comment.