diff --git a/services/web/frontend/js/features/history/components/change-list/change-list.tsx b/services/web/frontend/js/features/history/components/change-list/change-list.tsx
index d2906faf91..93613ce4e2 100644
--- a/services/web/frontend/js/features/history/components/change-list/change-list.tsx
+++ b/services/web/frontend/js/features/history/components/change-list/change-list.tsx
@@ -14,7 +14,10 @@ function ChangeList() {
)}
{!error && (
-
+
)}
diff --git a/services/web/frontend/js/features/history/components/change-list/dropdown/actions-dropdown.tsx b/services/web/frontend/js/features/history/components/change-list/dropdown/actions-dropdown.tsx
index 61fe196f40..48aee26017 100644
--- a/services/web/frontend/js/features/history/components/change-list/dropdown/actions-dropdown.tsx
+++ b/services/web/frontend/js/features/history/components/change-list/dropdown/actions-dropdown.tsx
@@ -1,42 +1,69 @@
-import { useState } from 'react'
+import { useState, useRef, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { Dropdown } from 'react-bootstrap'
import DropdownToggleWithTooltip from '../../../../../shared/components/dropdown/dropdown-toggle-with-tooltip'
import Icon from '../../../../../shared/components/icon'
+import DropdownMenuWithRef from '../../../../../shared/components/dropdown/dropdown-menu-with-ref'
type DropdownMenuProps = {
id: string
children: React.ReactNode
+ parentSelector?: string
}
-function ActionsDropdown({ id, children }: DropdownMenuProps) {
+function ActionsDropdown({ id, children, parentSelector }: DropdownMenuProps) {
const { t } = useTranslation()
const [isOpened, setIsOpened] = useState(false)
+ const menuRef = useRef
()
+
+ // handle the placement of the dropdown above or below the toggle button
+ useEffect(() => {
+ if (menuRef.current && parentSelector) {
+ const parent = menuRef.current.closest(parentSelector)
+
+ if (!parent) {
+ return
+ }
+
+ const parentBottom = parent.getBoundingClientRect().bottom
+ const { top, height } = menuRef.current.getBoundingClientRect()
+
+ if (top + height > parentBottom) {
+ menuRef.current.style.bottom = '100%'
+ menuRef.current.style.top = 'auto'
+ } else {
+ menuRef.current.style.bottom = 'auto'
+ menuRef.current.style.top = '100%'
+ }
+ }
+ })
return (
- <>
- setIsOpened(open)}
+ setIsOpened(open)}
+ >
+
-
-
-
-
- {children}
-
-
- >
+
+
+
+ {children}
+
+
)
}
diff --git a/services/web/frontend/js/features/history/components/change-list/dropdown/history-version-dropdown.tsx b/services/web/frontend/js/features/history/components/change-list/dropdown/history-version-dropdown.tsx
index f9f9f604f9..2c4849201d 100644
--- a/services/web/frontend/js/features/history/components/change-list/dropdown/history-version-dropdown.tsx
+++ b/services/web/frontend/js/features/history/components/change-list/dropdown/history-version-dropdown.tsx
@@ -22,7 +22,10 @@ function HistoryVersionDropdown({
updateMetaEndTimestamp,
}: HistoryVersionDropdownProps) {
return (
-
+
{!isComparing && !isSelected && (
diff --git a/services/web/frontend/js/features/history/components/change-list/dropdown/label-dropdown.tsx b/services/web/frontend/js/features/history/components/change-list/dropdown/label-dropdown.tsx
index 8775c2a67b..573db42d69 100644
--- a/services/web/frontend/js/features/history/components/change-list/dropdown/label-dropdown.tsx
+++ b/services/web/frontend/js/features/history/components/change-list/dropdown/label-dropdown.tsx
@@ -20,7 +20,10 @@ function LabelDropdown({
updateMetaEndTimestamp,
}: LabelDropdownProps) {
return (
-
+
{!isComparing && !isSelected && (
,
+ {
+ children: React.ReactNode
+ bsRole: 'menu'
+ menuRef: React.MutableRefObject
+ className?: string
+ // The props below are passed by react-bootstrap
+ labelledBy?: string | undefined
+ rootCloseEvent?: 'click' | 'mousedown' | undefined
+ }
+>
+
+const DropdownMenuWithRef = forwardRef<
+ HTMLUListElement,
+ DropdownMenuWithRefProps
+>(function (props, ref) {
+ const {
+ children,
+ bsRole,
+ bsClass,
+ className,
+ open,
+ pullRight,
+ labelledBy,
+ menuRef,
+ onClose,
+ rootCloseEvent,
+ ...rest
+ } = props
+
+ // expose the menu reference to both the `menuRef` and `ref callback` from react-bootstrap
+ const handleRefs = (node: HTMLUListElement) => {
+ if (typeof ref === 'function') {
+ ref(node)
+ }
+ menuRef.current = node
+ }
+
+ // Implementation as suggested in
+ // https://react-bootstrap-v3.netlify.app/components/dropdowns/#btn-dropdowns-props-dropdown
+ return (
+
+
+
+ )
+})
+DropdownMenuWithRef.displayName = 'DropdownMenuWithRef'
+
+export default DropdownMenuWithRef
diff --git a/services/web/frontend/js/shared/components/dropdown/dropdown-toggle-with-tooltip.tsx b/services/web/frontend/js/shared/components/dropdown/dropdown-toggle-with-tooltip.tsx
index 5295b9790d..44756b6f16 100644
--- a/services/web/frontend/js/shared/components/dropdown/dropdown-toggle-with-tooltip.tsx
+++ b/services/web/frontend/js/shared/components/dropdown/dropdown-toggle-with-tooltip.tsx
@@ -5,7 +5,7 @@ import { DropdownProps } from 'react-bootstrap'
import { MergeAndOverride } from '../../../../../types/utils'
type CustomToggleProps = MergeAndOverride<
- Pick,
+ Pick,
{
children: React.ReactNode
bsRole: 'toggle'
@@ -23,6 +23,7 @@ const DropdownToggleWithTooltip = forwardRef<
children,
bsClass,
className,
+ open,
bsRole: _bsRole,
...rest
} = props
@@ -33,6 +34,8 @@ const DropdownToggleWithTooltip = forwardRef<
type="button"
ref={ref}
className={classnames(bsClass, 'btn', className)}
+ aria-expanded={open}
+ aria-haspopup="true"
{...rest}
>
{children}