[Glitch] Fix dropdown menu positions when scrolling
Port fd33bcb3b2
to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
@ -2,7 +2,7 @@
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Overlay from 'react-overlays/lib/Overlay';
|
||||
import Overlay from 'react-overlays/Overlay';
|
||||
|
||||
// Components.
|
||||
import IconButton from 'flavours/glitch/components/icon_button';
|
||||
@ -45,7 +45,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
|
||||
};
|
||||
|
||||
// Toggles opening and closing the dropdown.
|
||||
handleToggle = ({ target, type }) => {
|
||||
handleToggle = ({ type }) => {
|
||||
const { onModalOpen } = this.props;
|
||||
const { open } = this.state;
|
||||
|
||||
@ -59,11 +59,9 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const { top } = target.getBoundingClientRect();
|
||||
if (this.state.open && this.activeElement) {
|
||||
this.activeElement.focus({ preventScroll: true });
|
||||
}
|
||||
this.setState({ placement: top * 2 < innerHeight ? 'bottom' : 'top' });
|
||||
this.setState({ open: !this.state.open, openedViaKeyboard: type !== 'click' });
|
||||
}
|
||||
}
|
||||
@ -158,6 +156,18 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
|
||||
};
|
||||
}
|
||||
|
||||
setTargetRef = c => {
|
||||
this.target = c;
|
||||
}
|
||||
|
||||
findTarget = () => {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
handleOverlayEnter = (state) => {
|
||||
this.setState({ placement: state.placement });
|
||||
}
|
||||
|
||||
// Rendering.
|
||||
render () {
|
||||
const {
|
||||
@ -179,6 +189,7 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
|
||||
<div
|
||||
className={classNames('privacy-dropdown', placement, { active: open })}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
ref={this.setTargetRef}
|
||||
>
|
||||
<div className={classNames('privacy-dropdown__value', { active })}>
|
||||
<IconButton
|
||||
@ -204,18 +215,26 @@ export default class ComposerOptionsDropdown extends React.PureComponent {
|
||||
containerPadding={20}
|
||||
placement={placement}
|
||||
show={open}
|
||||
target={this}
|
||||
flip
|
||||
target={this.findTarget}
|
||||
container={container}
|
||||
popperConfig={{ strategy: 'fixed', onFirstUpdate: this.handleOverlayEnter }}
|
||||
>
|
||||
<DropdownMenu
|
||||
items={items}
|
||||
renderItemContents={renderItemContents}
|
||||
onChange={onChange}
|
||||
onClose={this.handleClose}
|
||||
value={value}
|
||||
openedViaKeyboard={this.state.openedViaKeyboard}
|
||||
closeOnChange={closeOnChange}
|
||||
/>
|
||||
{({ props, placement }) => (
|
||||
<div {...props} style={{ ...props.style, width: 350, maxWidth: '100vw' }}>
|
||||
<div className={`dropdown-animation privacy-dropdown__dropdown ${placement}`}>
|
||||
<DropdownMenu
|
||||
items={items}
|
||||
renderItemContents={renderItemContents}
|
||||
onChange={onChange}
|
||||
onClose={this.handleClose}
|
||||
value={value}
|
||||
openedViaKeyboard={this.state.openedViaKeyboard}
|
||||
closeOnChange={closeOnChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Overlay>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Package imports.
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import spring from 'react-motion/lib/spring';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import classNames from 'classnames';
|
||||
|
||||
@ -10,15 +9,8 @@ import Icon from 'flavours/glitch/components/icon';
|
||||
|
||||
// Utils.
|
||||
import { withPassive } from 'flavours/glitch/utils/dom_helpers';
|
||||
import Motion from '../../ui/util/optional_motion';
|
||||
import { assignHandlers } from 'flavours/glitch/utils/react_helpers';
|
||||
|
||||
// The spring to use with our motion.
|
||||
const springMotion = spring(1, {
|
||||
damping: 35,
|
||||
stiffness: 400,
|
||||
});
|
||||
|
||||
// The component.
|
||||
export default class ComposerOptionsDropdownContent extends React.PureComponent {
|
||||
|
||||
@ -44,7 +36,6 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
|
||||
};
|
||||
|
||||
state = {
|
||||
mounted: false,
|
||||
value: this.props.openedViaKeyboard ? this.props.items[0].name : undefined,
|
||||
};
|
||||
|
||||
@ -56,7 +47,7 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
|
||||
}
|
||||
|
||||
// Stores our node in `this.node`.
|
||||
handleRef = (node) => {
|
||||
setRef = (node) => {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
@ -69,7 +60,6 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
|
||||
} else {
|
||||
this.node.firstChild.focus({ preventScroll: true });
|
||||
}
|
||||
this.setState({ mounted: true });
|
||||
}
|
||||
|
||||
// On unmounting, we remove our listeners.
|
||||
@ -191,7 +181,6 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
|
||||
|
||||
// Rendering.
|
||||
render () {
|
||||
const { mounted } = this.state;
|
||||
const {
|
||||
items,
|
||||
onChange,
|
||||
@ -201,36 +190,9 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
|
||||
|
||||
// The result.
|
||||
return (
|
||||
<Motion
|
||||
defaultStyle={{
|
||||
opacity: 0,
|
||||
scaleX: 0.85,
|
||||
scaleY: 0.75,
|
||||
}}
|
||||
style={{
|
||||
opacity: springMotion,
|
||||
scaleX: springMotion,
|
||||
scaleY: springMotion,
|
||||
}}
|
||||
>
|
||||
{({ opacity, scaleX, scaleY }) => (
|
||||
// It should not be transformed when mounting because the resulting
|
||||
// size will be used to determine the coordinate of the menu by
|
||||
// react-overlays
|
||||
<div
|
||||
className='privacy-dropdown__dropdown'
|
||||
ref={this.handleRef}
|
||||
role='listbox'
|
||||
style={{
|
||||
...style,
|
||||
opacity: opacity,
|
||||
transform: mounted ? `scale(${scaleX}, ${scaleY})` : null,
|
||||
}}
|
||||
>
|
||||
{!!items && items.map((item, i) => this.renderItem(item, i))}
|
||||
</div>
|
||||
)}
|
||||
</Motion>
|
||||
<div style={{ ...style }} role='listbox' ref={this.setRef}>
|
||||
{!!items && items.map((item, i) => this.renderItem(item, i))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components';
|
||||
import Overlay from 'react-overlays/lib/Overlay';
|
||||
import Overlay from 'react-overlays/Overlay';
|
||||
import classNames from 'classnames';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||
@ -155,9 +155,6 @@ class EmojiPickerMenu extends React.PureComponent {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onPick: PropTypes.func.isRequired,
|
||||
style: PropTypes.object,
|
||||
placement: PropTypes.string,
|
||||
arrowOffsetLeft: PropTypes.string,
|
||||
arrowOffsetTop: PropTypes.string,
|
||||
intl: PropTypes.object.isRequired,
|
||||
skinTone: PropTypes.number.isRequired,
|
||||
onSkinTone: PropTypes.func.isRequired,
|
||||
@ -326,14 +323,13 @@ class EmojiPickerDropdown extends React.PureComponent {
|
||||
state = {
|
||||
active: false,
|
||||
loading: false,
|
||||
placement: null,
|
||||
};
|
||||
|
||||
setRef = (c) => {
|
||||
this.dropdown = c;
|
||||
}
|
||||
|
||||
onShowDropdown = ({ target }) => {
|
||||
onShowDropdown = () => {
|
||||
this.setState({ active: true });
|
||||
|
||||
if (!EmojiPicker) {
|
||||
@ -348,9 +344,6 @@ class EmojiPickerDropdown extends React.PureComponent {
|
||||
this.setState({ loading: false, active: false });
|
||||
});
|
||||
}
|
||||
|
||||
const { top } = target.getBoundingClientRect();
|
||||
this.setState({ placement: top * 2 < innerHeight ? 'bottom' : 'top' });
|
||||
}
|
||||
|
||||
onHideDropdown = () => {
|
||||
@ -384,7 +377,7 @@ class EmojiPickerDropdown extends React.PureComponent {
|
||||
render () {
|
||||
const { intl, onPickEmoji, onSkinTone, skinTone, frequentlyUsedEmojis, button } = this.props;
|
||||
const title = intl.formatMessage(messages.emoji);
|
||||
const { active, loading, placement } = this.state;
|
||||
const { active, loading } = this.state;
|
||||
|
||||
return (
|
||||
<div className='emoji-picker-dropdown' onKeyDown={this.handleKeyDown}>
|
||||
@ -396,16 +389,22 @@ class EmojiPickerDropdown extends React.PureComponent {
|
||||
/>}
|
||||
</div>
|
||||
|
||||
<Overlay show={active} placement={placement} target={this.findTarget}>
|
||||
<EmojiPickerMenu
|
||||
custom_emojis={this.props.custom_emojis}
|
||||
loading={loading}
|
||||
onClose={this.onHideDropdown}
|
||||
onPick={onPickEmoji}
|
||||
onSkinTone={onSkinTone}
|
||||
skinTone={skinTone}
|
||||
frequentlyUsedEmojis={frequentlyUsedEmojis}
|
||||
/>
|
||||
<Overlay show={active} placement={'bottom'} target={this.findTarget} popperConfig={{ strategy: 'fixed' }}>
|
||||
{({ props, placement })=> (
|
||||
<div {...props} style={{ ...props.style, width: 299 }}>
|
||||
<div className={`dropdown-animation ${placement}`}>
|
||||
<EmojiPickerMenu
|
||||
custom_emojis={this.props.custom_emojis}
|
||||
loading={loading}
|
||||
onClose={this.onHideDropdown}
|
||||
onPick={onPickEmoji}
|
||||
onSkinTone={onSkinTone}
|
||||
skinTone={skinTone}
|
||||
frequentlyUsedEmojis={frequentlyUsedEmojis}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Overlay>
|
||||
</div>
|
||||
);
|
||||
|
@ -2,9 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { injectIntl, defineMessages } from 'react-intl';
|
||||
import TextIconButton from './text_icon_button';
|
||||
import Overlay from 'react-overlays/lib/Overlay';
|
||||
import Motion from 'flavours/glitch/features/ui/util/optional_motion';
|
||||
import spring from 'react-motion/lib/spring';
|
||||
import Overlay from 'react-overlays/Overlay';
|
||||
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||
import classNames from 'classnames';
|
||||
import { languages as preloadedLanguages } from 'flavours/glitch/initial_state';
|
||||
@ -22,10 +20,8 @@ const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||
class LanguageDropdownMenu extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
style: PropTypes.object,
|
||||
value: PropTypes.string.isRequired,
|
||||
frequentlyUsedLanguages: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
placement: PropTypes.string.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
languages: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)),
|
||||
@ -37,7 +33,6 @@ class LanguageDropdownMenu extends React.PureComponent {
|
||||
};
|
||||
|
||||
state = {
|
||||
mounted: false,
|
||||
searchValue: '',
|
||||
};
|
||||
|
||||
@ -50,7 +45,6 @@ class LanguageDropdownMenu extends React.PureComponent {
|
||||
componentDidMount () {
|
||||
document.addEventListener('click', this.handleDocumentClick, false);
|
||||
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
this.setState({ mounted: true });
|
||||
|
||||
// Because of https://github.com/react-bootstrap/react-bootstrap/issues/2614 we need
|
||||
// to wait for a frame before focusing
|
||||
@ -222,29 +216,22 @@ class LanguageDropdownMenu extends React.PureComponent {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { style, placement, intl } = this.props;
|
||||
const { mounted, searchValue } = this.state;
|
||||
const { intl } = this.props;
|
||||
const { searchValue } = this.state;
|
||||
const isSearching = searchValue !== '';
|
||||
const results = this.search();
|
||||
|
||||
return (
|
||||
<Motion defaultStyle={{ opacity: 0, scaleX: 0.85, scaleY: 0.75 }} style={{ opacity: spring(1, { damping: 35, stiffness: 400 }), scaleX: spring(1, { damping: 35, stiffness: 400 }), scaleY: spring(1, { damping: 35, stiffness: 400 }) }}>
|
||||
{({ opacity, scaleX, scaleY }) => (
|
||||
// It should not be transformed when mounting because the resulting
|
||||
// size will be used to determine the coordinate of the menu by
|
||||
// react-overlays
|
||||
<div className={`language-dropdown__dropdown ${placement}`} style={{ ...style, opacity: opacity, transform: mounted ? `scale(${scaleX}, ${scaleY})` : null }} ref={this.setRef}>
|
||||
<div className='emoji-mart-search'>
|
||||
<input type='search' value={searchValue} onChange={this.handleSearchChange} onKeyDown={this.handleSearchKeyDown} placeholder={intl.formatMessage(messages.search)} />
|
||||
<button className='emoji-mart-search-icon' disabled={!isSearching} aria-label={intl.formatMessage(messages.clear)} onClick={this.handleClear}>{!isSearching ? loupeIcon : deleteIcon}</button>
|
||||
</div>
|
||||
<div ref={this.setRef}>
|
||||
<div className='emoji-mart-search'>
|
||||
<input type='search' value={searchValue} onChange={this.handleSearchChange} onKeyDown={this.handleSearchKeyDown} placeholder={intl.formatMessage(messages.search)} />
|
||||
<button type='button' className='emoji-mart-search-icon' disabled={!isSearching} aria-label={intl.formatMessage(messages.clear)} onClick={this.handleClear}>{!isSearching ? loupeIcon : deleteIcon}</button>
|
||||
</div>
|
||||
|
||||
<div className='language-dropdown__dropdown__results emoji-mart-scroll' role='listbox' ref={this.setListRef}>
|
||||
{results.map(this.renderItem)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Motion>
|
||||
<div className='language-dropdown__dropdown__results emoji-mart-scroll' role='listbox' ref={this.setListRef}>
|
||||
{results.map(this.renderItem)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -266,14 +253,11 @@ class LanguageDropdown extends React.PureComponent {
|
||||
placement: 'bottom',
|
||||
};
|
||||
|
||||
handleToggle = ({ target }) => {
|
||||
const { top } = target.getBoundingClientRect();
|
||||
|
||||
handleToggle = () => {
|
||||
if (this.state.open && this.activeElement) {
|
||||
this.activeElement.focus({ preventScroll: true });
|
||||
}
|
||||
|
||||
this.setState({ placement: top * 2 < innerHeight ? 'bottom' : 'top' });
|
||||
this.setState({ open: !this.state.open });
|
||||
}
|
||||
|
||||
@ -293,13 +277,25 @@ class LanguageDropdown extends React.PureComponent {
|
||||
onChange(value);
|
||||
}
|
||||
|
||||
setTargetRef = c => {
|
||||
this.target = c;
|
||||
}
|
||||
|
||||
findTarget = () => {
|
||||
return this.target;
|
||||
}
|
||||
|
||||
handleOverlayEnter = (state) => {
|
||||
this.setState({ placement: state.placement });
|
||||
}
|
||||
|
||||
render () {
|
||||
const { value, intl, frequentlyUsedLanguages } = this.props;
|
||||
const { open, placement } = this.state;
|
||||
|
||||
return (
|
||||
<div className={classNames('privacy-dropdown', { active: open })}>
|
||||
<div className='privacy-dropdown__value'>
|
||||
<div className={classNames('privacy-dropdown', placement, { active: open })}>
|
||||
<div className='privacy-dropdown__value' ref={this.setTargetRef} >
|
||||
<TextIconButton
|
||||
className='privacy-dropdown__value-icon'
|
||||
label={value && value.toUpperCase()}
|
||||
@ -309,15 +305,20 @@ class LanguageDropdown extends React.PureComponent {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Overlay show={open} placement={placement} target={this}>
|
||||
<LanguageDropdownMenu
|
||||
value={value}
|
||||
frequentlyUsedLanguages={frequentlyUsedLanguages}
|
||||
onClose={this.handleClose}
|
||||
onChange={this.handleChange}
|
||||
placement={placement}
|
||||
intl={intl}
|
||||
/>
|
||||
<Overlay show={open} placement={'bottom'} flip target={this.findTarget} popperConfig={{ strategy: 'fixed', onFirstUpdate: this.handleOverlayEnter }}>
|
||||
{({ props, placement }) => (
|
||||
<div {...props} style={{ ...props.style, width: 280 }}>
|
||||
<div className={`dropdown-animation language-dropdown__dropdown ${placement}`} >
|
||||
<LanguageDropdownMenu
|
||||
value={value}
|
||||
frequentlyUsedLanguages={frequentlyUsedLanguages}
|
||||
onClose={this.handleClose}
|
||||
onChange={this.handleChange}
|
||||
intl={intl}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Overlay>
|
||||
</div>
|
||||
);
|
||||
|
@ -3,13 +3,12 @@ import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import spring from 'react-motion/lib/spring';
|
||||
import {
|
||||
injectIntl,
|
||||
FormattedMessage,
|
||||
defineMessages,
|
||||
} from 'react-intl';
|
||||
import Overlay from 'react-overlays/lib/Overlay';
|
||||
import Overlay from 'react-overlays/Overlay';
|
||||
|
||||
// Components.
|
||||
import Icon from 'flavours/glitch/components/icon';
|
||||
@ -17,7 +16,6 @@ import Icon from 'flavours/glitch/components/icon';
|
||||
// Utils.
|
||||
import { focusRoot } from 'flavours/glitch/utils/dom_helpers';
|
||||
import { searchEnabled } from 'flavours/glitch/initial_state';
|
||||
import Motion from '../../ui/util/optional_motion';
|
||||
|
||||
const messages = defineMessages({
|
||||
placeholder: { id: 'search.placeholder', defaultMessage: 'Search' },
|
||||
@ -26,31 +24,20 @@ const messages = defineMessages({
|
||||
|
||||
class SearchPopout extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
style: PropTypes.object,
|
||||
};
|
||||
|
||||
render () {
|
||||
const { style } = this.props;
|
||||
const extraInformation = searchEnabled ? <FormattedMessage id='search_popout.tips.full_text' defaultMessage='Simple text returns statuses you have written, favourited, boosted, or have been mentioned in, as well as matching usernames, display names, and hashtags.' /> : <FormattedMessage id='search_popout.tips.text' defaultMessage='Simple text returns matching display names, usernames and hashtags' />;
|
||||
return (
|
||||
<div style={{ ...style, position: 'absolute', width: 285, zIndex: 2 }}>
|
||||
<Motion defaultStyle={{ opacity: 0, scaleX: 0.85, scaleY: 0.75 }} style={{ opacity: spring(1, { damping: 35, stiffness: 400 }), scaleX: spring(1, { damping: 35, stiffness: 400 }), scaleY: spring(1, { damping: 35, stiffness: 400 }) }}>
|
||||
{({ opacity, scaleX, scaleY }) => (
|
||||
<div className='search-popout' style={{ opacity: opacity, transform: `scale(${scaleX}, ${scaleY})` }}>
|
||||
<h4><FormattedMessage id='search_popout.search_format' defaultMessage='Advanced search format' /></h4>
|
||||
<div className='search-popout'>
|
||||
<h4><FormattedMessage id='search_popout.search_format' defaultMessage='Advanced search format' /></h4>
|
||||
|
||||
<ul>
|
||||
<li><em>#example</em> <FormattedMessage id='search_popout.tips.hashtag' defaultMessage='hashtag' /></li>
|
||||
<li><em>@username@domain</em> <FormattedMessage id='search_popout.tips.user' defaultMessage='user' /></li>
|
||||
<li><em>URL</em> <FormattedMessage id='search_popout.tips.user' defaultMessage='user' /></li>
|
||||
<li><em>URL</em> <FormattedMessage id='search_popout.tips.status' defaultMessage='status' /></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><em>#example</em> <FormattedMessage id='search_popout.tips.hashtag' defaultMessage='hashtag' /></li>
|
||||
<li><em>@username@domain</em> <FormattedMessage id='search_popout.tips.user' defaultMessage='user' /></li>
|
||||
<li><em>URL</em> <FormattedMessage id='search_popout.tips.user' defaultMessage='user' /></li>
|
||||
<li><em>URL</em> <FormattedMessage id='search_popout.tips.status' defaultMessage='status' /></li>
|
||||
</ul>
|
||||
|
||||
{extraInformation}
|
||||
</div>
|
||||
)}
|
||||
</Motion>
|
||||
{extraInformation}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -136,6 +123,10 @@ class Search extends React.PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
findTarget = () => {
|
||||
return this.searchForm;
|
||||
}
|
||||
|
||||
render () {
|
||||
const { intl, value, submitted } = this.props;
|
||||
const { expanded } = this.state;
|
||||
@ -161,8 +152,14 @@ class Search extends React.PureComponent {
|
||||
<Icon id='search' className={hasValue ? '' : 'active'} />
|
||||
<Icon id='times-circle' className={hasValue ? 'active' : ''} />
|
||||
</div>
|
||||
<Overlay show={expanded && !hasValue} placement='bottom' target={this} container={this}>
|
||||
<SearchPopout />
|
||||
<Overlay show={expanded && !hasValue} placement='bottom' target={this.findTarget} popperConfig={{ strategy: 'fixed' }}>
|
||||
{({ props, placement }) => (
|
||||
<div {...props} style={{ ...props.style, width: 285, zIndex: 2 }}>
|
||||
<div className={`dropdown-animation ${placement}`}>
|
||||
<SearchPopout />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Overlay>
|
||||
</div>
|
||||
);
|
||||
|
Reference in New Issue
Block a user