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

added node edit menu

This commit is contained in:
Fedor Katurov 2022-07-15 12:13:27 +07:00
parent f185914c7c
commit 74f4c7562b
16 changed files with 320 additions and 175 deletions

View file

@ -0,0 +1,64 @@
import React, { FC, ReactNode } from 'react';
import classNames from 'classnames';
import { Manager, Popper, Reference } from 'react-popper';
import { Icon } from '~/components/input/Icon';
import { useFocusEvent } from '~/hooks/dom/useFocusEvent';
import styles from './styles.module.scss';
interface MenuButtonProps {
icon?: ReactNode;
className?: string;
}
const modifiers = [
{
name: 'offset',
options: {
offset: [5, 10],
},
},
];
const MenuButton: FC<MenuButtonProps> = ({
children,
className,
icon = <Icon icon="dots-vertical" size={24} />,
}) => {
const { focused, onFocus, onBlur } = useFocusEvent(false, 150);
return (
<Manager>
<Reference>
{({ ref }) => (
<button
className={classNames(styles.menu, className)}
ref={ref}
onFocus={onFocus}
onBlur={onBlur}
>
{icon}
</button>
)}
</Reference>
{focused && (
<Popper placement="bottom-end" modifiers={modifiers}>
{({ style, ref, placement }) => (
<div
style={style}
ref={ref}
className={classNames(styles.popper, { [styles.top]: placement === 'top-end' })}
>
{children}
</div>
)}
</Popper>
)}
</Manager>
);
};
export { MenuButton };

View file

@ -0,0 +1,40 @@
.menu {
position: relative;
cursor: pointer;
}
@import "src/styles/variables.scss";
@keyframes appear {
0% { opacity: 0 }
100% { opacity: 1 }
}
.popper {
@include outer_shadow;
background-color: $menu_bg;
box-sizing: border-box;
z-index: 12;
border-radius: $radius;
animation: appear forwards 250ms;
&::after {
content: ' ';
width: 0;
height: 0;
border-style: solid;
border-width: 0 10px 10px 10px;
border-color: transparent transparent lighten($menu_bg, 6%) transparent;
position: absolute;
top: -11px;
right: 10px;
}
&.top::after {
border-width: 10px 10px 0 10px;
border-color: darken($menu_bg, 8%) transparent transparent transparent;
top: auto;
bottom: -11px;
}
}

View file

@ -0,0 +1,23 @@
import React, { FC } from 'react';
import { Icon } from '~/components/input/Icon';
import styles from './styles.module.scss';
interface MenuItemWithIconProps {
children: string;
icon: string;
onClick?: () => void;
}
const MenuItemWithIcon: FC<MenuItemWithIconProps> = ({ children, icon, onClick }) => (
<button className={styles.item} onClick={onClick}>
<div className={styles.icon}>
<Icon icon={icon} size={20} />
</div>
<div className={styles.text}>{children}</div>
</button>
);
export { MenuItemWithIcon };

View file

@ -0,0 +1,29 @@
@import "src/styles/variables";
.item {
@include row_shadow;
@include hover_opacity;
font: $font_14_medium;
line-height: 20px;
padding: $gap + 2px $gap $gap - 2px;
display: flex;
flex-direction: row;
color: white;
align-items: stretch;
justify-content: center;
width: 100%;
cursor: pointer;
}
.icon {
flex: 0 0 20px;
margin-right: $gap;
}
.text {
flex: 1;
text-align: left;
padding-right: $gap;
white-space: nowrap;
}

View file

@ -0,0 +1,31 @@
import React, { FC, ReactNode, useMemo } from 'react';
import classNames from 'classnames';
import styles from './styles.module.scss';
interface SeparatedMenuProps {
className?: string;
}
const SeparatedMenu: FC<SeparatedMenuProps> = ({ children, className }) => {
const items = useMemo<ReactNode[]>(() => {
if (!children) {
return [];
}
return (Array.isArray(children) ? children : [children]).filter(it => it);
}, [children]);
return (
<div className={classNames(styles.menu, className)}>
{items.map((item, index) => (
<div className={styles.item} key={index}>
{item}
</div>
))}
</div>
);
};
export { SeparatedMenu };

View file

@ -0,0 +1,29 @@
@import "src/styles/mixins";
@import "src/styles/variables";
.menu {
flex: 0;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.item {
margin-left: $gap * 4;
position: relative;
&:not(:last-child)::after {
@include inner_shadow;
content: ' ';
position: absolute;
width: 3px;
height: 16px;
background: darken($content_bg, 1%);
display: flex;
top: 5px;
right: -$gap * 2 - 2px;
border-radius: 2px;
}
}

View file

@ -0,0 +1,5 @@
export * from './VerticalMenu';
export * from './HorizontalMenu';
export * from './MenuButton';
export * from './MenuItemWithIcon';
export * from './SeparatedMenu';