Skip to content

Commit

Permalink
chore(react-tag-picker): ensure Click and Enter open/close popover pr…
Browse files Browse the repository at this point in the history
…operly (#31010)
  • Loading branch information
bsunderhus authored Apr 10, 2024
1 parent bd8b04a commit 889bb44
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "chore: ensure Click and Enter open/close popover properly",
"packageName": "@fluentui/react-tag-picker-preview",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ExtractSlotProps,
Slot,
getIntrinsicElementProps,
isResolvedShorthand,
slot,
useEventCallback,
useMergedRefs,
Expand All @@ -27,9 +28,10 @@ export const useTagPickerControl_unstable = (
props: TagPickerControlProps,
ref: React.Ref<HTMLDivElement>,
): TagPickerControlState => {
const targetRef = useTagPickerContext_unstable(ctx => ctx.targetRef) as React.RefObject<HTMLDivElement>;
const open = useTagPickerContext_unstable(ctx => ctx.open);
const targetRef = useTagPickerContext_unstable(ctx => ctx.targetRef);
const triggerRef = useTagPickerContext_unstable(ctx => ctx.triggerRef);
const open = useTagPickerContext_unstable(ctx => ctx.open);
const setOpen = useTagPickerContext_unstable(ctx => ctx.setOpen);
const secondaryInnerActionRef = useTagPickerContext_unstable(ctx => ctx.secondaryActionRef);
const size = useTagPickerContext_unstable(ctx => ctx.size);
const appearance = useTagPickerContext_unstable(ctx => ctx.appearance);
Expand All @@ -38,18 +40,14 @@ export const useTagPickerControl_unstable = (

const innerRef = React.useRef<HTMLDivElement>(null);

const handleMouseDown = useEventCallback((event: React.MouseEvent<HTMLDivElement>) => {
if (event.target !== triggerRef.current) {
event.preventDefault();
}
});
const secondaryAction = slot.optional(props.secondaryAction, {
elementType: 'span',
});
const secondaryActionRef = useMergedRefs(secondaryInnerActionRef, secondaryAction?.ref);
if (secondaryAction) {
secondaryAction.ref = secondaryActionRef;
}

const expandIcon = slot.optional(props.expandIcon, {
renderByDefault: true,
defaultProps: {
Expand All @@ -59,6 +57,24 @@ export const useTagPickerControl_unstable = (
},
elementType: 'span',
});

// mousedown instead of click as by preventing default of mousedown we're
// avoiding losing focus on trigger
const handleExpandIconMouseDown: React.MouseEventHandler<HTMLSpanElement> = useEventCallback(event => {
if (isResolvedShorthand(props.expandIcon)) {
props.expandIcon.onMouseDown?.(event);
}
if (event.isDefaultPrevented()) {
return;
}
event.preventDefault();
setOpen(event, !open);
triggerRef.current?.focus();
});
if (expandIcon) {
expandIcon.onMouseDown = handleExpandIconMouseDown;
}

const observerRef = useResizeObserverRef<HTMLSpanElement>(([entry]) => {
innerRef.current?.style.setProperty(tagPickerControlAsideWidthToken, `${entry.contentRect.width}px`);
});
Expand All @@ -77,7 +93,6 @@ export const useTagPickerControl_unstable = (
root: slot.always(
getIntrinsicElementProps('div', {
ref: useMergedRefs(ref, targetRef, innerRef),
onMouseDown: handleMouseDown,
...props,
}),
{ elementType: 'div' },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,14 @@ export const useTagPickerInput_unstable = (
onKeyDown: useEventCallback((event: React.KeyboardEvent<HTMLInputElement>) => {
props.onKeyDown?.(event);
if (event.key === Enter) {
ReactDOM.unstable_batchedUpdates(() => {
setValue(undefined);
setOpen(event, false);
});
if (open) {
ReactDOM.unstable_batchedUpdates(() => {
setValue(undefined);
setOpen(event, false);
});
} else {
setOpen(event, true);
}
}

if (event.key === Backspace && value?.length === 0 && selectedOptions.length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface TagPickerContextValue
triggerRef: React.RefObject<HTMLInputElement>;
popoverRef: React.RefObject<HTMLDivElement>;
popoverId: string;
targetRef: React.RefObject<HTMLElement>;
targetRef: React.RefObject<HTMLDivElement>;
secondaryActionRef: React.RefObject<HTMLSpanElement>;
tagPickerGroupRef: React.RefObject<HTMLDivElement>;
size: TagPickerSize;
Expand All @@ -37,7 +37,7 @@ export const tagPickerContextDefaultValue: TagPickerContextValue = {
multiselect: false,
triggerRef: React.createRef<HTMLInputElement>(),
popoverRef: React.createRef<HTMLDivElement>(),
targetRef: React.createRef<HTMLElement>(),
targetRef: React.createRef<HTMLDivElement>(),
tagPickerGroupRef: React.createRef<HTMLDivElement>(),
secondaryActionRef: React.createRef<HTMLDivElement>(),
open: false,
Expand Down

0 comments on commit 889bb44

Please sign in to comment.