From 29b0e23319d33613182f3ed4f33bc6fe0cbca7da Mon Sep 17 00:00:00 2001 From: Pavel Prichodko <14926950+prichodko@users.noreply.github.com> Date: Mon, 13 Jun 2022 16:18:06 +0200 Subject: [PATCH] add support for identicon ring to avatar --- .../status-react/src/system/avatar/avatar.tsx | 66 +++++++++---------- .../status-react/src/system/avatar/styles.tsx | 16 ++++- .../status-react/src/system/avatar/utils.tsx | 60 +++++++++++++++++ 3 files changed, 107 insertions(+), 35 deletions(-) create mode 100644 packages/status-react/src/system/avatar/utils.tsx diff --git a/packages/status-react/src/system/avatar/avatar.tsx b/packages/status-react/src/system/avatar/avatar.tsx index 9994235..b1f6d6b 100644 --- a/packages/status-react/src/system/avatar/avatar.tsx +++ b/packages/status-react/src/system/avatar/avatar.tsx @@ -1,7 +1,8 @@ -import React from 'react' +import React, { useMemo } from 'react' import { Image } from '../image' -import { Base, Indicator, Initials } from './styles' +import { Base, Content, Indicator, Initials } from './styles' +import { generateIdenticonRing } from './utils' import type { Variants } from './styles' @@ -11,46 +12,43 @@ interface Props { indicator?: 'online' | 'offline' src?: string color?: string + colorHash?: number[][] } const Avatar = (props: Props) => { - const { size, name, src, color, indicator } = props + const { size, name, src, color, indicator, colorHash } = props - // const identicon = useMemo(() => { - // const colors = colorWheel - // .map((color, idx) => { - // const prevDeg = idx === 0 ? '0deg' : `${colorWheel[idx - 1][1]}deg` - // return `${color[0]} ${prevDeg} ${color[1]}deg` - // }) - // .join(',') - // return `conic-gradient(${colors})` - // }, [colorWheel]) - - // const intials = useMemo(() => { - // if (contact && contact?.customName) { - // return contact.customName.slice(0, 2) - // } - // if (contact && contact.trueName) { - // return contact.trueName.slice(0, 2) - // } - // }, [contact]) + const identiconRing = useMemo(() => { + if (colorHash) { + const gradient = generateIdenticonRing(colorHash) + return `conic-gradient(${gradient})` + } + }, [colorHash]) const initials = name ? name.slice(0, 1) : '' return ( - - {initials && {initials}} - {src && ( - avatar - )} - {indicator && } + + + {initials && {initials}} + {src && ( + avatar + )} + {indicator && } + ) } diff --git a/packages/status-react/src/system/avatar/styles.tsx b/packages/status-react/src/system/avatar/styles.tsx index fd8d4ac..3761a43 100644 --- a/packages/status-react/src/system/avatar/styles.tsx +++ b/packages/status-react/src/system/avatar/styles.tsx @@ -6,7 +6,6 @@ export type Variants = VariantProps export const Base = styled('div', { position: 'relative', - background: '$primary-1', borderRadius: '100%', flexShrink: 0, @@ -15,39 +14,54 @@ export const Base = styled('div', { 20: { width: 20, height: 20, + padding: 1, }, 24: { width: 24, height: 24, + padding: 1, }, 32: { width: 32, height: 32, + padding: 2, }, 36: { width: 36, height: 36, + padding: 2, }, 44: { width: 44, height: 44, + padding: 2, }, 64: { width: 64, height: 64, + padding: 3, }, 80: { width: 80, height: 80, + padding: 4, }, 120: { width: 120, height: 120, + padding: 5, }, }, }, }) +export const Content = styled('div', { + background: '$primary-1', + borderRadius: '100%', + width: '100%', + height: '100%', +}) + export const Indicator = styled('span', { position: 'absolute', right: -2, diff --git a/packages/status-react/src/system/avatar/utils.tsx b/packages/status-react/src/system/avatar/utils.tsx new file mode 100644 index 0000000..61984fb --- /dev/null +++ b/packages/status-react/src/system/avatar/utils.tsx @@ -0,0 +1,60 @@ +/** + * returns value for conic-gradient + */ +export const generateIdenticonRing = (colorHash: number[][]) => { + const segments = colorHash.reduce((acc, segment) => (acc += segment[0]), 0) + + let prevAngle = 0 + const gradient = colorHash.reduce((acc, segment, index) => { + const [length, colorIndex] = segment + const color = COLORS[colorIndex] + const nextAngle = Math.round(prevAngle + (length * 360) / segments) + + acc += `${color} ${prevAngle}deg ${nextAngle}deg` + + if (index !== colorHash.length - 1) { + acc += `, ` + } + + prevAngle = nextAngle + + return acc + }, '') + + return gradient +} + +const COLORS = [ + '#000000', + '#726F6F', + '#C4C4C4', + '#E7E7E7', + '#FFFFFF', + '#00FF00', + '#009800', + '#B8FFBB', + '#FFC413', + '#9F5947', + '#FFFF00', + '#A8AC00', + '#FFFFB0', + '#FF5733', + '#FF0000', + '#9A0000', + '#FF9D9D', + '#FF0099', + '#C80078', + '#FF00FF', + '#900090', + '#FFB0FF', + '#9E00FF', + '#0000FF', + '#000086', + '#9B81FF', + '#3FAEF9', + '#9A6600', + '#00FFFF', + '#008694', + '#C2FFFF', + '#00F0B6', +]