Skip to content

Commit

Permalink
chore(react-tabster): bump tabster to 8.5.0. (#33817)
Browse files Browse the repository at this point in the history
  • Loading branch information
mshoho authored Feb 21, 2025
1 parent d43c79e commit 99ddb18
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Update to satisfy the bumped Tabster 8.5.0.",
"packageName": "@fluentui/react-popover",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "Nested modalizer fix and useActivateModal() hook to activate modals without moving focus.",
"packageName": "@fluentui/react-tabster",
"email": "[email protected]",
"dependentChangeType": "minor"
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
mergeArrowOffset,
usePositioningMouseTarget,
} from '@fluentui/react-positioning';
import { useFocusFinders } from '@fluentui/react-tabster';
import { useFocusFinders, useActivateModal } from '@fluentui/react-tabster';
import { arrowHeights } from '../PopoverSurface/index';
import type { OpenPopoverEvents, PopoverProps, PopoverState } from './Popover.types';
import { popoverSurfaceBorderRadius } from './constants';
Expand Down Expand Up @@ -111,20 +111,28 @@ export const usePopover_unstable = (props: PopoverProps): PopoverState => {
});

const { findFirstFocusable } = useFocusFinders();
const activateModal = useActivateModal();

React.useEffect(() => {
if (props.unstable_disableAutoFocus) {
return;
}

if (open && positioningRefs.contentRef.current) {
const containerTabIndex = positioningRefs.contentRef.current.getAttribute('tabIndex') ?? undefined;
const firstFocusable = isNaN(containerTabIndex)
? findFirstFocusable(positioningRefs.contentRef.current)
: positioningRefs.contentRef.current;
const contentElement = positioningRefs.contentRef.current;

if (open && contentElement) {
const shouldFocusContainer = !isNaN(contentElement.getAttribute('tabIndex') ?? undefined);
const firstFocusable = shouldFocusContainer ? contentElement : findFirstFocusable(contentElement);

firstFocusable?.focus();

if (shouldFocusContainer) {
// Modal activation happens automatically when something inside the modal is focused programmatically.
// When the container is focused, we need to activate the modal manually.
activateModal(contentElement);
}
}
}, [findFirstFocusable, open, positioningRefs.contentRef, props.unstable_disableAutoFocus]);
}, [findFirstFocusable, activateModal, open, positioningRefs.contentRef, props.unstable_disableAutoFocus]);

return {
...initialState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,9 @@ interface UncontrolledProps {
completely?: boolean;
}

// @public
export function useActivateModal(): (elementFromModal: HTMLElement | undefined) => void;

// @public
export const useArrowNavigationGroup: (options?: UseArrowNavigationGroupOptions) => Types.TabsterDOMAttribute;

Expand Down
2 changes: 1 addition & 1 deletion packages/react-components/react-tabster/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@griffel/react": "^1.5.22",
"@swc/helpers": "^0.5.1",
"keyborg": "^2.6.0",
"tabster": "^8.2.0"
"tabster": "^8.5.0"
},
"peerDependencies": {
"@types/react": ">=16.14.0 <19.0.0",
Expand Down
1 change: 1 addition & 0 deletions packages/react-components/react-tabster/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export { useUncontrolledFocus } from './useUncontrolledFocus';
export { useIsNavigatingWithKeyboard } from './useIsNavigatingWithKeyboard';
export { useSetKeyboardNavigation } from './useSetKeyboardNavigation';
export { useFocusedElementChange } from './useFocusedElementChange';
export { useActivateModal } from './useActivateModal';
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as React from 'react';
import { getModalizer } from 'tabster';
import { useTimeout } from '@fluentui/react-utilities';
import { useTabster } from './useTabster';

/**
* Returns a function that activates a modal by element from the modal or modal container.
*/
export function useActivateModal(): (elementFromModal: HTMLElement | undefined) => void {
const tabster = useTabster();
const modalizerAPI = tabster ? getModalizer(tabster) : undefined;
const [setActivateModalTimeout] = useTimeout();

const activateModal = React.useCallback(
(elementFromModal: HTMLElement | undefined) => {
// We call the actual activation function on the next tick, because with the typical use case,
// the hook will be called on the same tick when other Tabster attributes are being applied,
// and on the current tick the element has just received the attributes, but Tabster has not
// instantiated the Modalizer yet.
setActivateModalTimeout(() => {
modalizerAPI?.activate(elementFromModal);
}, 0);
},
[modalizerAPI, setActivateModalTimeout],
);

return activateModal;
}
1 change: 1 addition & 0 deletions packages/react-components/react-tabster/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export {
useIsNavigatingWithKeyboard,
useSetKeyboardNavigation,
useFocusedElementChange,
useActivateModal,
} from './hooks/index';
export type {
UseArrowNavigationGroupOptions,
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -22262,10 +22262,10 @@ table@^6.0.7:
string-width "^4.2.3"
strip-ansi "^6.0.1"

tabster@^8.2.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/tabster/-/tabster-8.2.0.tgz#474b32af394495b0835d4eceeab6594f276486d0"
integrity sha512-Gvplk/Yl/12aVFA6FPOqGcq31Qv8hbPfYO0N+6IxrRgRT6eSLsipT6gkZBYjyOwGsp6BD5XlZAuJgupfG/GHoA==
tabster@^8.5.0:
version "8.5.0"
resolved "https://registry.yarnpkg.com/tabster/-/tabster-8.5.0.tgz#ec7a7d2f5965e60d60e68215893e1965abe81156"
integrity sha512-ePkJm9nycgh4MeW2yXY6QBa4btvwfb4h6+i1uYRAzRxQVf/AJMpN4mHooZKQceM4yQkCjfNibfGtC6DnPmo9vQ==
dependencies:
keyborg "2.6.0"
tslib "^2.3.1"
Expand Down

0 comments on commit 99ddb18

Please sign in to comment.