add support for identicon ring to avatar

This commit is contained in:
Pavel Prichodko 2022-06-13 16:18:06 +02:00
parent 47ea7a90ad
commit 29b0e23319
No known key found for this signature in database
GPG Key ID: 8E4C82D464215E83
3 changed files with 107 additions and 35 deletions

View File

@ -1,7 +1,8 @@
import React from 'react' import React, { useMemo } from 'react'
import { Image } from '../image' 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' import type { Variants } from './styles'
@ -11,46 +12,43 @@ interface Props {
indicator?: 'online' | 'offline' indicator?: 'online' | 'offline'
src?: string src?: string
color?: string color?: string
colorHash?: number[][]
} }
const Avatar = (props: Props) => { const Avatar = (props: Props) => {
const { size, name, src, color, indicator } = props const { size, name, src, color, indicator, colorHash } = props
// const identicon = useMemo(() => { const identiconRing = useMemo(() => {
// const colors = colorWheel if (colorHash) {
// .map((color, idx) => { const gradient = generateIdenticonRing(colorHash)
// const prevDeg = idx === 0 ? '0deg' : `${colorWheel[idx - 1][1]}deg` return `conic-gradient(${gradient})`
// return `${color[0]} ${prevDeg} ${color[1]}deg` }
// }) }, [colorHash])
// .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 initials = name ? name.slice(0, 1) : '' const initials = name ? name.slice(0, 1) : ''
return ( return (
<Base size={size} style={{ backgroundColor: color }}> <Base
{initials && <Initials size={size}>{initials}</Initials>} size={size}
{src && ( style={{
<Image background: identiconRing,
src={src} padding: !identiconRing ? 0 : undefined,
alt="avatar" }}
width="100%" >
height="100%" <Content style={{ background: color }}>
fit="cover" {initials && <Initials size={size}>{initials}</Initials>}
radius="full" {src && (
/> <Image
)} src={src}
{indicator && <Indicator size={size} state={indicator} />} alt="avatar"
width="100%"
height="100%"
fit="cover"
radius="full"
/>
)}
{indicator && <Indicator size={size} state={indicator} />}
</Content>
</Base> </Base>
) )
} }

View File

@ -6,7 +6,6 @@ export type Variants = VariantProps<typeof Base>
export const Base = styled('div', { export const Base = styled('div', {
position: 'relative', position: 'relative',
background: '$primary-1',
borderRadius: '100%', borderRadius: '100%',
flexShrink: 0, flexShrink: 0,
@ -15,39 +14,54 @@ export const Base = styled('div', {
20: { 20: {
width: 20, width: 20,
height: 20, height: 20,
padding: 1,
}, },
24: { 24: {
width: 24, width: 24,
height: 24, height: 24,
padding: 1,
}, },
32: { 32: {
width: 32, width: 32,
height: 32, height: 32,
padding: 2,
}, },
36: { 36: {
width: 36, width: 36,
height: 36, height: 36,
padding: 2,
}, },
44: { 44: {
width: 44, width: 44,
height: 44, height: 44,
padding: 2,
}, },
64: { 64: {
width: 64, width: 64,
height: 64, height: 64,
padding: 3,
}, },
80: { 80: {
width: 80, width: 80,
height: 80, height: 80,
padding: 4,
}, },
120: { 120: {
width: 120, width: 120,
height: 120, height: 120,
padding: 5,
}, },
}, },
}, },
}) })
export const Content = styled('div', {
background: '$primary-1',
borderRadius: '100%',
width: '100%',
height: '100%',
})
export const Indicator = styled('span', { export const Indicator = styled('span', {
position: 'absolute', position: 'absolute',
right: -2, right: -2,

View File

@ -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',
]