Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add random and randompalette prop #87

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 37 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ import Avatar from 'boring-avatars';

### Props

| Prop | Type | Default |
|---------|--------------------------------------------------------------|-----------------------------------------------------------|
| size | number or string | `40px` |
| square | boolean | `false` |
| title | boolean | `false` |
| name | string | `Clara Barton` |
| variant | oneOf: `marble`, `beam`, `pixel`,`sunset`, `ring`, `bauhaus` | `marble` |
| colors | array | `['#92A1C6', '#146A7C', '#F0AB3D', '#C271B4', '#C20D90']` |
| Prop | Type | Default |
|----------------|--------------------------------------------------------------|-----------------------------------------------------------|
| size | number or string | `40px` |
| square | boolean | `false` |
| title | boolean | `false` |
| name | string | `""` |
| variant | oneOf: `marble`, `beam`, `pixel`,`sunset`, `ring`, `bauhaus` | `marble` |
| colors | array | `['#92A1C6', '#146A7C', '#F0AB3D', '#C271B4', '#C20D90']` |
| random | boolean | `false` |
| randompalette | boolean | `false` |


#### Name
Expand Down Expand Up @@ -68,6 +70,33 @@ The `square` prop is used to make the avatar square.
<Avatar name="Helen Keller" square/>
```

#### Random
The `random` prop is used to generate the avatar randomly, independent of the name.

```jsx
<Avatar name="Clara Barton" random/>
```

Or you can leave the name empty.

```jsx
<Avatar name=""/>
```

Or you can not use it at all.

```jsx
<Avatar />
```

#### Random Palette

The `randompalette` prop is used to change the color palette of the avatar with a random color palette.

```jsx
<Avatar name="Lucy Stone" randompalette/>
```

## API service

> [!IMPORTANT]
Expand Down
2 changes: 2 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ declare module 'boring-avatars' {
square?: boolean;
variant?: 'marble' | 'beam' | 'pixel' | 'sunset' | 'ring' | 'bauhaus';
colors?: string[];
random?: boolean;
randompalette?: boolean;
[key: string]: any; // Allows any additional prop
}

Expand Down
6 changes: 5 additions & 1 deletion src/demo/playground.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const Input = styled.input`
}
`;

const AvatarWrapper = ({ name, playgroundColors, size, square, variant }) => {
const AvatarWrapper = ({ name, playgroundColors, size, square, variant, random }) => {
const [avatarName, setAvatarName] = useState(name);
const handleFocus = (event) => event.target.select();
const ref = useRef();
Expand All @@ -96,6 +96,7 @@ const AvatarWrapper = ({ name, playgroundColors, size, square, variant }) => {
size={size}
variant={variants[variant]}
square={square}
random={random}
/>
</AvatarSection>
<Input
Expand Down Expand Up @@ -183,6 +184,7 @@ const Playground = () => {
const [avatarSize, setAvatarSize] = useState(avatarSizes.medium);
const [variant, setVariant] = useState(variants.beam);
const [isSquare, setSquare] = useState(false);
const [isRandom, setRandom] = useState(false);

return (
<>
Expand Down Expand Up @@ -223,6 +225,7 @@ const Playground = () => {

<Button onClick={() => handleRandomColors()}>Random palette</Button>
<Button onClick={() => setSquare(!isSquare)}>{isSquare ? 'Round' : 'Square'}</Button>
<Button onClick={() => setRandom(!isRandom)}>{isRandom ? 'Random' : 'By Name'}</Button>
<SegmentGroup>
{Object.entries(avatarSizes).map(([key, value], index) => (
<SizeDot
Expand All @@ -243,6 +246,7 @@ const Playground = () => {
name={exampleName}
playgroundColors={filteredColors}
variant={variant}
random={isRandom}
/>
))}
</AvatarsGrid>
Expand Down
16 changes: 12 additions & 4 deletions src/lib/components/avatar-bauhaus.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { hashCode, getUnit, getRandomColor, getBoolean } from '../utilities';
import palettes from 'nice-color-palettes/1000';
import { hashCode, getUnit, getRandomColor, getBoolean, getRandomStr, getRandomPalette } from '../utilities';

const ELEMENTS = 4;
const SIZE = 80;
Expand All @@ -20,8 +21,15 @@ function generateColors(name, colors) {
}

const AvatarBauhaus = (props) => {
const { name, colors, title, square, size, ...otherProps } = props;
const properties = generateColors(name, colors);
const { name, colors, title, square, size, random, randompalette, ...otherProps } = props;
const recalculate = random || !name;
const randomStr = React.useMemo(() => {
return recalculate ? getRandomStr() : '';
}, [recalculate]);
const randomPlt = React.useMemo(() => {
return randompalette ? getRandomPalette(palettes) : [];
}, [randompalette]);
const properties = generateColors(recalculate ? randomStr : name, randompalette ? randomPlt : colors);
const maskID = React.useId();

return (
Expand All @@ -34,7 +42,7 @@ const AvatarBauhaus = (props) => {
height={size}
{...otherProps}
>
{title && <title>{name}</title>}
{title && name && <title>{name}</title>}
<mask id={maskID} maskUnits="userSpaceOnUse" x={0} y={0} width={SIZE} height={SIZE}>
<rect width={SIZE} height={SIZE} rx={square ? undefined : SIZE * 2} fill="#FFFFFF" />
</mask>
Expand Down
16 changes: 12 additions & 4 deletions src/lib/components/avatar-beam.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { hashCode, getUnit, getBoolean, getRandomColor, getContrast } from '../utilities';
import palettes from 'nice-color-palettes/1000';
import { hashCode, getUnit, getBoolean, getRandomColor, getContrast, getRandomStr, getRandomPalette } from '../utilities';

const SIZE = 36;

Expand Down Expand Up @@ -35,8 +36,15 @@ function generateData(name, colors) {
}

const AvatarBeam = (props) => {
const { name, colors, title, square, size, ...otherProps } = props;
const data = generateData(name, colors);
const { name, colors, title, square, size, random, randompalette, ...otherProps } = props;
const recalculate = random || !name;
const randomStr = React.useMemo(() => {
return recalculate ? getRandomStr() : '';
}, [recalculate]);
const randomPlt = React.useMemo(() => {
return randompalette ? getRandomPalette(palettes) : [];
}, [randompalette]);
const data = generateData(recalculate ? randomStr : name, randompalette ? randomPlt : colors);
const maskID = React.useId();

return (
Expand All @@ -49,7 +57,7 @@ const AvatarBeam = (props) => {
height={size}
{...otherProps}
>
{title && <title>{name}</title>}
{title && name && <title>{name}</title>}
<mask id={maskID} maskUnits="userSpaceOnUse" x={0} y={0} width={SIZE} height={SIZE}>
<rect width={SIZE} height={SIZE} rx={square ? undefined : SIZE * 2} fill="#FFFFFF" />
</mask>
Expand Down
16 changes: 12 additions & 4 deletions src/lib/components/avatar-marble.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { hashCode, getUnit, getRandomColor } from '../utilities';
import palettes from 'nice-color-palettes/1000';
import { hashCode, getUnit, getRandomColor, getRandomStr, getRandomPalette } from '../utilities';

const ELEMENTS = 3;
const SIZE = 80;
Expand All @@ -20,8 +21,15 @@ function generateColors(name, colors) {
}

const AvatarMarble = (props) => {
const { name, colors, title, square, size, ...otherProps } = props;
const properties = generateColors(name, colors);
const { name, colors, title, square, size, random, randompalette, ...otherProps } = props;
const recalculate = random || !name;
const randomStr = React.useMemo(() => {
return recalculate ? getRandomStr() : '';
}, [recalculate]);
const randomPlt = React.useMemo(() => {
return randompalette ? getRandomPalette(palettes) : [];
}, [randompalette]);
const properties = generateColors(recalculate ? randomStr : name, randompalette ? randomPlt : colors);
const maskID = React.useId();

return (
Expand All @@ -34,7 +42,7 @@ const AvatarMarble = (props) => {
height={size}
{...otherProps}
>
{title && <title>{name}</title>}
{title && name && <title>{name}</title>}
<mask id={maskID} maskUnits="userSpaceOnUse" x={0} y={0} width={SIZE} height={SIZE}>
<rect width={SIZE} height={SIZE} rx={square ? undefined : SIZE * 2} fill="#FFFFFF" />
</mask>
Expand Down
16 changes: 12 additions & 4 deletions src/lib/components/avatar-pixel.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { hashCode, getRandomColor } from '../utilities';
import palettes from 'nice-color-palettes/1000';
import { hashCode, getRandomColor, getRandomStr, getRandomPalette } from '../utilities';

const ELEMENTS = 64;
const SIZE = 80;
Expand All @@ -16,8 +17,15 @@ function generateColors(name, colors) {
}

const AvatarPixel = (props) => {
const { name, colors, title, square, size, ...otherProps } = props;
const pixelColors = generateColors(name, colors);
const { name, colors, title, square, size, random, randompalette, ...otherProps } = props;
const recalculate = random || !name;
const randomStr = React.useMemo(() => {
return recalculate ? getRandomStr() : '';
}, [recalculate]);
const randomPlt = React.useMemo(() => {
return randompalette ? getRandomPalette(palettes) : [];
}, [randompalette]);
const pixelColors = generateColors(recalculate ? randomStr : name, randompalette ? randomPlt : colors);
const maskID = React.useId();

return (
Expand All @@ -30,7 +38,7 @@ const AvatarPixel = (props) => {
height={size}
{...otherProps}
>
{title && <title>{name}</title>}
{title && name && <title>{name}</title>}
<mask
id={maskID}
mask-type="alpha"
Expand Down
16 changes: 12 additions & 4 deletions src/lib/components/avatar-ring.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { hashCode, getRandomColor } from '../utilities';
import palettes from 'nice-color-palettes/1000';
import { hashCode, getRandomColor, getRandomStr, getRandomPalette } from '../utilities';

const SIZE = 90;
const COLORS = 5;
Expand All @@ -25,8 +26,15 @@ function generateColors(colors, name) {
}

const AvatarRing = (props) => {
const { name, colors, title, square, size, ...otherProps } = props;
const ringColors = generateColors(colors, name);
const { name, colors, title, square, size, random, randompalette, ...otherProps } = props;
const recalculate = random || !name;
const randomStr = React.useMemo(() => {
return recalculate ? getRandomStr() : '';
}, [recalculate]);
const randomPlt = React.useMemo(() => {
return randompalette ? getRandomPalette(palettes) : [];
}, [randompalette]);
const ringColors = generateColors(randompalette ? randomPlt : colors, recalculate ? randomStr : name);
const maskID = React.useId();

return (
Expand All @@ -39,7 +47,7 @@ const AvatarRing = (props) => {
height={size}
{...otherProps}
>
{title && <title>{name}</title>}
{title && name && <title>{name}</title>}
<mask id={maskID} maskUnits="userSpaceOnUse" x={0} y={0} width={SIZE} height={SIZE}>
<rect width={SIZE} height={SIZE} rx={square ? undefined : SIZE * 2} fill="#FFFFFF" />
</mask>
Expand Down
25 changes: 16 additions & 9 deletions src/lib/components/avatar-sunset.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { hashCode, getRandomColor } from '../utilities';
import palettes from 'nice-color-palettes/1000';
import { hashCode, getRandomColor, getRandomStr, getRandomPalette } from '../utilities';

const ELEMENTS = 4;
const SIZE = 80;
Expand All @@ -16,9 +17,15 @@ function generateColors(name, colors) {
}

const AvatarSunset = (props) => {
const { name, colors, title, square, size, ...otherProps } = props;
const sunsetColors = generateColors(name, colors);
const nameWithoutSpace = name.replace(/\s/g, '');
const { name, colors, title, square, size, random, randompalette, ...otherProps } = props;
const recalculate = random || !name;
const randomStr = React.useMemo(() => {
return recalculate ? getRandomStr() : '';
}, [recalculate]);
const randomPlt = React.useMemo(() => {
return randompalette ? getRandomPalette(palettes) : [];
}, [randompalette]);
const sunsetColors = generateColors(recalculate ? randomStr : name, randompalette ? randomPlt : colors);
const maskID = React.useId();

return (
Expand All @@ -31,17 +38,17 @@ const AvatarSunset = (props) => {
height={size}
{...otherProps}
>
{title && <title>{name}</title>}
{title && name && <title>{name}</title>}
<mask id={maskID} maskUnits="userSpaceOnUse" x={0} y={0} width={SIZE} height={SIZE}>
<rect width={SIZE} height={SIZE} rx={square ? undefined : SIZE * 2} fill="#FFFFFF" />
</mask>
<g mask={`url(#${maskID})`}>
<path fill={'url(#gradient_paint0_linear_' + nameWithoutSpace + ')'} d="M0 0h80v40H0z" />
<path fill={'url(#gradient_paint1_linear_' + nameWithoutSpace + ')'} d="M0 40h80v40H0z" />
<path fill={`url(#gradient_paint0_linear_${maskID})`} d="M0 0h80v40H0z" />
<path fill={`url(#gradient_paint1_linear_${maskID})`} d="M0 40h80v40H0z" />
</g>
<defs>
<linearGradient
id={'gradient_paint0_linear_' + nameWithoutSpace}
id={`gradient_paint0_linear_${maskID}`}
x1={SIZE / 2}
y1={0}
x2={SIZE / 2}
Expand All @@ -52,7 +59,7 @@ const AvatarSunset = (props) => {
<stop offset={1} stopColor={sunsetColors[1]} />
</linearGradient>
<linearGradient
id={'gradient_paint1_linear_' + nameWithoutSpace}
id={`gradient_paint1_linear_${maskID}`}
x1={SIZE / 2}
y1={SIZE / 2}
x2={SIZE / 2}
Expand Down
8 changes: 7 additions & 1 deletion src/lib/components/avatar.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ const DEPRECATED_VARIANTS = {
const Avatar = ({
variant = 'marble',
colors = ['#92A1C6', '#146A7C', '#F0AB3D', '#C271B4', '#C20D90'],
name = 'Clara Barton',
name = '',
title = false,
size,
square = false,
random = false,
randompalette = false,
...otherProps
}) => {
const resolvedVariant = DEPRECATED_VARIANTS[variant] || variant;
Expand All @@ -40,6 +42,8 @@ const Avatar = ({
title={title}
size={size}
square={square}
random={random}
randompalette={randompalette}
{...otherProps}
/>
);
Expand All @@ -51,6 +55,8 @@ Avatar.propTypes = {
name: PropTypes.string,
square: PropTypes.bool,
title: PropTypes.bool,
random: PropTypes.bool,
randompalette: PropTypes.bool,
};

export default Avatar;
13 changes: 13 additions & 0 deletions src/lib/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,16 @@ export const getContrast = (hexcolor) => {
return (yiq >= 128) ? '#000000' : '#FFFFFF';

};

export const getRandomStr = (length = 6) => {
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
let result = '';
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
return result;
}

export const getRandomPalette = (palettes) => {
return palettes[Math.floor(Math.random() * palettes.length)];
}