mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
used popper to handle positioning
This commit is contained in:
parent
c19fb3282e
commit
6de411f140
4 changed files with 29 additions and 46 deletions
|
@ -1,6 +1,6 @@
|
||||||
.wrap {
|
.wrap {
|
||||||
height: $header_height;
|
height: $header_height;
|
||||||
z-index: 5;
|
z-index: 25;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import * as TAG_ACTIONS from '~/redux/tag/actions';
|
||||||
import { selectTagAutocomplete } from '~/redux/tag/selectors';
|
import { selectTagAutocomplete } from '~/redux/tag/selectors';
|
||||||
import { separateTagOptions } from '~/utils/tag';
|
import { separateTagOptions } from '~/utils/tag';
|
||||||
import { TagAutocompleteRow } from '~/components/tags/TagAutocompleteRow';
|
import { TagAutocompleteRow } from '~/components/tags/TagAutocompleteRow';
|
||||||
|
import { usePopper } from 'react-popper';
|
||||||
|
|
||||||
const mapStateToProps = selectTagAutocomplete;
|
const mapStateToProps = selectTagAutocomplete;
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
|
@ -30,16 +31,28 @@ const TagAutocompleteUnconnected: FC<Props> = ({
|
||||||
tagLoadAutocomplete,
|
tagLoadAutocomplete,
|
||||||
options,
|
options,
|
||||||
}) => {
|
}) => {
|
||||||
const [top, setTop] = useState(false);
|
|
||||||
const [left, setLeft] = useState(false);
|
|
||||||
|
|
||||||
const [selected, setSelected] = useState(-1);
|
const [selected, setSelected] = useState(-1);
|
||||||
const [categories, tags] = useMemo(
|
const [categories, tags] = useMemo(
|
||||||
() =>
|
() =>
|
||||||
separateTagOptions(options.filter(option => option !== search && !exclude.includes(option))),
|
separateTagOptions(
|
||||||
|
options.slice(0, 7).filter(option => option !== search && !exclude.includes(option))
|
||||||
|
),
|
||||||
[options, search, exclude]
|
[options, search, exclude]
|
||||||
);
|
);
|
||||||
const scroll = useRef<HTMLDivElement>(null);
|
const scroll = useRef<HTMLDivElement>(null);
|
||||||
|
const wrapper = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const pop = usePopper(wrapper?.current?.parentElement, wrapper.current, {
|
||||||
|
placement: 'bottom-end',
|
||||||
|
modifiers: [
|
||||||
|
{
|
||||||
|
name: 'offset',
|
||||||
|
options: {
|
||||||
|
offset: [0, 4],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
const onKeyDown = useCallback(
|
const onKeyDown = useCallback(
|
||||||
event => {
|
event => {
|
||||||
|
@ -62,17 +75,6 @@ const TagAutocompleteUnconnected: FC<Props> = ({
|
||||||
[setSelected, selected, categories, tags, onSelect, search]
|
[setSelected, selected, categories, tags, onSelect, search]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onScroll = useCallback(() => {
|
|
||||||
if (!scroll.current) return;
|
|
||||||
const { y, height, x, width } = scroll.current.getBoundingClientRect();
|
|
||||||
|
|
||||||
const newTop = window.innerHeight - y - height <= (top ? 120 : 10);
|
|
||||||
if (top !== newTop) setTop(newTop);
|
|
||||||
|
|
||||||
const newLeft = x <= 0;
|
|
||||||
if (newLeft !== left) setLeft(newLeft);
|
|
||||||
}, [scroll.current, top, left]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
input.addEventListener('keydown', onKeyDown, false);
|
input.addEventListener('keydown', onKeyDown, false);
|
||||||
return () => input.removeEventListener('keydown', onKeyDown);
|
return () => input.removeEventListener('keydown', onKeyDown);
|
||||||
|
@ -99,20 +101,13 @@ const TagAutocompleteUnconnected: FC<Props> = ({
|
||||||
}
|
}
|
||||||
}, [selected, scroll.current]);
|
}, [selected, scroll.current]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
onScroll();
|
|
||||||
|
|
||||||
window.addEventListener('resize', onScroll);
|
|
||||||
window.addEventListener('scroll', onScroll);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('resize', onScroll);
|
|
||||||
window.removeEventListener('scroll', onScroll);
|
|
||||||
};
|
|
||||||
}, [options, search]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(styles.window, { [styles.top]: top, [styles.left]: left })}>
|
<div
|
||||||
|
className={classNames(styles.window)}
|
||||||
|
ref={wrapper}
|
||||||
|
style={pop.styles.popper}
|
||||||
|
{...pop.attributes.popper}
|
||||||
|
>
|
||||||
<div className={styles.scroll} ref={scroll}>
|
<div className={styles.scroll} ref={scroll}>
|
||||||
<TagAutocompleteRow selected={selected === -1} title={search} type="enter" />
|
<TagAutocompleteRow selected={selected === -1} title={search} type="enter" />
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
$row_height: 24px;
|
$row_height: 24px;
|
||||||
|
|
||||||
.window {
|
.window {
|
||||||
box-shadow: transparentize(white, 0.9) 0 0 0 1px, transparentize(black, 0.7) 4px 4px;
|
box-shadow: transparentize(white, 0.9) 0 0 0 1px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -2px;
|
top: -2px;
|
||||||
right: -2px;
|
right: -2px;
|
||||||
|
@ -14,24 +14,12 @@ $row_height: 24px;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
background: darken($content_bg, 2%);
|
background: darken($content_bg, 2%);
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
border-radius: 3px;
|
border-radius: 4px;
|
||||||
padding: $tag_height + 4px 0 0;
|
|
||||||
animation: appear 0.25s forwards;
|
animation: appear 0.25s forwards;
|
||||||
|
|
||||||
&.top {
|
|
||||||
bottom: -2px;
|
|
||||||
top: auto;
|
|
||||||
padding: 0 0 $tag_height + 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.left {
|
|
||||||
right: auto;
|
|
||||||
left: -2px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.scroll {
|
.scroll {
|
||||||
overflow: auto;
|
overflow: hidden;
|
||||||
max-height: 7 * $row_height + $tag_height;
|
|
||||||
padding: 0 0 $gap / 2;
|
padding: 0 0 $gap / 2;
|
||||||
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
background: rgba(255, 0, 0, 0.3);
|
background: rgba(255, 0, 0, 0.3);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
z-index: 20;
|
z-index: 26;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
animation: appear 0.25s forwards;
|
animation: appear 0.25s forwards;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue