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

#58 made dialogs as routes

This commit is contained in:
Fedor Katurov 2021-03-29 14:11:39 +07:00
parent d9af895558
commit 4dc8bea040
21 changed files with 230 additions and 172 deletions

View file

@ -1,58 +1,44 @@
import React, { FC, useCallback } from 'react';
import { useDispatch } from 'react-redux';
import React, { FC, useCallback, useState } from 'react';
import { Icon } from '~/components/input/Icon';
import { nodeCreate } from '~/redux/node/actions';
import styles from './styles.module.scss';
import { NODE_TYPES } from '~/redux/node/constants';
import { Link } from 'react-router-dom';
import classNames from 'classnames';
import { useRouteMatch } from 'react-router';
import styles from './styles.module.scss';
interface Props {
isLab?: boolean;
}
const SubmitBar: FC<Props> = ({ isLab }) => {
const dispatch = useDispatch();
const { url } = useRouteMatch();
const [focused, setFocused] = useState(false);
const onOpenImageEditor = useCallback(() => dispatch(nodeCreate(NODE_TYPES.IMAGE, isLab)), [
dispatch,
]);
const onOpenTextEditor = useCallback(() => dispatch(nodeCreate(NODE_TYPES.TEXT, isLab)), [
dispatch,
]);
const onOpenVideoEditor = useCallback(() => dispatch(nodeCreate(NODE_TYPES.VIDEO, isLab)), [
dispatch,
]);
const onOpenAudioEditor = useCallback(() => dispatch(nodeCreate(NODE_TYPES.AUDIO, isLab)), [
dispatch,
]);
const onFocus = useCallback(() => setFocused(true), [setFocused]);
const onBlur = useCallback(() => setFocused(false), [setFocused]);
return (
<div className={classNames(styles.wrap, { [styles.lab]: isLab })}>
<div className={styles.panel}>
<div onClick={onOpenImageEditor}>
<Icon icon="image" />
</div>
<div className={classNames(styles.panel, { [styles.active]: focused })}>
<Link to={`${url}/create/image`} className={styles.link}>
<Icon icon="image" size={32} />
</Link>
<div onClick={onOpenTextEditor}>
<Icon icon="text" />
</div>
<Link to={`${url}/create/text`} className={styles.link}>
<Icon icon="text" size={32} />
</Link>
<div onClick={onOpenVideoEditor}>
<Icon icon="video" />
</div>
<Link to={`${url}/create/video`} className={styles.link}>
<Icon icon="video" size={32} />
</Link>
<div onClick={onOpenAudioEditor}>
<Icon icon="audio" />
</div>
<Link to={`${url}/create/audio`} className={styles.link}>
<Icon icon="audio" size={32} />
</Link>
</div>
<div className={styles.button}>
<button className={styles.button} onFocus={onFocus} onBlur={onBlur} type="button">
<Icon icon="plus" />
</div>
</button>
</div>
);
};

View file

@ -5,13 +5,7 @@
bottom: 0;
left: 50%;
transform: translate($content_width / 2 + $gap, 0);
z-index: 4;
&:hover {
.panel {
transform: translate(0, 0);
}
}
z-index: 14;
@media (max-width: $content_width + ($bar_height + $gap) * 2) {
left: 100%;
@ -31,6 +25,8 @@
cursor: pointer;
position: relative;
z-index: 2;
border: none;
outline: none;
svg {
width: 32px;
@ -50,24 +46,32 @@
padding-bottom: $bar_height;
border-radius: $radius $radius 0 0;
transform: translate(0, 100%);
transition: transform 250ms;
transition: transform 250ms 250ms;
div {
@include outer_shadow;
height: $bar_height;
width: $bar_height;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
svg {
width: 32px;
height: 32px;
}
&:first-child {
border-radius: $radius $radius 0 0;
}
&.active {
transform: translate(0, 0);
transition: transform 250ms;
}
}
.link {
@include outer_shadow;
height: $bar_height;
width: $bar_height;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
fill: white;
color: white;
svg {
width: 32px;
height: 32px;
}
&:first-child {
border-radius: $radius $radius 0 0;
}
}

View file

@ -0,0 +1,19 @@
import React, { FC, MouseEventHandler } from 'react';
import ReactDOM from 'react-dom';
import styles from './styles.module.scss';
type IProps = {
onOverlayClick: MouseEventHandler;
};
const ModalWrapper: FC<IProps> = ({ children, onOverlayClick }) => {
return ReactDOM.createPortal(
<div className={styles.fixed}>
<div className={styles.overlay} onClick={onOverlayClick} />
<div className={styles.content}>{children}</div>
</div>,
document.body
);
};
export { ModalWrapper };

View file

@ -0,0 +1,61 @@
@import "src/styles/variables";
.fixed {
position: fixed;
z-index: 30;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
@keyframes appear {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.content {
position: absolute;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
opacity: 0;
animation: appear 0.25s forwards;
}
.content_scroller {
width: 100%;
max-width: 100vw;
max-height: 100vh;
overflow: auto;
}
.content_padder {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: transparentize($color: #000000, $amount: 0.9);
cursor: pointer;
animation: appear 0.25s forwards;
@include can_backdrop {
backdrop-filter: blur(15px);
}
}

View file

@ -5,6 +5,8 @@ import { INode } from '~/redux/types';
import classNames from 'classnames';
import { Placeholder } from '~/components/placeholders/Placeholder';
import { getPrettyDate } from '~/utils/dom';
import { URLS } from '~/constants/urls';
import { Link } from 'react-router-dom';
interface IProps {
node: Partial<INode>;
@ -24,7 +26,7 @@ interface IProps {
const NodePanelInner: FC<IProps> = memo(
({
node: { title, user, is_liked, is_heroic, deleted_at, created_at, like_count },
node: { id, title, user, is_liked, is_heroic, deleted_at, created_at, like_count },
stack,
canStar,
@ -78,9 +80,9 @@ const NodePanelInner: FC<IProps> = memo(
<Icon icon={deleted_at ? 'locked' : 'unlocked'} size={24} onClick={onLock} />
</div>
<div>
<Link to={URLS.NODE_EDIT_URL(id)}>
<Icon icon="edit" size={24} onClick={onEdit} />
</div>
</Link>
</div>
</div>
)}