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

better scroll dialog

This commit is contained in:
Fedor Katurov 2019-11-03 21:15:38 +07:00
parent 782ef41eda
commit 0c2229d9af
13 changed files with 221 additions and 27 deletions

5
package-lock.json generated
View file

@ -3028,6 +3028,11 @@
}
}
},
"body-scroll-lock": {
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/body-scroll-lock/-/body-scroll-lock-2.6.4.tgz",
"integrity": "sha512-NP08WsovlmxEoZP9pdlqrE+AhNaivlTrz9a0FF37BQsnOrpN48eNqivKkE7SYpM9N+YIPjsdVzfLAUQDBm6OQw=="
},
"bonjour": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",

View file

@ -57,6 +57,7 @@
"@typescript-eslint/parser": "^1.13.0",
"axios": "^0.18.0",
"babel-runtime": "^6.26.0",
"body-scroll-lock": "^2.6.4",
"classnames": "^2.2.6",
"clean-webpack-plugin": "^0.1.9",
"connected-react-router": "^6.3.2",

View file

@ -0,0 +1,64 @@
import React, {
FC,
MouseEventHandler,
ReactChild,
useCallback,
useEffect,
useState,
useRef,
} from 'react';
// import { DialogPanel } from '~/components/panels/DialogPanel';
import classNames from 'classnames';
import { Scroll } from '~/components/containers/Scroll';
import * as styles from './styles.scss';
import { enableBodyScroll, disableBodyScroll } from 'body-scroll-lock';
import { Icon } from '~/components/input/Icon';
interface IProps {
children: React.ReactChild;
header?: JSX.Element;
footer?: JSX.Element;
size?: 'medium' | 'big';
width?: number;
error?: string;
onOverlayClick?: MouseEventHandler<HTMLDivElement>;
onRefCapture?: (ref: any) => void;
onClose?: () => void;
}
const BetterScrollDialog: FC<IProps> = ({
children,
header,
footer,
width = 600,
error,
onOverlayClick,
onRefCapture,
onClose,
}) => {
const ref = useRef(null);
useEffect(() => {
disableBodyScroll(ref.current);
return () => enableBodyScroll(ref.current);
}, [ref]);
return (
<div className={styles.wrap} ref={ref}>
<div className={styles.container} style={{ maxWidth: width }}>
{onClose && (
<div className={styles.close} onClick={onClose}>
<Icon icon="close" />
</div>
)}
{header && <div className={styles.header}>{header}</div>}
<div className={styles.body}>{children}</div>
{footer && <div className={styles.header}>{footer}</div>}
</div>
</div>
);
};
export { BetterScrollDialog };

View file

@ -0,0 +1,84 @@
.wrap {
width: 100vw;
height: 100vh;
background: transparentize(darken($content_bg, 4%), 0.5);
display: flex;
align-items: center;
justify-content: center;
padding: 40px;
box-sizing: border-box;
}
.container {
display: flex;
align-items: stretch;
justify-content: center;
flex-direction: column;
min-width: $cell;
max-width: 400px;
max-height: 100%;
width: 100%;
position: relative;
& > div:nth-child(2) {
border-top-left-radius: $dialog_radius;
border-top-right-radius: $dialog_radius;
}
& > div:last-child {
border-bottom-left-radius: $dialog_radius;
border-bottom-right-radius: $dialog_radius;
}
}
.header,
.footer {
@include outer_shadow();
padding: 10px;
background: darken($content_bg, 2%);
}
.body {
@include outer_shadow();
overflow: auto;
flex: 1;
background: $content_bg;
}
@keyframes appear {
0% {
top: -48px;
}
100% {
top: -58px;
}
}
.close {
background: darken($content_bg, 2%);
width: 48px;
height: 48px;
position: absolute;
top: -58px;
right: 50%;
transform: translate(50%, 0);
display: flex;
align-items: center;
justify-content: center;
border-radius: 100%;
cursor: pointer;
transition: transform 0.25s, background-color 0.25s;
animation: appear 0.5s forwards;
&:hover {
background-color: $red;
transform: translate(50%, -5px);
}
svg {
width: 24px;
height: 24px;
}
}

View file

