mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
made better profile popups
This commit is contained in:
parent
141b9c0d60
commit
0564fe29e2
5 changed files with 94 additions and 91 deletions
|
@ -16,7 +16,7 @@ interface Props {
|
||||||
const CommentAvatar: FC<Props> = ({ user, className }) => {
|
const CommentAvatar: FC<Props> = ({ user, className }) => {
|
||||||
return (
|
return (
|
||||||
<MenuButton
|
<MenuButton
|
||||||
position="top-start"
|
position="auto"
|
||||||
icon={
|
icon={
|
||||||
<Avatar url={path(['photo', 'url'], user)} username={user.username} className={className} />
|
<Avatar url={path(['photo', 'url'], user)} username={user.username} className={className} />
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import React, { FC, ReactNode } from 'react';
|
import React, { FC, ReactNode, useState } from 'react';
|
||||||
|
|
||||||
|
import { Placement } from '@popperjs/core';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Manager, Popper, Reference } from 'react-popper';
|
import { usePopper } from 'react-popper';
|
||||||
|
|
||||||
import { Icon } from '~/components/input/Icon';
|
import { Icon } from '~/components/input/Icon';
|
||||||
import { useFocusEvent } from '~/hooks/dom/useFocusEvent';
|
import { useFocusEvent } from '~/hooks/dom/useFocusEvent';
|
||||||
|
@ -9,61 +10,69 @@ import { useFocusEvent } from '~/hooks/dom/useFocusEvent';
|
||||||
import styles from './styles.module.scss';
|
import styles from './styles.module.scss';
|
||||||
|
|
||||||
interface MenuButtonProps {
|
interface MenuButtonProps {
|
||||||
position?: 'top-end' | 'bottom-end' | 'top-start' | 'bottom-start' | 'top' | 'bottom';
|
position?: Placement;
|
||||||
icon?: ReactNode;
|
icon?: ReactNode;
|
||||||
className?: string;
|
className?: string;
|
||||||
translucentMenu?: boolean;
|
translucentMenu?: boolean;
|
||||||
|
activate?: 'hover' | 'focus';
|
||||||
}
|
}
|
||||||
|
|
||||||
const modifiers = [
|
|
||||||
{
|
|
||||||
name: 'offset',
|
|
||||||
options: {
|
|
||||||
offset: [5, 10],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const MenuButton: FC<MenuButtonProps> = ({
|
const MenuButton: FC<MenuButtonProps> = ({
|
||||||
position = 'bottom-end',
|
position = 'bottom-end',
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
icon = <Icon icon="dots-vertical" size={24} />,
|
icon = <Icon icon="dots-vertical" size={24} />,
|
||||||
translucentMenu,
|
translucentMenu,
|
||||||
|
activate = 'focus',
|
||||||
}) => {
|
}) => {
|
||||||
const { focused, onFocus, onBlur } = useFocusEvent(false, 150);
|
const focus = useFocusEvent(false, 150);
|
||||||
|
const hover = useFocusEvent(false, 150);
|
||||||
|
|
||||||
|
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
|
||||||
|
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
||||||
|
const [arrowElement, setArrowElement] = useState<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
|
const popper = usePopper(referenceElement, popperElement, {
|
||||||
|
placement: position,
|
||||||
|
modifiers: [
|
||||||
|
{ name: 'arrow', options: { element: arrowElement } },
|
||||||
|
{
|
||||||
|
name: 'offset',
|
||||||
|
options: {
|
||||||
|
offset: [5, 10],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const visible = activate === 'focus' ? focus.focused : hover.focused;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Manager>
|
<>
|
||||||
<Reference>
|
<button
|
||||||
{({ ref }) => (
|
className={classNames(styles.menu, className)}
|
||||||
<button
|
ref={setReferenceElement}
|
||||||
className={classNames(styles.menu, className)}
|
onFocus={focus.onFocus}
|
||||||
ref={ref}
|
onBlur={focus.onBlur}
|
||||||
onFocus={onFocus}
|
onMouseOver={hover.onFocus}
|
||||||
onBlur={onBlur}
|
onMouseOut={hover.onBlur}
|
||||||
>
|
>
|
||||||
{icon}
|
{icon}
|
||||||
</button>
|
</button>
|
||||||
)}
|
|
||||||
</Reference>
|
|
||||||
|
|
||||||
{focused && (
|
<div
|
||||||
<Popper placement={position} modifiers={modifiers}>
|
style={popper.styles.popper}
|
||||||
{({ style, ref, placement }) => (
|
ref={setPopperElement}
|
||||||
<div
|
{...popper.attributes.popper}
|
||||||
style={style}
|
className={classNames(styles.popper, {
|
||||||
ref={ref}
|
[styles.translucent]: translucentMenu,
|
||||||
className={classNames(styles.popper, styles[placement], {
|
[styles.visible]: visible,
|
||||||
[styles.translucent]: translucentMenu,
|
})}
|
||||||
})}
|
>
|
||||||
>
|
<div style={popper.styles.arrow} ref={setArrowElement} className={styles.arrow} />
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
)}
|
</>
|
||||||
</Popper>
|
|
||||||
)}
|
|
||||||
</Manager>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,53 +12,44 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
z-index: 12;
|
z-index: 12;
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
touch-action: none;
|
||||||
|
|
||||||
&::after {
|
&.visible {
|
||||||
content: ' ';
|
visibility: visible;
|
||||||
width: 0;
|
pointer-events: all;
|
||||||
height: 0;
|
touch-action: initial;
|
||||||
border-style: solid;
|
}
|
||||||
border-width: 0 10px 10px 10px;
|
}
|
||||||
border-color: transparent transparent lighten($menu_bg, 6%) transparent;
|
|
||||||
position: absolute;
|
.arrow {
|
||||||
}
|
width: 0;
|
||||||
|
height: 0;
|
||||||
&.bottom-end::after {
|
border-style: solid;
|
||||||
top: -11px;
|
position: absolute;
|
||||||
right: 10px;
|
|
||||||
}
|
[data-popper-placement*='bottom'] & {
|
||||||
|
border-width: 0 10px 10px 10px;
|
||||||
&.bottom-start::after {
|
border-color: transparent transparent lighten($menu_bg, 6%) transparent;
|
||||||
top: -11px;
|
top: -10px;
|
||||||
left: 10px;
|
}
|
||||||
}
|
|
||||||
|
[data-popper-placement*='top'] & {
|
||||||
&.bottom::after {
|
border-width: 10px 10px 0 10px;
|
||||||
top: -11px;
|
border-color: lighten($menu_bg, 6%) transparent transparent transparent;
|
||||||
left: 50%;
|
bottom: -10px;
|
||||||
margin-left: -15px;
|
}
|
||||||
}
|
|
||||||
|
[data-popper-placement*='right'] & {
|
||||||
&.top-end::after {
|
border-width: 10px 10px 10px 0;
|
||||||
border-width: 10px 10px 0 10px;
|
border-color: transparent lighten($menu_bg, 6%) transparent transparent;
|
||||||
border-color: darken($menu_bg, 8%) transparent transparent transparent;
|
left: -10px;
|
||||||
bottom: -11px;
|
}
|
||||||
}
|
|
||||||
|
[data-popper-placement*='left'] & {
|
||||||
&.top-start::after {
|
border-width: 10px 0 10px 10px;
|
||||||
border-width: 10px 10px 0 10px;
|
border-color: transparent transparent transparent lighten($menu_bg, 6%);
|
||||||
border-color: darken($menu_bg, 8%) transparent transparent transparent;
|
right: -10px;
|
||||||
top: auto;
|
|
||||||
bottom: -11px;
|
|
||||||
left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.top::after {
|
|
||||||
border-width: 10px 10px 0 10px;
|
|
||||||
border-color: darken($menu_bg, 8%) transparent transparent transparent;
|
|
||||||
top: auto;
|
|
||||||
bottom: -11px;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -15px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ const ProfileQuickInfo: FC<ProfileQuickInfoProps> = ({ user }) => {
|
||||||
<Avatar url={path(['photo', 'url'], user)} username={user.username} />
|
<Avatar url={path(['photo', 'url'], user)} username={user.username} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Filler>
|
<Filler className={styles.names}>
|
||||||
<h5 className={styles.fullname}>{user.fullname || user.username}</h5>
|
<h5 className={styles.fullname}>{user.fullname || user.username}</h5>
|
||||||
<div className={styles.username}>~{user.username}</div>
|
<div className={styles.username}>~{user.username}</div>
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@ div.top.top {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.names {
|
||||||
|
}
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
font: $font_12_regular;
|
font: $font_12_regular;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue