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

fixed features at editor

This commit is contained in:
muerwre 2019-08-01 19:11:01 +07:00
parent 85ee879c2f
commit 393813ce4e
9 changed files with 204 additions and 163 deletions

View file

@ -1,6 +1,6 @@
import React, { FC } from 'react'; import React, { FC } from "react";
import classNames from 'classnames'; import classNames from "classnames";
import * as styles from './styles.scss'; import * as styles from "./styles.scss";
type IProps = React.HTMLAttributes<HTMLDivElement> & { type IProps = React.HTMLAttributes<HTMLDivElement> & {
horizontal?: boolean; horizontal?: boolean;
@ -10,39 +10,42 @@ type IProps = React.HTMLAttributes<HTMLDivElement> & {
size?: string; size?: string;
square?: boolean; square?: boolean;
gap?: number; gap?: number;
stretchy?: boolean;
}; };
const Grid: FC<IProps> = ({ const Grid: FC<IProps> = ({
children, children,
className = '', className = "",
horizontal = false, horizontal = false,
vertical = false, vertical = false,
square = false, square = false,
size = 'auto', size = "auto",
style = {}, style = {},
columns = 'auto', columns = "auto",
rows = 'auto', rows = "auto",
gap = 10, gap = 10,
stretchy,
...props ...props
}) => ( }) => (
<div <div
className={classNames( className={classNames(styles.grid, className, {
styles.grid, [styles.horizontal]: horizontal,
className, [styles.vertical]: !horizontal,
{ [styles.square]: square,
[styles.horizontal]: horizontal, [styles.stretchy]: stretchy
[styles.vertical]: !horizontal, })}
[styles.square]: square,
},
)}
style={{ style={{
...style, ...style,
gridTemplateColumns: square ? `repeat(auto-fill, ${(columns !== 'auto' && columns) || size})` : columns, gridTemplateColumns: square
gridTemplateRows: square ? `repeat(auto-fill, ${(rows !== 'auto' && rows) || size})` : rows, ? `repeat(auto-fill, ${(columns !== "auto" && columns) || size})`
: columns,
gridTemplateRows: square
? `repeat(auto-fill, ${(rows !== "auto" && rows) || size})`
: rows,
gridAutoRows: rows, gridAutoRows: rows,
gridAutoColumns: columns, gridAutoColumns: columns,
gridRowGap: gap, gridRowGap: gap,
gridColumnGap: gap, gridColumnGap: gap
}} }}
{...props} {...props}
> >

View file

@ -15,4 +15,8 @@
&.square { &.square {
grid-auto-flow: dense; grid-auto-flow: dense;
} }
&.stretchy {
flex: 1;
}
} }

View file

@ -1,25 +1,29 @@
import classnames from 'classnames'; import classnames from "classnames";
import * as styles from './styles.scss'; import * as styles from "./styles.scss";
import React, { ButtonHTMLAttributes, DetailedHTMLProps, FC } from 'react'; import React, { ButtonHTMLAttributes, DetailedHTMLProps, FC } from "react";
import { Icon } from '~/components/input/Icon'; import { Icon } from "~/components/input/Icon";
import { IIcon } from "~/redux/types"; import { IIcon } from "~/redux/types";
type IButtonProps = DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> & { type IButtonProps = DetailedHTMLProps<
size?: 'mini' | 'normal' | 'big' | 'giant' | 'micro'; ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
> & {
size?: "mini" | "normal" | "big" | "giant" | "micro";
iconLeft?: IIcon; iconLeft?: IIcon;
iconRight?: IIcon; iconRight?: IIcon;
seamless?: boolean; seamless?: boolean;
transparent?: boolean; transparent?: boolean;
title?: string; title?: string;
red?: boolean, red?: boolean;
grey?: boolean, grey?: boolean;
non_submitting?: boolean; non_submitting?: boolean;
is_loading?: boolean; is_loading?: boolean;
stretchy?: boolean;
}; };
export const Button: FC<IButtonProps> = ({ export const Button: FC<IButtonProps> = ({
className = '', className = "",
size = 'normal', size = "normal",
iconLeft, iconLeft,
iconRight, iconRight,
children, children,
@ -30,34 +34,28 @@ export const Button: FC<IButtonProps> = ({
grey = false, grey = false,
is_loading, is_loading,
title, title,
stretchy,
...props ...props
}) => ( }) =>
React.createElement( React.createElement(seamless || non_submitting ? "div" : "button", {
(seamless || non_submitting) ? 'div' : 'button', className: classnames(styles.button, className, styles[size], {
{ red,
className: classnames( grey,
styles.button, seamless,
className, transparent,
styles[size], disabled: props.disabled,
{ icon: (iconLeft || iconRight) && !title && !children,
red, is_loading,
grey, stretchy
seamless, }),
transparent, children: [
disabled: props.disabled, iconLeft && <Icon icon={iconLeft} size={20} key={0} />,
icon: (iconLeft || iconRight) && !title && !children, title ? (
is_loading, <span key={1}>{title}</span>
}), ) : (
children: [ (children && <span key={1}>{children}</span>) || null
iconLeft && <Icon icon={iconLeft} size={20} key={0} />, ),
( iconRight && <Icon icon={iconRight} size={20} key={2} />
title ],
? <span key={1}>{title}</span> ...props
: (children && <span key={1}>{children}</span>) || null });
),
iconRight && <Icon icon={iconRight} size={20} key={2} />,
],
...props,
},
)
);

View file

@ -1,6 +1,10 @@
@keyframes pulse { @keyframes pulse {
0% { opacity: 1; } 0% {
100% { opacity: 0.3; } opacity: 1;
}
100% {
opacity: 0.3;
}
} }
.button { .button {
@ -28,23 +32,27 @@
justify-content: center; justify-content: center;
// box-shadow: transparentize(#E933A5, 0.6) 0 2px 8px; // box-shadow: transparentize(#E933A5, 0.6) 0 2px 8px;
box-shadow: transparentize(#E933A5, 0.6) 0 0 0; box-shadow: transparentize(#e933a5, 0.6) 0 0 0;
filter: grayscale(0); filter: grayscale(0);
transition: opacity 0.25s, filter 0.25s, box-shadow 0.25s; transition: opacity 0.25s, filter 0.25s, box-shadow 0.25s;
opacity: 0.8; opacity: 0.8;
span {
flex: 1;
}
&:hover { &:hover {
opacity: 1; opacity: 1;
box-shadow: transparentize(#E933A5, 0.4) 0 2px 8px; box-shadow: transparentize(#e933a5, 0.4) 0 2px 8px;
&:global(.disabled) { &:global(.disabled) {
box-shadow: transparentize(#E933A5, 0.6) 0 0 0; box-shadow: transparentize(#e933a5, 0.6) 0 0 0;
cursor: auto; cursor: auto;
} }
&:active { &:active {
box-shadow: transparentize(#E933A5, 0.6) 0 0 0; box-shadow: transparentize(#e933a5, 0.6) 0 0 0;
} }
} }
@ -72,7 +80,12 @@
color: $red; color: $red;
} }
&:global(.disabled), &:global(.grey) { &:global(.stretchy) {
flex: 1;
}
&:global(.disabled),
&:global(.grey) {
opacity: 0.3; opacity: 0.3;
//background: black; //background: black;
filter: grayscale(100%); filter: grayscale(100%);
@ -84,7 +97,8 @@
} }
&:global(.is_loading) { &:global(.is_loading) {
span, svg { span,
svg {
animation: pulse 0.25s infinite alternate; animation: pulse 0.25s infinite alternate;
} }
} }
@ -92,16 +106,34 @@
> * { > * {
margin: 0 5px; margin: 0 5px;
&:first-child { margin-left: 0; } &:first-child {
&:last-child { margin-right: 0; } margin-left: 0;
}
&:last-child {
margin-right: 0;
}
} }
} }
.micro { height: 20px; font: $font_12_semibold; padding: 0 15px;} .micro {
.mini { height: 28px; } height: 20px;
.normal { height: 38px; } font: $font_12_semibold;
.big { height: 40px; } padding: 0 15px;
.giant { height: 50px; padding: 0 15px; min-width: 50px; } }
.mini {
height: 28px;
}
.normal {
height: 38px;
}
.big {
height: 40px;
}
.giant {
height: 50px;
padding: 0 15px;
min-width: 50px;
}
.disabled { .disabled {
opacity: 0.5; opacity: 0.5;
} }

View file

@ -1,23 +1,19 @@
import React, { FC } from 'react'; import React, { FC } from "react";
import { IIcon } from '~/redux/types'; import { IIcon } from "~/redux/types";
type IProps = React.SVGAttributes<SVGElement> & { type IProps = React.SVGAttributes<SVGElement> & {
size?: number; size?: number;
icon: IIcon; icon: IIcon;
}; };
export const Icon: FC<IProps> = ({ export const Icon: FC<IProps> = ({ size = 20, icon, style, ...props }) => (
size = 20,
icon,
...props
}) => (
<svg <svg
width={size} width={size}
height={size} height={size}
viewBox={`0 0 24 24`} viewBox={`0 0 24 24`}
preserveAspectRatio="xMidYMid slice" preserveAspectRatio="xMidYMid slice"
style={{ ...style, outline: "none" }}
{...props} {...props}
style={{ ...props.style, outline: 'none' }}
> >
<use xlinkHref={`#${icon}`} /> <use xlinkHref={`#${icon}`} />
</svg> </svg>

View file

@ -1,28 +1,38 @@
import * as React from 'react'; import * as React from "react";
import { Logo } from "~/components/main/Logo"; import { Logo } from "~/components/main/Logo";
import { connect } from 'react-redux'; import { connect } from "react-redux";
import { IUserState } from "~/redux/user/reducer"; import { IUserState } from "~/redux/user/reducer";
import { push as historyPush } from 'connected-react-router'; import { push as historyPush } from "connected-react-router";
import * as style from './style.scss'; import * as style from "./style.scss";
import {Filler} from "~/components/containers/Filler"; import { Filler } from "~/components/containers/Filler";
import {Group} from "~/components/containers/Group"; import { Link } from "react-router-dom";
import { Link } from 'react-router-dom';
const mapStateToProps = ({
user: {
profile: { username, is_user }
}
}: {
user: IUserState;
}) => ({ username, is_user });
const mapStateToProps = ({ user: { profile: { username, is_user } } }: { user: IUserState }) => ({ username, is_user });
const mapDispatchToProps = { const mapDispatchToProps = {
push: historyPush, push: historyPush
}; };
type IHeaderProps = ReturnType<typeof mapStateToProps> & typeof mapDispatchToProps & {}; type IHeaderProps = ReturnType<typeof mapStateToProps> &
typeof mapDispatchToProps & {};
export const Component: React.FunctionComponent<IHeaderProps> = ({ username, is_user }) => { export const Component: React.FunctionComponent<IHeaderProps> = ({
username,
is_user
}) => {
return ( return (
<div className="default_container head_container"> <div className="default_container head_container">
<div className={style.container}> <div className={style.container}>
<Logo/> <Logo />
<Filler/> <Filler />
<div className={style.plugs}> <div className={style.plugs}>
<Link to="/">flow</Link> <Link to="/">flow</Link>
@ -31,15 +41,18 @@ export const Component: React.FunctionComponent<IHeaderProps> = ({ username, is_
<Link to="/examples/horizontal">horizontal</Link> <Link to="/examples/horizontal">horizontal</Link>
</div> </div>
<Filler/> <Filler />
<Group horizontal className={style.user_button}> {/* <Group horizontal className={style.user_button}>
<div>username</div> <div>username</div>
<div className={style.user_avatar}/> <div className={style.user_avatar}/>
</Group> </Group> */}
</div> </div>
</div> </div>
); );
}; };
export const Header = connect(mapStateToProps, mapDispatchToProps)(Component); export const Header = connect(
mapStateToProps,
mapDispatchToProps
)(Component);

View file

@ -1,6 +1,6 @@
import React, { FC } from 'react'; import React, { FC } from "react";
import { Card } from "~/components/containers/Card"; import { Card } from "~/components/containers/Card";
import * as styles from './styles.scss'; import * as styles from "./styles.scss";
import { Group } from "~/components/containers/Group"; import { Group } from "~/components/containers/Group";
import { CellGrid } from "~/components/containers/CellGrid"; import { CellGrid } from "~/components/containers/CellGrid";
import { Panel } from "~/components/containers/Panel"; import { Panel } from "~/components/containers/Panel";
@ -11,71 +11,63 @@ import { Button } from "~/components/input/Button";
import { Filler } from "~/components/containers/Filler"; import { Filler } from "~/components/containers/Filler";
import { InputText } from "~/components/input/InputText"; import { InputText } from "~/components/input/InputText";
import { Icon } from "~/components/input/Icon"; import { Icon } from "~/components/input/Icon";
import { Grid } from "~/components/containers/Grid";
interface IProps {} interface IProps {}
const EditorExample: FC<IProps> = () => ( const EditorExample: FC<IProps> = () => (
<Card className={styles.wrap} seamless> <Card className={styles.wrap} seamless>
<Group horizontal className={styles.group} seamless> <Group horizontal className={styles.group} seamless>
<div className={styles.editor}> <div className={styles.editor}>
<Panel className={classNames(styles.editor_panel, styles.editor_image_panel)}> <Panel
<Scroll> className={classNames(styles.editor_panel, styles.editor_image_panel)}
<CellGrid className={styles.editor_image_container} size={200}> >
<div className={styles.editor_image} /> <Scroll>
<div className={styles.editor_image} /> <CellGrid className={styles.editor_image_container} size={200}>
<div className={styles.editor_image} /> <div className={styles.editor_image} />
<div className={styles.editor_image} /> <div className={styles.editor_image} />
</CellGrid> <div className={styles.editor_image} />
</Scroll> <div className={styles.editor_image} />
</Panel> </CellGrid>
</div> </Scroll>
</Panel>
<div className={styles.panel}> <Panel>
<Panel> <Grid columns="1fr" stretchy>
<Group> <Card className={styles.feature_card}>
<InputText title="Заголовок" /> <div className={styles.cover} />
</Card>
</Grid>
</Panel>
</div>
<Tags <div className={styles.panel}>
tags={[ <Panel>
{ title: 'Избранный', feature: 'red' }, <Group>
{ title: 'Плейлист', feature: 'green' }, <InputText title="Заголовок" />
{ title: 'Просто' },
{ title: '+ фото', feature: 'black' },
{ title: '+ с музыкой', feature: 'black' },
]}
/>
</Group>
</Panel>
<Panel stretchy> <Tags
<Group> tags={[
<Card className={styles.feature_card}> { title: "Избранный", feature: "red" },
<div className={styles.cover} /> { title: "Плейлист", feature: "green" },
</Card> { title: "Просто" },
{ title: "+ фото", feature: "black" },
{ title: "+ с музыкой", feature: "black" }
]}
/>
</Group>
</Panel>
<Card className={styles.feature_card} style={{ justifyContent: 'flex-start', height: 72 }}> <Panel stretchy />
<Icon icon="play" size={48} />
</Card>
<Card className={styles.feature_card}> <Panel>
<Group horizontal className={styles.views}> <Button iconRight="play" stretchy>
<Icon icon="cell-single" size={48} /> Submit?
<Icon icon="cell-double-h" size={48} /> </Button>
<Icon icon="cell-single" size={48} /> </Panel>
<Icon icon="cell-double-h" size={48} /> </div>
</Group> </Group>
</Card> </Card>
<Filler />
</Group>
</Panel>
<Panel>
<Button>Submit?</Button>
</Panel>
</div>
</Group>
</Card>
); );
export { EditorExample }; export { EditorExample };

View file

@ -44,7 +44,7 @@
} }
.feature_card { .feature_card {
// height: 120px; height: 120px;
background: darken($main_bg_color, 6%); background: darken($main_bg_color, 6%);
color: transparentize(white, 0.5); color: transparentize(white, 0.5);
display: flex; display: flex;
@ -58,7 +58,7 @@
.cover { .cover {
border-radius: $radius; border-radius: $radius;
background: url('http://37.192.131.144/full/attached/2017/11/f01fdaaea789915284757634baf7cd11.jpg'); background: url("http://37.192.131.144/full/attached/2017/11/f01fdaaea789915284757634baf7cd11.jpg");
flex: 1; flex: 1;
height: 120px; height: 120px;
background-size: cover; background-size: cover;
@ -79,5 +79,9 @@
} }
.views { .views {
div {
} display: flex;
align-items: center;
justify-content: center;
}
}

View file

@ -23,8 +23,7 @@ const Sprites: FC<{}> = () => (
<g id="play"> <g id="play">
<path d="M8 6.82v10.36c0 .79.87 1.27 1.54.84l8.14-5.18c.62-.39.62-1.29 0-1.69L9.54 5.98C8.87 5.55 8 6.03 8 6.82z"/> <path d="M8 6.82v10.36c0 .79.87 1.27 1.54.84l8.14-5.18c.62-.39.62-1.29 0-1.69L9.54 5.98C8.87 5.55 8 6.03 8 6.82z"/>
</g> </g>
</svg> </svg>
); );