diff --git a/packages/react-core/src/components/Dropdown/Dropdown.tsx b/packages/react-core/src/components/Dropdown/Dropdown.tsx index b94c301f017..2819cc8eea1 100644 --- a/packages/react-core/src/components/Dropdown/Dropdown.tsx +++ b/packages/react-core/src/components/Dropdown/Dropdown.tsx @@ -8,7 +8,7 @@ export interface DropdownPopperProps { /** Vertical direction of the popper. If enableFlip is set to true, this will set the initial direction before the popper flips. */ direction?: 'up' | 'down'; /** Horizontal position of the popper */ - position?: 'right' | 'left' | 'center'; + position?: 'right' | 'left' | 'center' | 'start' | 'end'; /** Custom width of the popper. If the value is "trigger", it will set the width to the dropdown toggle's width */ width?: string | 'trigger'; /** Minimum width of the popper. If the value is "trigger", it will set the min width to the dropdown toggle's width */ diff --git a/packages/react-core/src/components/Menu/MenuContainer.tsx b/packages/react-core/src/components/Menu/MenuContainer.tsx index 16f002561f3..f1bceac4eff 100644 --- a/packages/react-core/src/components/Menu/MenuContainer.tsx +++ b/packages/react-core/src/components/Menu/MenuContainer.tsx @@ -5,7 +5,7 @@ export interface MenuPopperProps { /** Vertical direction of the popper. If enableFlip is set to true, this will set the initial direction before the popper flips. */ direction?: 'up' | 'down'; /** Horizontal position of the popper */ - position?: 'right' | 'left' | 'center'; + position?: 'right' | 'left' | 'center' | 'start' | 'end'; /** Custom width of the popper. If the value is "trigger", it will set the width to the dropdown toggle's width */ width?: string | 'trigger'; /** Minimum width of the popper. If the value is "trigger", it will set the min width to the dropdown toggle's width */ diff --git a/packages/react-core/src/components/Select/Select.tsx b/packages/react-core/src/components/Select/Select.tsx index d3f71d5862f..2b8a0691208 100644 --- a/packages/react-core/src/components/Select/Select.tsx +++ b/packages/react-core/src/components/Select/Select.tsx @@ -8,7 +8,7 @@ export interface SelectPopperProps { /** Vertical direction of the popper. If enableFlip is set to true, this will set the initial direction before the popper flips. */ direction?: 'up' | 'down'; /** Horizontal position of the popper */ - position?: 'right' | 'left' | 'center'; + position?: 'right' | 'left' | 'center' | 'start' | 'end'; /** Custom width of the popper. If the value is "trigger", it will set the width to the select toggle's width */ width?: string | 'trigger'; /** Minimum width of the popper. If the value is "trigger", it will set the min width to the select toggle's width */ diff --git a/packages/react-core/src/helpers/Popper/Popper.tsx b/packages/react-core/src/helpers/Popper/Popper.tsx index 403e232dfd6..b7ba8663470 100644 --- a/packages/react-core/src/helpers/Popper/Popper.tsx +++ b/packages/react-core/src/helpers/Popper/Popper.tsx @@ -45,6 +45,21 @@ const getOppositePlacement = (placement: Placement): any => export const getOpacityTransition = (animationDuration: number) => `opacity ${animationDuration}ms cubic-bezier(.54, 1.5, .38, 1.11)`; +export const getLanguageDirection = (targetElement: HTMLElement) => { + const defaultDirection = 'ltr'; + let direction = defaultDirection; + + if (targetElement) { + direction = getComputedStyle(targetElement).getPropertyValue('direction'); + } + + if (['ltr', 'rtl'].includes(direction)) { + return direction as 'ltr' | 'rtl'; + } + + return defaultDirection; +}; + export interface PopperProps { /** * Trigger reference element to which the popper is relatively placed to. @@ -66,7 +81,7 @@ export interface PopperProps { /** popper direction */ direction?: 'up' | 'down'; /** popper position */ - position?: 'right' | 'left' | 'center'; + position?: 'right' | 'left' | 'center' | 'start' | 'end'; /** Instead of direction and position can set the placement of the popper */ placement?: Placement; /** Custom width of the popper. If the value is "trigger", it will set the width to the trigger element's width */ @@ -177,7 +192,7 @@ export const Popper: React.FunctionComponent = ({ trigger, popper, direction = 'down', - position = 'left', + position = 'start', placement, width, minWidth = 'trigger', @@ -226,6 +241,28 @@ export const Popper: React.FunctionComponent = ({ const refOrTrigger = refElement || triggerElement; const showPopper = isVisible || internalIsVisible; + const triggerParent = ((triggerRef as React.RefObject)?.current || triggerElement)?.parentElement; + const languageDirection = getLanguageDirection(triggerParent); + + const internalPosition = React.useMemo<'left' | 'right' | 'center'>(() => { + const fixedPositions = { left: 'left', right: 'right', center: 'center' }; + + const positionMap = { + ltr: { + start: 'left', + end: 'right', + ...fixedPositions + }, + rtl: { + start: 'right', + end: 'left', + ...fixedPositions + } + }; + + return positionMap[languageDirection][position] as 'left' | 'right' | 'center'; + }, [position, languageDirection]); + const onDocumentClickCallback = React.useCallback( (event: MouseEvent) => onDocumentClick(event, refOrTrigger, popperElement), [showPopper, triggerElement, refElement, popperElement, onDocumentClick] @@ -333,15 +370,15 @@ export const Popper: React.FunctionComponent = ({ return placement; } let convertedPlacement = direction === 'up' ? 'top' : 'bottom'; - if (position !== 'center') { - convertedPlacement = `${convertedPlacement}-${position === 'right' ? 'end' : 'start'}`; + if (internalPosition !== 'center') { + convertedPlacement = `${convertedPlacement}-${internalPosition === 'right' ? 'end' : 'start'}`; } return convertedPlacement as Placement; }; - const getPlacementMemo = React.useMemo(getPlacement, [direction, position, placement]); + const getPlacementMemo = React.useMemo(getPlacement, [direction, internalPosition, placement]); const getOppositePlacementMemo = React.useMemo( () => getOppositePlacement(getPlacement()), - [direction, position, placement] + [direction, internalPosition, placement] ); const widthMods: Modifier<'widthMods', {}> = React.useMemo( diff --git a/packages/react-table/src/components/Table/ActionsColumn.tsx b/packages/react-table/src/components/Table/ActionsColumn.tsx index 369951d4a5d..5d8f01f0b94 100644 --- a/packages/react-table/src/components/Table/ActionsColumn.tsx +++ b/packages/react-table/src/components/Table/ActionsColumn.tsx @@ -39,7 +39,7 @@ const ActionsColumnBase: React.FunctionComponent = ({ extraData, actionsToggle, popperProps = { - position: 'right', + position: 'end', direction: 'down' }, innerRef,