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

Enhancement focusOnHover Prop #6228

Merged
merged 14 commits into from
Mar 27, 2024
Merged
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
3 changes: 1 addition & 2 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
//Remove '*' during the development.
*
*
32 changes: 32 additions & 0 deletions components/doc/common/apidoc/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -23094,6 +23094,14 @@
"default": "",
"description": "Reference of the focusable input element."
},
{
"name": "focusOnHover",
"optional": true,
"readonly": false,
"type": "boolean",
"default": "true",
"description": "When enabled, the focus is placed on the hovered option."
},
{
"name": "highlightOnSelect",
"optional": true,
Expand Down Expand Up @@ -35723,6 +35731,14 @@
"default": "false",
"description": "Use flex layout for the items panel."
},
{
"name": "focusOnHover",
"optional": true,
"readonly": false,
"type": "boolean",
"default": "true",
"description": "When enabled, the focus is placed on the hovered option."
},
{
"name": "id",
"optional": true,
Expand Down Expand Up @@ -37376,6 +37392,14 @@
"default": "",
"description": "Custom template of filter element."
},
{
"name": "focusOnHover",
"optional": true,
"readonly": false,
"type": "boolean",
"default": "true",
"description": "When enabled, the focus is placed on the hovered option."
},
{
"name": "header",
"optional": true,
Expand Down Expand Up @@ -41405,6 +41429,14 @@
"default": "contains",
"description": "Defines how the items are filtered, valid values are \"contains\" (default) \"startsWith\", \"endsWith\", \"equals\", \"notEquals\", \"in\", \"notIn\", \"lt\", \"lte\", \"gt\" and \"gte\"."
},
{
"name": "focusOnHover",
"optional": true,
"readonly": false,
"type": "boolean",
"default": "true",
"description": "When enabled, the focus is placed on the hovered option."
},
{
"name": "id",
"optional": true,
Expand Down
6 changes: 3 additions & 3 deletions components/lib/dropdown/Dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -1251,9 +1251,9 @@ export const Dropdown = React.memo(
onOptionClick={onOptionClick}
ptm={ptm}
resetFilter={resetFilter}
setFocusedOptionIndex={setFocusedOptionIndex}
firstFocusableElement={<span {...firstHiddenFocusableElementProps}></span>}
lastFocusableElement={<span {...lastHiddenFocusableElementProps}></span>}
changeFocusedOptionIndex={changeFocusedOptionIndex}
firstFocusableElement={<span {...firstHiddenFocusableElementProps} />}
lastFocusableElement={<span {...lastHiddenFocusableElementProps} />}
sx={sx}
/>
</div>
Expand Down
1 change: 1 addition & 0 deletions components/lib/dropdown/DropdownBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ export const DropdownBase = ComponentBase.extend({
optionDisabled: null,
optionGroupChildren: 'items',
selectOnFocus: false,
focusOnHover: true,
autoOptionFocus: false,
optionGroupLabel: null,
optionGroupTemplate: null,
Expand Down
1 change: 1 addition & 0 deletions components/lib/dropdown/DropdownItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const DropdownItem = React.memo((props) => {
className: classNames(option.className, cx('item', { selected, disabled, label, index, focusedOptionIndex, highlightOnSelect })),
style: props.style,
onClick: (e) => onClick(e, index),
onMouseMove: (e) => props?.onMouseMove(e, index),
'aria-label': label,
'aria-selected': selected,
'data-p-highlight': selected,
Expand Down
9 changes: 8 additions & 1 deletion components/lib/dropdown/DropdownPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export const DropdownPanel = React.memo(
const mergeProps = useMergeProps();
const { ptm, cx, sx } = props;
const context = React.useContext(PrimeReactContext);
const virtualScrollerRef = React.useRef(null);

const filterInputRef = React.useRef(null);
const isEmptyFilter = !(props.visibleOptions && props.visibleOptions.length) && props.hasFilter;
Expand Down Expand Up @@ -71,6 +70,12 @@ export const DropdownPanel = React.memo(
return null;
};

const changeFocusedItemOnHover = (event, index) => {
if (props.focusOnHover) {
props?.changeFocusedOptionIndex?.(event, index);
}
};

const createGroupChildren = (optionGroup, style) => {
const groupChildren = props.getOptionGroupChildren(optionGroup);

Expand All @@ -92,6 +97,7 @@ export const DropdownPanel = React.memo(
highlightOnSelect={props.highlightOnSelect}
disabled={disabled}
onClick={props.onOptionClick}
onMouseMove={changeFocusedItemOnHover}
ptm={ptm}
cx={cx}
checkmark={props.checkmark}
Expand Down Expand Up @@ -163,6 +169,7 @@ export const DropdownPanel = React.memo(
highlightOnSelect={props.highlightOnSelect}
disabled={disabled}
onClick={props.onOptionClick}
onMouseMove={changeFocusedItemOnHover}
ptm={ptm}
cx={cx}
checkmark={props.checkmark}
Expand Down
5 changes: 5 additions & 0 deletions components/lib/dropdown/dropdown.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,11 @@ export interface DropdownProps extends Omit<React.DetailedHTMLProps<React.InputH
* @defaultValue false
*/
selectOnFocus?: false;
/**
* When enabled, the focus is placed on the hovered option.
* @defaultValue true
*/
focusOnHover?: boolean | undefined;
/**
* Whether to focus on the first visible or selected element.
* @defaultValue false
Expand Down
1 change: 1 addition & 0 deletions components/lib/multiselect/MultiSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -1107,6 +1107,7 @@ export const MultiSelect = React.memo(
sx={sx}
isUnstyled={isUnstyled}
metaData={metaData}
changeFocusedOptionIndex={changeFocusedOptionIndex}
/>
</div>
{hasTooltip && <Tooltip target={elementRef} content={props.tooltip} pt={ptm('tooltip')} {...props.tooltipOptions} />}
Expand Down
1 change: 1 addition & 0 deletions components/lib/multiselect/MultiSelectBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ export const MultiSelectBase = ComponentBase.extend({
filterInputAutoFocus: true,
filterLocale: undefined,
selectOnFocus: false,
focusOnHover: true,
autoOptionFocus: false,
filterMatchMode: 'contains',
filterPlaceholder: null,
Expand Down
1 change: 1 addition & 0 deletions components/lib/multiselect/MultiSelectItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export const MultiSelectItem = React.memo((props) => {
onClick: onClick,
onFocus: onFocus,
onBlur: onBlur,
onMouseMove: (e) => props?.onMouseMove(e, props.index),
tabIndex: tabIndex,
role: 'option',
'aria-selected': props.selected,
Expand Down
8 changes: 8 additions & 0 deletions components/lib/multiselect/MultiSelectPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ export const MultiSelectPanel = React.memo(
return null;
};

const changeFocusedItemOnHover = (event, index) => {
if (props.focusOnHover) {
props?.changeFocusedOptionIndex?.(event, index);
}
};

const createGroupChildren = (optionGroup, style) => {
const groupChildren = props.getOptionGroupChildren(optionGroup);

Expand All @@ -116,6 +122,7 @@ export const MultiSelectPanel = React.memo(
template={props.itemTemplate}
selected={selected}
onClick={props.onOptionSelect}
onMouseMove={changeFocusedItemOnHover}
tabIndex={tabIndex}
disabled={disabled}
className={props.itemClassName}
Expand Down Expand Up @@ -194,6 +201,7 @@ export const MultiSelectPanel = React.memo(
template={props.itemTemplate}
selected={selected}
onClick={props.onOptionSelect}
onMouseMove={changeFocusedItemOnHover}
tabIndex={tabIndex}
disabled={disabled}
className={props.itemClassName}
Expand Down
5 changes: 5 additions & 0 deletions components/lib/multiselect/multiselect.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,11 @@ export interface MultiSelectProps extends Omit<React.DetailedHTMLProps<React.Inp
* @defaultValue false
*/
selectOnFocus?: false;
/**
* When enabled, the focus is placed on the hovered option.
* @defaultValue true
*/
focusOnHover?: boolean | undefined;
/**
* Whether to focus on the first visible or selected element.
* @defaultValue false
Expand Down
2 changes: 2 additions & 0 deletions components/lib/orderlist/OrderList.js
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,8 @@ export const OrderList = React.memo(
isUnstyled={isUnstyled}
ptm={ptm}
cx={cx}
changeFocusedOptionIndex={changeFocusedOptionIndex}
{...props}
/>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions components/lib/orderlist/OrderListBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export const OrderListBase = ComponentBase.extend({
moveBottomIcon: null,
dataKey: null,
autoOptionFocus: true,
focusOnHover: true,
breakpoint: '960px',
onChange: null,
itemTemplate: null,
Expand Down
8 changes: 8 additions & 0 deletions components/lib/orderlist/OrderListSubList.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ export const OrderListSubList = React.memo(
}
};

const changeFocusedItemOnHover = (event, index) => {
if (props.focusOnHover && props.focused) {
props?.changeFocusedOptionIndex?.(index);
}
};

const createDropPoint = (index, key) => {
const droppointProps = mergeProps(
{
Expand Down Expand Up @@ -142,6 +148,7 @@ export const OrderListSubList = React.memo(
draggable: 'true',
onClick: (e) => props.onItemClick({ originalEvent: e, value: item, index: i }),
onMouseDown: props.onOptionMouseDown,
onMouseMove: (e) => changeFocusedItemOnHover(e, i),
onDragStart: (e) => onDragStart(e, i),
onDragEnd: onDragEnd,
className: classNames(props.className, cx('item', { selected, focused })),
Expand Down Expand Up @@ -175,6 +182,7 @@ export const OrderListSubList = React.memo(
role: 'option',
onClick: (e) => props.onItemClick({ originalEvent: e, value: item, index: i }),
onMouseDown: props.onOptionMouseDown,
onMouseMove: (e) => changeFocusedItemOnHover(e, i),
className: classNames(props.className, cx('item', { selected, focused })),
'aria-selected': selected,
'data-p-highlight': selected,
Expand Down
5 changes: 5 additions & 0 deletions components/lib/orderlist/orderlist.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ export interface OrderListProps extends Omit<React.DetailedHTMLProps<React.HTMLA
* @defaultValue true
*/
autoOptionFocus?: boolean | undefined;
/**
* When enabled, the focus is placed on the hovered option.
* @defaultValue true
*/
focusOnHover?: boolean | undefined;
/**
* Inline style of the list element.
*/
Expand Down
6 changes: 6 additions & 0 deletions components/lib/picklist/PickList.js
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,9 @@ export const PickList = React.memo(
sourceFilterIcon={props.sourceFilterIcon}
ptm={ptm}
cx={cx}
focusedList={focused}
changeFocusedOptionIndex={changeFocusedOptionIndex}
focusOnHover={props.focusOnHover}
/>

<PickListTransferControls
Expand Down Expand Up @@ -706,6 +709,9 @@ export const PickList = React.memo(
targetFilterIcon={props.targetFilterIcon}
ptm={ptm}
cx={cx}
focusedList={focused}
changeFocusedOptionIndex={changeFocusedOptionIndex}
focusOnHover={props.focusOnHover}
/>

{props.showTargetControls && (
Expand Down
1 change: 1 addition & 0 deletions components/lib/picklist/PickListBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export const PickListBase = ComponentBase.extend({
tabIndex: 0,
dataKey: null,
autoOptionFocus: true,
focusOnHover: true,
breakpoint: '960px',
itemTemplate: null,
sourceItemTemplate: null,
Expand Down
1 change: 1 addition & 0 deletions components/lib/picklist/PickListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const PickListItem = React.memo((props) => {
onKeyDown,
onFocus,
onMouseDown,
onMouseMove: props.onMouseMove,
role: 'option',
'aria-selected': props.selected,
'data-p-highlight': props.selected,
Expand Down
7 changes: 7 additions & 0 deletions components/lib/picklist/PickListSubList.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ export const PickListSubList = React.memo(
return null;
};

const changeFocusedItemOnHover = (index) => {
if (props.focusOnHover && props.focusedList[props.type]) {
props?.changeFocusedOptionIndex?.(index, props.type);
}
};

const createItems = () => {
if (props.list) {
return props.list.map((item, index) => {
Expand All @@ -76,6 +82,7 @@ export const PickListSubList = React.memo(
onClick={props.onItemClick}
onKeyDown={props.onItemKeyDown}
onMouseDown={(event) => props.onOptionMouseDown({ ...event, index, type: props.type })}
onMouseMove={() => changeFocusedItemOnHover(index)}
ptm={ptm}
cx={cx}
/>
Expand Down
5 changes: 5 additions & 0 deletions components/lib/picklist/picklist.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ export interface PickListProps {
* @defaultValue true
*/
autoOptionFocus?: boolean | undefined;
/**
* When enabled, the focus is placed on the hovered option.
* @defaultValue true
*/
focusOnHover?: boolean | undefined;
/**
* Inline style of the element.
*/
Expand Down
Loading