From 861fd8d9e3e66d84108218accb0071b73b670aea Mon Sep 17 00:00:00 2001 From: Fedor Katurov <gotham48@gmail.com> Date: Wed, 15 Apr 2020 10:35:35 +0700 Subject: [PATCH] colors for cards --- src/components/node/NodeRelatedItem/index.tsx | 23 ++++++++-- .../node/NodeRelatedItem/styles.scss | 9 +++- src/utils/dom.ts | 45 +++++++++++++++++++ 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/components/node/NodeRelatedItem/index.tsx b/src/components/node/NodeRelatedItem/index.tsx index ebdfbdf8..982f62e9 100644 --- a/src/components/node/NodeRelatedItem/index.tsx +++ b/src/components/node/NodeRelatedItem/index.tsx @@ -1,10 +1,10 @@ -import React, { FC, memo, useCallback, useState } from 'react'; +import React, { FC, memo, useCallback, useState, useMemo } from 'react'; import * as styles from './styles.scss'; import classNames from 'classnames'; import { INode } from '~/redux/types'; import { URLS, PRESETS } from '~/constants/urls'; import { RouteComponentProps, withRouter } from 'react-router'; -import { getURL } from '~/utils/dom'; +import { getURL, stringToColour } from '~/utils/dom'; type IProps = RouteComponentProps & { item: Partial<INode>; @@ -28,6 +28,15 @@ const NodeRelatedItemUnconnected: FC<IProps> = memo(({ item, history }) => { const [is_loaded, setIsLoaded] = useState(false); const onClick = useCallback(() => history.push(URLS.NODE_URL(item.id)), [item, history]); + const thumb = useMemo( + () => (item.thumbnail ? getURL({ url: item.thumbnail }, PRESETS.avatar) : ''), + [item] + ); + const backgroundColor = useMemo( + () => (!thumb && item.title && stringToColour(item.title)) || '', + [] + ); + return ( <div className={classNames(styles.item, { [styles.is_loaded]: is_loaded })} @@ -36,10 +45,16 @@ const NodeRelatedItemUnconnected: FC<IProps> = memo(({ item, history }) => { > <div className={styles.thumb} - style={{ backgroundImage: `url("${getURL({ url: item.thumbnail }, PRESETS.avatar)}")` }} + style={{ + backgroundImage: `url("${thumb}")`, + }} /> - {!item.thumbnail && <div className={styles.letters}>{getTitleLetters(item.title)}</div>} + {!item.thumbnail && ( + <div className={styles.letters} style={{ backgroundColor }}> + {getTitleLetters(item.title)} + </div> + )} <img src={getURL({ url: item.thumbnail }, PRESETS.avatar)} diff --git a/src/components/node/NodeRelatedItem/styles.scss b/src/components/node/NodeRelatedItem/styles.scss index eccc8b81..39ce0041 100644 --- a/src/components/node/NodeRelatedItem/styles.scss +++ b/src/components/node/NodeRelatedItem/styles.scss @@ -40,6 +40,11 @@ width: 100%; height: 100%; font: $font_24_semibold; - // opacity: 0.2; - color: #444444; + color: white; + border-radius: $cell_radius; + background-image: linear-gradient( + 180deg, + transparentize($content_bg, 0.4), + transparentize($content_bg, 0.4) + ); } diff --git a/src/utils/dom.ts b/src/utils/dom.ts index d0624e25..7ef404a9 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -170,3 +170,48 @@ export function plural(n: number, one: string, two: string, five: string) { return `${n} ${five}`; } } + +export const stringToColour = (str: string) => { + let hash = 0; + + for (let i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + + let colour = '#'; + + for (let i = 0; i < 3; i++) { + let value = (hash >> (i * 8)) & 0xff; + colour += ('00' + value.toString(16)).substr(-2); + } + + return colour; +}; + +export const darken = (col: string, amt: number) => { + var usePound = false; + + if (col[0] == '#') { + col = col.slice(1); + usePound = true; + } + + var num = parseInt(col, 16); + + var r = (num >> 16) + amt; + + if (r > 255) r = 255; + else if (r < 0) r = 0; + + var b = ((num >> 8) & 0x00ff) + amt; + + if (b > 255) b = 255; + else if (b < 0) b = 0; + + var g = (num & 0x0000ff) + amt; + + if (g > 255) g = 255; + else if (g < 0) g = 0; + + return (usePound ? '#' : '') + (g | (b << 8) | (r << 16)).toString(16); +};