Skip to content
Merged
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
8 changes: 8 additions & 0 deletions src/components/App.res
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ let make = (
selectedColor: styles.skinColor,
selectedStyle: styles.nose,
},
{
id: #Accessories,
label: "ACCESSORIES",
colors: config.accessoryColors,
styles: config.accessoryStyles,
selectedColor: styles.accessoriesColor,
selectedStyle: styles.accessories,
},
{
id: #Background,
label: "BACKGROUND",
Expand Down
1 change: 0 additions & 1 deletion src/components/AvatarGenerator.css
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,3 @@
margin-bottom: 48px;
}
}

3 changes: 3 additions & 0 deletions src/components/AvatarGenerator.res
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

let getZIndex = (id: Types.id) =>
switch id {
| #Accessories => "115"
| #Eyes => "110"
| #Nose => "100"
| #FacialHair => "90"
Expand Down Expand Up @@ -72,6 +73,7 @@ let make = (~randomize, ~settings: array<Types.setting>, ~onChange, ~onExport) =
| #Hair => #HairColor
| #FacialHair => #FacialHairColor
| #Body => #BodyColor
| #Accessories => #AccessoriesColor
| #Background => #BackgroundColor
| _ => Js.Exn.raiseError("ColorNotFound: " ++ (o.id :> string))
}
Expand All @@ -87,6 +89,7 @@ let make = (~randomize, ~settings: array<Types.setting>, ~onChange, ~onExport) =
| #Eyes => #EyesStyle
| #Mouth => #MouthStyle
| #Nose => #NoseStyle
| #Accessories => #AccessoriesStyle
| _ => Js.Exn.raiseError("StyleNotFound: " ++ (o.id :> string))
}
onChange(key, style)
Expand Down
3 changes: 1 addition & 2 deletions src/components/Modal.res
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ let make = (~visible, ~onToggle) => {
target="_blank"
rel="no-follow"
href={"https://twitter.com/intent/tweet?text=I+made+this+avatar+with+Personas+by+@Draftbit&url=" ++
Js.Global.encodeURIComponent(locationHref) ++
"&related=draftbit"}
Js.Global.encodeURIComponent(locationHref) ++ "&related=draftbit"}
className="Modal-button Modal-button--twitter">
<img className="Modal-shareIcon" width="16" height="16" src="/images/twitter.svg" />
<span> {React.string("Twitter")} </span>
Expand Down
66 changes: 66 additions & 0 deletions src/components/SvgLoader.res
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,58 @@ let getSidebuzz = (fill, size) =>
let getStraightbun = (fill, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><g fill="none"><path fill="${fill}" d="M22.2 17.002c-.131-.647-.2-1.316-.2-2.002 0-5.523 4.477-10 10-10s10 4.477 10 10c0 .686-.069 1.355-.2 2.002C39.274 14.526 35.815 13 32 13s-7.274 1.526-9.8 4.002z"/><path fill="#f55d81" d="M45.934 25.632C43.828 20.564 38.83 17 33 17h-2c-5.83 0-10.828 3.564-12.934 8.632C18.753 18.542 24.73 13 32 13s13.247 5.542 13.934 12.632z"/></g></svg>`

/* --- 2026 expansion: eyes --- */

let getEyesClosed = (_, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><path fill="#1b0640" d="M24.712 27.263a.75.75 0 1 0-1.424.474c.434 1.301 1.383 2.013 2.712 2.013s2.278-.712 2.712-2.013a.75.75 0 1 0-1.424-.474c-.233.699-.617.987-1.288.987s-1.055-.288-1.288-.987zm12 0a.75.75 0 0 0-1.424.474c.434 1.301 1.383 2.013 2.712 2.013s2.278-.712 2.712-2.013a.75.75 0 0 0-1.424-.474c-.233.699-.617.987-1.288.987s-1.055-.288-1.288-.987z"/></svg>`

let getEyesHearts = (_, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><path fill="#f55d81" d="M25.5 31c-2.1-1.5-3.2-2.6-3.2-3.9 0-1 .8-1.8 1.8-1.8.55 0 1.05.25 1.4.7.35-.45.85-.7 1.4-.7 1 0 1.8.8 1.8 1.8 0 1.3-1.1 2.4-3.2 3.9zm13 0c-2.1-1.5-3.2-2.6-3.2-3.9 0-1 .8-1.8 1.8-1.8.55 0 1.05.25 1.4.7.35-.45.85-.7 1.4-.7 1 0 1.8.8 1.8 1.8 0 1.3-1.1 2.4-3.2 3.9z"/></svg>`

let getEyesDizzy = (_, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><g stroke="#1b0640" stroke-width="1.5" stroke-linecap="round"><path d="m24 27 3.5 3.5m0-3.5L24 30.5m10.5-3.5 3.5 3.5m0-3.5-3.5 3.5"/></g></svg>`

let getEyesSideeye = (_, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><g fill="none"><path fill="#fff" d="M28.5 28.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0zm13 0a3 3 0 1 1-6 0 3 3 0 0 1 6 0z"/><path fill="#1b0640" d="M28.4 28.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm13 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/></g></svg>`

/* --- 2026 expansion: mouths --- */

let getMouthGrin = (_, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><g fill="none"><path fill="#1b0640" d="M26.5 38.5h11a5.5 5.5 0 0 1-11 0z"/><path fill="#fff" d="M27.6 39.5h8.8v.8a1.4 1.4 0 0 1-1.4 1.4h-6a1.4 1.4 0 0 1-1.4-1.4z"/></g></svg>`

let getMouthTongue = (_, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><g fill="none"><path fill="#1b0640" d="M28.004 39.868a1 1 0 0 1 .992-1.736c1.02.583 2.018.868 3.004.868s1.983-.285 3.004-.868a1 1 0 1 1 .992 1.736C34.684 40.618 33.348 41 32 41c-1.348 0-2.684-.382-3.996-1.132z"/><path fill="#f57b98" d="M30 40.6c.66.27 1.33.4 2 .4s1.34-.13 2-.4v1.4a2 2 0 0 1-4 0z"/></g></svg>`

let getMouthWhistle = (_, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><ellipse fill="#1b0640" cx="33" cy="40.3" rx="1.7" ry="2.1"/></svg>`

let getMouthLaugh = (_, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><g fill="none"><path fill="#1b0640" d="M27 38h10c0 3.6-2.2 6-5 6s-5-2.4-5-6z"/><path fill="#f57b98" d="M29.3 42.8c.76.76 1.68 1.2 2.7 1.2s1.94-.44 2.7-1.2c-.7-.95-1.63-1.5-2.7-1.5s-2 .55-2.7 1.5z"/></g></svg>`

/* --- 2026 expansion: noses --- */

let getNosePointed = (fill, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><g fill="none"><path fill="${fill}" d="M31.13 31.5a1 1 0 0 1 1.74 0l2.6 4.55a1 1 0 0 1-.87 1.5h-5.2a1 1 0 0 1-.87-1.5z"/><path style="mix-blend-mode: overlay" fill="#fff" d="M32 31l2.6 4.55a1 1 0 0 1-.87 1.5H32z" opacity=".36"/></g></svg>`

let getNoseButton = (fill, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><g fill="none"><circle fill="${fill}" cx="32" cy="35.3" r="2.3"/><path style="mix-blend-mode: overlay" fill="#fff" d="M32 33a2.3 2.3 0 0 1 0 4.6z" opacity=".36"/></g></svg>`

/* --- 2026 expansion: bodies --- */

let getBodyHoodie = (fill, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><g fill="none"><path fill="${fill}" d="M27 51v.47a5 5 0 0 0 10 0V51c7.063 1.523 12.93 6.735 16 13H11c3.07-6.265 8.937-11.477 16-13z"/><path fill="#000" opacity=".18" d="M23.5 52.2c2.2 3.1 5.1 4.8 8.5 4.8s6.3-1.7 8.5-4.8l2.6 1c-2.5 4-6.4 6.2-11.1 6.2s-8.6-2.2-11.1-6.2z"/><path stroke="#fff" stroke-width="1.2" stroke-linecap="round" opacity=".8" d="M29.5 58.5v4m5-4v4"/></g></svg>`

let getBodyStripes = (fill, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><defs><path id="stripes-body" d="M27 51v.47a5 5 0 0 0 10 0V51c7.063 1.523 12.93 6.735 16 13H11c3.07-6.265 8.937-11.477 16-13z"/><clipPath id="stripes-clip"><use href="#stripes-body"/></clipPath></defs><g fill="none"><use fill="${fill}" href="#stripes-body"/><g clip-path="url(#stripes-clip)" fill="#fff" opacity=".4"><rect x="10" y="54" width="44" height="2.4"/><rect x="10" y="59" width="44" height="2.4"/></g></g></svg>`

/* --- 2026 expansion: accessories --- */

let getEarring = (fill, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><circle cx="17" cy="37.5" r="1.7" fill="none" stroke="${fill}" stroke-width="1.3"/></svg>`

let getEarrings = (fill, size) =>
`<svg width="${size}" height="${size}" viewBox="0 0 64 64"><g fill="none" stroke="${fill}" stroke-width="1.3"><circle cx="17" cy="37.5" r="1.7"/><circle cx="47" cy="37.5" r="1.7"/></g></svg>`

@react.component
let make = (~style=?, ~className="", ~name, ~fill="#000", ~size="64") => {
let getHtml = name =>
Expand Down Expand Up @@ -231,6 +283,20 @@ let make = (~style=?, ~className="", ~name, ~fill="#000", ~size="64") => {
| "Sidebuzz" => getSidebuzz(fill, size)
| "Straightbun" => getStraightbun(fill, size)
| "Background" => getBackground(fill, size)
| "Closed" => getEyesClosed(fill, size)
| "Hearts" => getEyesHearts(fill, size)
| "Dizzy" => getEyesDizzy(fill, size)
| "Sideeye" => getEyesSideeye(fill, size)
| "Grin" => getMouthGrin(fill, size)
| "Tongue" => getMouthTongue(fill, size)
| "Whistle" => getMouthWhistle(fill, size)
| "Laugh" => getMouthLaugh(fill, size)
| "Pointed" => getNosePointed(fill, size)
| "Button" => getNoseButton(fill, size)
| "Hoodie" => getBodyHoodie(fill, size)
| "Stripes" => getBodyStripes(fill, size)
| "Earring" => getEarring(fill, size)
| "Earrings" => getEarrings(fill, size)
| _ => ""
}

Expand Down
7 changes: 7 additions & 0 deletions src/components/Types.res
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type id = [
| #Eyes
| #Mouth
| #Nose
| #Accessories
| #Background
| #Head
]
Expand All @@ -15,6 +16,7 @@ type color = [
| #HairColor
| #FacialHairColor
| #BodyColor
| #AccessoriesColor
| #BackgroundColor
]

Expand All @@ -26,6 +28,7 @@ type style = [
| #EyesStyle
| #MouthStyle
| #NoseStyle
| #AccessoriesStyle
]

type key = [color | style]
Expand All @@ -42,6 +45,8 @@ type styles = {
eyes: string,
mouth: string,
nose: string,
accessories: string,
accessoriesColor: string,
bgColor: string,
head: string,
}
Expand All @@ -60,6 +65,7 @@ type config = {
hairColors: array<string>,
facialHairColors: array<string>,
bodyColors: array<string>,
accessoryColors: array<string>,
bgColors: array<string>,
disabledColors: array<string>,
skinStyles: array<string>,
Expand All @@ -69,5 +75,6 @@ type config = {
eyeStyles: array<string>,
mouthStyles: array<string>,
noseStyles: array<string>,
accessoryStyles: array<string>,
bgStyles: array<string>,
}
4 changes: 1 addition & 3 deletions src/components/Wordmark.res
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ let utmHref = (placement: string) =>

@react.component
let make = (~placement: string) =>
<a
href={utmHref(placement)}
title="Robust native front-end apps with usable code by Draftbit">
<a href={utmHref(placement)} title="Robust native front-end apps with usable code by Draftbit">
<Icon name="wordmark" />
</a>
44 changes: 37 additions & 7 deletions src/data/config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"skinStyles": ["Skin"],
"skinStyles": [
"Skin"
],
"hairStyles": [
"Bald",
"Hat",
Expand Down Expand Up @@ -36,15 +38,21 @@
"Oval",
"Round",
"Square",
"Checkered"
"Checkered",
"Hoodie",
"Stripes"
],
"eyeStyles": [
"Glasses",
"Happy",
"Open",
"Sleepy",
"Sunglasses",
"Wink"
"Wink",
"Closed",
"Hearts",
"Dizzy",
"Sideeye"
],
"mouthStyles": [
"Bigsmile",
Expand All @@ -53,14 +61,27 @@
"Pacifier",
"Smile",
"Smirk",
"Surprise"
"Surprise",
"Grin",
"Tongue",
"Whistle",
"Laugh"
],
"noseStyles": [
"Mediumround",
"Smallround",
"Wrinkles"
"Wrinkles",
"Pointed",
"Button"
],
"accessoryStyles": [
"None",
"Earring",
"Earrings"
],
"bgStyles": [
"Background"
],
"bgStyles": ["Background"],
"skinColors": [
"FFCC22",
"FFDFC4",
Expand Down Expand Up @@ -117,6 +138,16 @@
"C866D9",
"68C9F2"
],
"accessoryColors": [
"F3B63A",
"C9CFDB",
"C98850",
"362C47",
"F55D81",
"54D7C7",
"456DFF",
"5A45FF"
],
"bgColors": [
"93A7FF",
"A9E775",
Expand All @@ -142,4 +173,3 @@
"EEEFF5"
]
}

2 changes: 2 additions & 0 deletions src/helpers/shareUrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ const STYLE_KEYS = [
["eyes", "eyeStyles"],
["mouth", "mouthStyles"],
["nose", "noseStyles"],
["accessories", "accessoryStyles"],
];

const COLOR_KEYS = [
"skinColor",
"hairColor",
"facialHairColor",
"bodyColor",
"accessoriesColor",
"bgColor",
];

Expand Down
4 changes: 4 additions & 0 deletions src/pages/Index.res
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ let randomizeStyles = (config: Types.config): Types.styles => {
eyes: getRandom(config.eyeStyles),
mouth: getRandom(config.mouthStyles),
nose: getRandom(config.noseStyles),
accessories: Js.Math.random() < 0.6 ? "None" : getRandom(config.accessoryStyles),
accessoriesColor: getRandom(config.accessoryColors),
bgColor: getRandom(config.bgColors),
head: "Head",
}
Expand Down Expand Up @@ -57,6 +59,8 @@ let make = () => {
| #EyesStyle => {...styles, eyes: value}
| #MouthStyle => {...styles, mouth: value}
| #NoseStyle => {...styles, nose: value}
| #AccessoriesStyle => {...styles, accessories: value}
| #AccessoriesColor => {...styles, accessoriesColor: value}
| #BackgroundColor => {...styles, bgColor: value}
}
)
Expand Down