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

refactored flow cells, added colors for lab (#78)

* made better flow cells

* made cubical desaturation

* made colorfull lab nodes

* colorful lab nodes for all text ones

* all lab nodes are colorful

* disabled lazy loading on heroes

* fixed color calculation hook

* fixed lab color gradients calculation

* fixed cell text on flow
This commit is contained in:
muerwre 2021-10-08 11:33:53 +07:00 committed by GitHub
parent 7d6f35b0af
commit 94c656fe0f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 345 additions and 63 deletions

View file

@ -1,21 +1,26 @@
import React, { FC, useMemo } from 'react';
import styles from './styles.module.scss';
import { DEFAULT_DOMINANT_COLOR } from '~/constants/node';
import { convertHexToRGBA } from '~/utils/color';
import { DivProps } from '~/utils/types';
import classNames from 'classnames';
import { transparentize } from 'color2k';
import { normalizeBrightColor } from '~/utils/color';
interface Props extends DivProps {
color?: string;
size?: number;
}
const CellShade: FC<Props> = ({ color, ...rest }) => {
const CellShade: FC<Props> = ({ color, size = 50, ...rest }) => {
const background = useMemo(() => {
if (!color || color === DEFAULT_DOMINANT_COLOR) {
const normalized = normalizeBrightColor(color);
if (!color || color === DEFAULT_DOMINANT_COLOR || !normalized) {
return undefined;
}
return `linear-gradient(7deg, ${color} 50px, ${convertHexToRGBA(color, 0.3)} 250px)`;
return `linear-gradient(7deg, ${normalized} ${size}px, ${transparentize(normalized, 1)} ${size *
5}px)`;
}, [color]);
return (

View file

@ -1,16 +1,17 @@
@import "~/styles/variables";
.shade {
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: 0;
background: linear-gradient(7deg, transparentize($content_bg, 0.05) 30px, transparentize($content_bg, 1) 250px);
pointer-events: none;
touch-action: none;
@include tablet {
opacity: 0.7;
&.black::after {
content: ' ';
position: absolute;
top: 10px;
right: 10px;
width: 10px;
height: 10px;
background-color: blue;
}
}

View file

@ -0,0 +1,50 @@
import React, { FC } from 'react';
import styles from './styles.module.scss';
import { NavLink } from 'react-router-dom';
import { CellShade } from '~/components/flow/CellShade';
import { FlowCellImage } from '~/components/flow/FlowCellImage';
import { FlowDisplayVariant } from '~/redux/types';
import { FlowCellText } from '~/components/flow/FlowCellText';
import classNames from 'classnames';
interface Props {
to: string;
title: string;
image?: string;
color?: string;
text?: string;
display?: FlowDisplayVariant;
}
const FlowCell: FC<Props> = ({ color, to, image, display = 'single', text, title }) => {
const withText = ((!!display && display !== 'single') || !image) && !!text;
return (
<NavLink className={classNames(styles.cell, styles[display || 'single'])} to={to}>
{withText && (
<FlowCellText className={styles.text} heading={<h4 className={styles.title}>{title}</h4>}>
{text!}
</FlowCellText>
)}
{image && (
<FlowCellImage
src={image}
height={400}
className={styles.thumb}
style={{ backgroundColor: color }}
/>
)}
<CellShade color={color} className={styles.shade} size={withText ? 15 : 50} />
{!withText && (
<div className={styles.title_wrapper}>
<h4 className={styles.title}>{title}</h4>
</div>
)}
</NavLink>
);
};
export { FlowCell };

View file

@ -0,0 +1,97 @@
@import "~/styles/variables";
.cell {
@include inner_shadow;
position: relative;
overflow: hidden;
border-radius: $radius;
display: flex;
width: 100%;
height: 100%;
background: $content_bg;
flex-direction: row;
color: inherit;
text-decoration: inherit;
font: inherit;
line-height: inherit;
&.vertical {
flex-direction: column-reverse;
}
}
.thumb {
@include outer_shadow;
border-radius: $radius;
overflow: hidden;
position: relative;
z-index: 0;
}
.shade {
@include outer_shadow;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2;
}
.text {
position: absolute;
bottom: 5px;
left: 5px;
z-index: 1;
overflow: hidden;
border-radius: $radius;
max-height: calc(100% - 10px);
max-width: calc(100% - 10px);
box-sizing: border-box;
font: $font_16_regular;
@include tablet {
font: $font_14_regular;
left: 5px;
bottom: 5px;
}
& :global(.grey) {
color: inherit;
opacity: 0.5;
}
.quadro &,
.horizontal & {
max-width: calc(50% - 15px);
@include blur(transparentize($content_bg, 0), 10px, 0.5)
}
.quadro &,
.vertical & {
max-height: calc(50% - 15px);
@include blur(transparentize($content_bg, 0), 10px, 0.5)
}
}
.title_wrapper {
bottom: 0;
left: 0;
width: 100%;
z-index: 10;
padding: $gap;
position: absolute;
}
.title {
font: $font_cell_title;
text-transform: uppercase;
word-break: break-word;
@include tablet {
font: $font_18_semibold;
}
}

View file

@ -0,0 +1,18 @@
import React, { FC } from 'react';
import LazyLoad from 'react-lazyload';
import { IMGProps } from '~/utils/types';
import styles from './styles.module.scss';
import classNames from 'classnames';
interface Props extends IMGProps {
height?: number;
}
const FlowCellImage: FC<Props> = ({ className, children, ...rest }) => (
<LazyLoad once className={classNames(styles.wrapper, className)}>
<img {...rest} src={rest.src} alt="" />
{children}
</LazyLoad>
);
export { FlowCellImage };

View file

@ -0,0 +1,15 @@
.wrapper {
width: 100%;
height: 100%;
position: relative;
img {
position: absolute;
top: 50%;
left: 50%;
min-width: 100%;
min-height: 100%;
transform: translate(-50%, -50%);
object-fit: cover;
}
}

View file

@ -0,0 +1,23 @@
import React, { FC, ReactElement } from 'react';
import { Markdown } from '~/components/containers/Markdown';
import { DivProps } from '~/utils/types';
import classNames from 'classnames';
import styles from './styles.module.scss';
import { formatText } from '~/utils/dom';
interface Props extends DivProps {
children: string;
heading: string | ReactElement;
}
const FlowCellText: FC<Props> = ({ children, heading, ...rest }) => (
<div {...rest} className={classNames(styles.text, rest.className)}>
{heading && <div className={styles.heading}>{heading}</div>}
<Markdown
className={styles.description}
dangerouslySetInnerHTML={{ __html: formatText(children) }}
/>
</div>
);
export { FlowCellText };

View file

@ -0,0 +1,11 @@
@import "~/styles/variables";
.text {
padding: $gap;
line-height: 1.3em;
}
.heading {
margin-bottom: 0.4em;
}

View file

@ -1,12 +1,13 @@
import React, { FC, Fragment, useCallback } from 'react';
import { Cell } from '~/components/flow/Cell';
import React, { FC, Fragment } from 'react';
import { IFlowState } from '~/redux/flow/reducer';
import { INode } from '~/redux/types';
import { canEditNode } from '~/utils/node';
import { IUser } from '~/redux/auth/types';
import { useHistory } from 'react-router';
import { URLS } from '~/constants/urls';
import { PRESETS, URLS } from '~/constants/urls';
import { FlowCell } from '~/components/flow/FlowCell';
import classNames from 'classnames';
import styles from './styles.module.scss';
import { getURLFromString } from '~/utils/dom';
type IProps = Partial<IFlowState> & {
user: Partial<IUser>;
@ -14,9 +15,6 @@ type IProps = Partial<IFlowState> & {
};
export const FlowGrid: FC<IProps> = ({ user, nodes, onChangeCellView }) => {
const history = useHistory();
const onSelect = useCallback((id: INode['id']) => history.push(URLS.NODE_URL(id)), [history]);
if (!nodes) {
return null;
}
@ -24,13 +22,16 @@ export const FlowGrid: FC<IProps> = ({ user, nodes, onChangeCellView }) => {
return (
<Fragment>
{nodes.map(node => (
<Cell
key={node.id}
node={node}
onSelect={onSelect}
can_edit={canEditNode(node, user)}
onChangeCellView={onChangeCellView}
/>
<div className={classNames(styles.cell, styles[node.flow.display])} key={node.id}>
<FlowCell
color={node.flow.dominant_color}
to={URLS.NODE_URL(node.id)}
image={getURLFromString(node.thumbnail, PRESETS.cover)}
display={node.flow.display}
text={node.flow.show_description ? node.description : ''}
title={node.title}
/>
</div>
))}
</Fragment>
);

View file

@ -0,0 +1,19 @@
@import "~/styles/variables";
@mixin mobile {
@media (max-width: $cell * 2) {
@content;
}
}
.cell {
&.horizontal,
&.quadro {
grid-column-end: span 2;
}
&.vertical,
&.quadro {
grid-row-end: span 2;
}
}

View file

@ -100,7 +100,8 @@ export const FlowSwiperHero: FC<Props> = ({ heroes }) => {
speed={3000}
className={styles.swiper}
lazy={{
loadPrevNextAmount: 3,
loadPrevNextAmount: 5,
checkInView: false,
}}
loop
slidesPerView={1}
@ -122,7 +123,7 @@ export const FlowSwiperHero: FC<Props> = ({ heroes }) => {
.map(node => (
<SwiperSlide key={node.id}>
<img
data-src={getURLFromString(node.thumbnail!, preset)}
src={getURLFromString(node.thumbnail!, preset)}
alt=""
className={classNames(styles.preview, 'swiper-lazy')}
/>