@ -14,6 +14,7 @@ import * as NODE_ACTIONS from '~/redux/node/actions';
import { selectUploads } from '~/redux/uploads/selectors';
import { ERROR_LITERAL } from '~/constants/errors';
import { NODE_EDITORS, EMPTY_NODE } from '~/redux/node/constants';
import { BetterScrollDialog } from '../BetterScrollDialog';
const mapStateToProps = state => {
const { editor, errors } = selectNode(state);
@ -90,8 +91,8 @@ const EditorDialogUnconnected: FC<IProps> = ({
return (
<form onSubmit={onSubmit} className={styles.form}>
<ScrollDialog
buttons={buttons}
<BetterScrollDialog
footer={buttons}
width={860}
error={error && ERROR_LITERAL[error]}
onClose={onRequestClose}
@ -104,7 +105,7 @@ const EditorDialogUnconnected: FC<IProps> = ({
setTemp,
})}
</div>
</ScrollDialog>
</BetterScrollDialog>
</form>
);
};

View file

@ -11,6 +11,7 @@ import * as styles from './styles.scss';
import { selectAuthLogin } from '~/redux/auth/selectors';
import * as ACTIONS from '~/redux/auth/actions';
import { API } from '~/constants/api';
import { BetterScrollDialog } from '../BetterScrollDialog';
const mapStateToProps = selectAuthLogin;
@ -47,20 +48,18 @@ const LoginDialogUnconnected: FC<IProps> = ({
}, [username, password]);
const buttons = (
<Padder>
<Group horizontal>
<Button iconLeft="key" stretchy>
<span>Войти</span>
</Button>
</Group>
</Padder>
<Group horizontal className={styles.footer}>
<Button stretchy>
<span>Войти</span>
</Button>
</Group>
);
useCloseOnEscape(onRequestClose);
return (
<form onSubmit={onSubmit}>
<ScrollDialog width={260} error={error} onClose={onRequestClose} buttons={buttons}>
<BetterScrollDialog width={260} error={error} onClose={onRequestClose} footer={buttons}>
<Padder>
<div className={styles.wrap}>
<Group>
@ -77,7 +76,7 @@ const LoginDialogUnconnected: FC<IProps> = ({
</Group>
</div>
</Padder>
</ScrollDialog>
</BetterScrollDialog>
</form>
);
};

View file

@ -1,14 +1,17 @@
$vk_color: darken(desaturate($blue, 70%), 20%);
$vk_color: darken(desaturate($blue, 100%), 30%);
.wrap {
display: flex;
align-items: flex-start;
justify-content: center;
padding: 20px;
margin: auto;
padding: $gap;
button {
text-align: left;
}
h2 {
margin-bottom: $gap * 3 !important;
margin: $gap 0 $gap * 4 !important;
}
}
@ -20,8 +23,8 @@ $vk_color: darken(desaturate($blue, 70%), 20%);
svg {
fill: $vk_color;
margin-right: $gap;
width: 24px;
height: 24px;
// width: 24px;
// height: 24px;
}
}
@ -30,3 +33,11 @@ $vk_color: darken(desaturate($blue, 70%), 20%);
padding: $gap * 2 0 0 0;
border-top: 1px solid black;
}
.footer {
padding: $gap;
button {
// text-align: left;
}
}

View file

@ -33,14 +33,10 @@ const ModalUnconnected: FC<IProps> = ({
<div className={styles.fixed}>
<div className={styles.overlay} onClick={onRequestClose} />
<div className={styles.content}>
<div className={styles.content_scroller}>
<div className={styles.content_padder}>
{React.createElement(DIALOG_CONTENT[dialog], {
onRequestClose,
onDialogChange: modalShowDialog,
})}
</div>
</div>
{React.createElement(DIALOG_CONTENT[dialog], {
onRequestClose,
onDialogChange: modalShowDialog,
})}
</div>
</div>,
document.body
@ -53,3 +49,12 @@ const Modal = connect(
)(ModalUnconnected);
export { ModalUnconnected, Modal };
/*
<div className={styles.content_scroller}>
<div className={styles.content_padder}>
</div>
</div>
*/

View file

@ -0,0 +1,16 @@
import React, { FC } from 'react';
import { BetterScrollDialog } from '../BetterScrollDialog';
import * as styles from './styles.scss';
interface IProps {}
const TestDialog: FC<IProps> = ({}) => (
<BetterScrollDialog
header={<div className={styles.head}>HEAD</div>}
footer={<div className={styles.footer}>FOOTER</div>}
>
<div className={styles.example} />
</BetterScrollDialog>
);
export { TestDialog };

View file

@ -0,0 +1,4 @@
.example {
height: 1200px;
background: yellow;
}

View file

@ -6,6 +6,7 @@ import { EditorDialogText } from '~/containers/editors/EditorDialogText';
import { EditorDialogVideo } from '~/containers/editors/EditorDialogVideo';
import { EditorDialogAudio } from '~/containers/editors/EditorDialogAudio';
import { NODE_TYPES } from '../node/constants';
import { TestDialog } from '~/containers/dialogs/TestDialog';
export const MODAL_ACTIONS = {
SET_SHOWN: 'MODAL.SET_SHOWN',
@ -20,6 +21,7 @@ export const DIALOGS = {
EDITOR_AUDIO: 'EDITOR_AUDIO',
LOGIN: 'LOGIN',
LOADING: 'LOADING',
TEST: 'TEST',
};
export const DIALOG_CONTENT = {
@ -29,6 +31,7 @@ export const DIALOG_CONTENT = {
[DIALOGS.EDITOR_AUDIO]: EditorDialogAudio,
[DIALOGS.LOGIN]: LoginDialog,
[DIALOGS.LOADING]: LoadingDialog,
[DIALOGS.TEST]: TestDialog,
};
export const NODE_EDITOR_DIALOGS = {

View file

@ -10,7 +10,7 @@ export interface IModalState {
const INITIAL_STATE: IModalState = {
is_shown: false,
dialog: DIALOGS.EDITOR_TEXT,
dialog: DIALOGS.LOGIN,
};
export default createReducer(INITIAL_STATE, MODAL_HANDLERS);

View file

@ -12,6 +12,7 @@ $radius: 4px;
$cell_radius: $radius;
$panel_radius: $radius;
$input_radius: $radius;
$dialog_radius: $radius * 2;
$input_height: 36px;
$info_height: 24px;