1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 04:46:40 +07:00

used popper to handle positioning

This commit is contained in:
Fedor Katurov 2020-10-31 22:55:09 +07:00
parent c19fb3282e
commit 6de411f140
4 changed files with 29 additions and 46 deletions

View file

@ -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;

View file

@ -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" />

View file

@ -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;
} }

View file

@ -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;