Skip to content

Commit

Permalink
fix: Action dropdown not properly overflowing (#5000)
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagoapolo authored Jan 15, 2025
1 parent 4a90cf6 commit 5fc9fef
Showing 1 changed file with 74 additions and 44 deletions.
118 changes: 74 additions & 44 deletions frontend/web/components/UserAction.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { FC, useCallback, useLayoutEffect, useRef, useState } from 'react'
import classNames from 'classnames'
import { createPortal } from 'react-dom'

import useOutsideClick from 'common/useOutsideClick'
import Utils from 'common/utils/utils'
import Constants from 'common/constants'
import Permission from 'common/providers/Permission'
import Button from './base/forms/Button'
import Icon from './Icon'
import ActionButton from './ActionButton'
Expand All @@ -18,6 +15,15 @@ interface FeatureActionProps {

type ActionType = 'edit' | 'remove'

type ActionDropdownProps = {
isOpen: boolean
canEdit?: boolean
canRemove?: boolean
btnRef: React.RefObject<HTMLDivElement>
onAction: (action: ActionType) => void
onOutsideClick: () => void
}

function calculateListPosition(
btnEl: HTMLElement,
listEl: HTMLElement,
Expand All @@ -31,6 +37,62 @@ function calculateListPosition(
}
}

const ActionDropdown = ({
btnRef,
canEdit,
canRemove,
isOpen,
onAction,
onOutsideClick,
}: ActionDropdownProps) => {
const dropDownRef = useRef<HTMLDivElement>(null)

useOutsideClick(dropDownRef, onOutsideClick)

useLayoutEffect(() => {
if (!isOpen || !dropDownRef.current || !btnRef.current) return
const listPosition = calculateListPosition(
btnRef.current,
dropDownRef.current,
)
dropDownRef.current.style.top = `${listPosition.top}px`
dropDownRef.current.style.left = `${listPosition.left}px`
}, [btnRef, isOpen, dropDownRef])

if (!isOpen) return null

return createPortal(
<div ref={dropDownRef} className='feature-action__list'>
{!!canEdit && (
<div
className='feature-action__item'
onClick={(e) => {
e.stopPropagation()
onAction('edit')
}}
>
<Icon name='edit' width={18} fill='#9DA4AE' />
<span>Manage user</span>
</div>
)}

{!!canRemove && (
<div
className='feature-action__item'
onClick={(e) => {
e.stopPropagation()
onAction('remove')
}}
>
<Icon name='trash-2' width={18} fill='#9DA4AE' />
<span>Remove</span>
</div>
)}
</div>,
document.body,
)
}

export const FeatureAction: FC<FeatureActionProps> = ({
canEdit,
canRemove,
Expand All @@ -40,7 +102,6 @@ export const FeatureAction: FC<FeatureActionProps> = ({
const [isOpen, setIsOpen] = useState<boolean>(false)

const btnRef = useRef<HTMLDivElement>(null)
const listRef = useRef<HTMLDivElement>(null)

const close = useCallback(() => setIsOpen(false), [])

Expand All @@ -61,15 +122,6 @@ export const FeatureAction: FC<FeatureActionProps> = ({
[close, onRemove, onEdit],
)

useOutsideClick(listRef, handleOutsideClick)

useLayoutEffect(() => {
if (!isOpen || !listRef.current || !btnRef.current) return
const listPosition = calculateListPosition(btnRef.current, listRef.current)
listRef.current.style.top = `${listPosition.top}px`
listRef.current.style.left = `${listPosition.left}px`
}, [isOpen])

if (!canEdit && !!canRemove) {
return (
<Button onClick={onRemove} size='small' className='btn-with-icon'>
Expand Down Expand Up @@ -99,36 +151,14 @@ export const FeatureAction: FC<FeatureActionProps> = ({
<div ref={btnRef}>
<ActionButton size='small' onClick={() => setIsOpen(true)} />
</div>

{isOpen && (
<div ref={listRef} className='feature-action__list'>
{!!canEdit && (
<div
className='feature-action__item'
onClick={(e) => {
e.stopPropagation()
handleActionClick('edit')
}}
>
<Icon name='edit' width={18} fill='#9DA4AE' />
<span>Manage user</span>
</div>
)}

{!!canRemove && (
<div
className='feature-action__item'
onClick={(e) => {
e.stopPropagation()
handleActionClick('remove')
}}
>
<Icon name='trash-2' width={18} fill='#9DA4AE' />
<span>Remove</span>
</div>
)}
</div>
)}
<ActionDropdown
isOpen={isOpen}
canEdit={canEdit}
canRemove={canRemove}
btnRef={btnRef}
onAction={handleActionClick}
onOutsideClick={handleOutsideClick}
/>
</div>
)
}
Expand Down

0 comments on commit 5fc9fef

Please sign in to comment.