Semantic-UI-React icon indicating copy to clipboard operation
Semantic-UI-React copied to clipboard

Dropdown menus do not pop over sidebars but instead result in scrollbars in the sidebar

Open ryanewtaylor opened this issue 4 years ago • 6 comments

Bug Report

Dropdown menus do not pop over sidebars but instead result in scrollbars in the sidebar.

dropdown-in-sidebar

Steps

  1. Create a Sidebar
  2. Add a Dropdown menu with content wider than the Sidebar
  3. Click on the Dropdown

Expected Result

The menu options should be displayed over the Sidebar.

Actual Result

The menu options fill the Sidebar which now shows horizontal and/or vertical scrollbars.

Version

2.0.3

Testcase

https://codesandbox.io/s/prod-cookies-ilvo5

ryanewtaylor avatar Feb 16 '21 20:02 ryanewtaylor

Have you had any progress on this topic? I see using Portal as a potential solution to this problem. Overlay could capture scroll events and close the Dropdown.

https://codesandbox.io/s/react-semantic-ui-dropdown-issue-irg52

radulle avatar May 19 '21 08:05 radulle

@radulle no

brianespinosa avatar May 20 '21 15:05 brianespinosa

the solution: this one support portal npm install --save react-dropdown-select

jonlepage avatar Jan 26 '23 22:01 jonlepage

here solution, enjoy: wrap your component with

<DropdownPortal >
	<Dropdown 
	....

function DropdownPortal( props:{children:React.ReactElement<DropdownProps>}) {
	const { children } = props;
	const [ state, setState ] = useState({ open:false });
	const [ node, setNode ] = useState<HTMLElement | null>( null );
	const [ root, setRoot ] = useState<HTMLElement | null>( null );
	const dropdownref = useRef<React.Component<DropdownProps, HTMLElement>>( null );

	const clone = useMemo( () => {
		const { onOpen, onClose } = children.props;
		return cloneElement( children, {
			ref: dropdownref,
			onOpen: ( ...args )=>{
				setState({ open:true });
				onOpen?.call( children, ...args );
			},
			onClose: ( ...args )=>{
				setState({ open:false });
				onClose?.call( children, ...args );
			},
		});
	}, [ children ]);
	useEffect( () => {
		const target = dropdownref.current?.ref.current;
		if ( target && target.lastChild && target.lastChild instanceof HTMLElement ) {
			setNode( target.lastChild );
			setRoot( target );

		}
	}, [ ]);

	useEffect( () => {
		if ( node && root ) {
			if ( state.open ) {
				const bounds = node.getBoundingClientRect();
				document.body.appendChild( node );
				node.style.position = 'absolute';
				node.style.background = 'red';
				node.style.top = bounds.top + 'px';
				node.style.left = bounds.left + 'px';
			} else {
				root.append( node );
				node.style.position = '';
				node.style.background = '';
				node.style.top = '';
				node.style.left = '';

			}
		}

	}, [state]);

	return (
		<>
			{clone}
		</>
	);

}

not work with simple flag

jonlepage avatar Jan 26 '23 23:01 jonlepage

Any chance this becomes a regular behavior? I mean, any popout, modal or dropdown should render on a portal, right? It just feels like the best modern approach :)

felipenmoura avatar Jan 10 '24 01:01 felipenmoura

Any chance this becomes a regular behavior? I mean, any popout, modal or dropdown should render on a portal, right? It just feels like the best modern approach :)

I'm currently doing a menuPortalTarget props on the dropdown, just posted yesterday, it might be close to finished. I'm trying to gather informations before making the pull request.

Dropdown menuPortalTarget props

Reavxn avatar Jan 12 '24 10:01 Reavxn