Skip to content

Commit

Permalink
fix(clerk-js): Add appearance customization support for avatar gradient
Browse files Browse the repository at this point in the history
* fix(clerk-js): Add customization for avatar gradient from appearance provider

* fix(clerk-js): Refactor types

* fix(clerk-js): Refactor some props in boring avatar

* fix(clerk-js): Eliminate warnings regarding svg attributes

* fix(clerk-js): Prevent deep-merging of arrays in fastDeepMerge

* fix(clerk-js): Fix type issues

* fix(clerk-js): Fix issue with avatar initials color font

* feat(clerk-js): Replace `avatar` with `avatarBox` descriptor

Co-authored-by: Nikos Douvlis <nikosdouvlis@gmail.com>
  • Loading branch information
raptisj and nikosdouvlis authored Oct 13, 2022
1 parent ac8df24 commit 96cde45
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 15 deletions.
14 changes: 11 additions & 3 deletions packages/clerk-js/src/ui/common/BoringAvatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,15 @@ function generateColors(name: string, colors: string[]) {
return elementsProperties;
}

const AvatarMarble = props => {
type AvatarProps = {
colors: string[];
name: string;
square: boolean;
title: boolean;
size: string;
};

const AvatarMarble = (props: AvatarProps) => {
const properties = generateColors(props.name, props.colors);

return (
Expand Down Expand Up @@ -130,10 +138,10 @@ const AvatarMarble = props => {

export const BoringAvatar = ({
colors = ['#92A1C6', '#146A7C', '#F0AB3D', '#C271B4', '#C20D90'],
name = 'Clara Barton',
name = '',
square = false,
title = false,
size = 40,
size = '40px',
...props
}) => {
const avatarProps = { colors, name, title, size, square, ...props };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const APPEARANCE_KEYS = containsAllElementsConfigKeys([
'formFieldInputCopyToClipboardButton',
'formFieldInputCopyToClipboardIcon',

'avatar',
'avatarBox',
'avatarImage',

'userButtonBox',
Expand Down
2 changes: 2 additions & 0 deletions packages/clerk-js/src/ui/customizables/parseVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { colorOptionToHslaAlphaScale, colorOptionToHslaLightnessScale } from './

export const createColorScales = (theme: Theme) => {
const variables = theme.variables || {};

return removeUndefinedProps({
...colorOptionToHslaLightnessScale(variables.colorPrimary, 'primary'),
...colorOptionToHslaLightnessScale(variables.colorDanger, 'danger'),
Expand All @@ -19,6 +20,7 @@ export const createColorScales = (theme: Theme) => {
colorInputText: toHSLA(variables.colorInputText),
colorBackground: toHSLA(variables.colorBackground),
colorInputBackground: toHSLA(variables.colorInputBackground),
colorAvatarGradient: variables.colorAvatarGradient?.length ? variables.colorAvatarGradient.map(toHSLA) : undefined,
});
};

Expand Down
18 changes: 10 additions & 8 deletions packages/clerk-js/src/ui/elements/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const Avatar = (props: AvatarProps) => {
<InitialsAvatarFallback {...props} />
) : (
<Image
elementDescriptor={imageElementDescriptor || descriptors.avatarImage}
elementDescriptor={[imageElementDescriptor, descriptors.avatarImage]}
alt={fullName}
title={fullName}
src={src || ''}
Expand All @@ -66,7 +66,7 @@ export const Avatar = (props: AvatarProps) => {
// TODO: Revise size handling. Do we need to be this dynamic or should we use the theme instead?
return (
<Flex
elementDescriptor={boxElementDescriptor || descriptors.avatar}
elementDescriptor={[boxElementDescriptor, descriptors.avatarBox]}
sx={[
theme => ({
flexShrink: 0,
Expand All @@ -89,8 +89,6 @@ export const Avatar = (props: AvatarProps) => {
);
};

const avatarColors = ['#6C47FF', '#5BC5EF', '#FBD486', '#BEF972', '#FF8F8F'];

function InitialsAvatarFallback(props: AvatarProps) {
const initials = getInitials(props);
const { parsedInternalTheme } = useAppearance();
Expand All @@ -102,14 +100,18 @@ function InitialsAvatarFallback(props: AvatarProps) {
align='center'
>
<BoringAvatar
size={Number(props.size?.(parsedInternalTheme))}
name={`${props.firstName} ${props.lastName}`}
colors={avatarColors}
size={`${props.size?.(parsedInternalTheme)}`}
colors={[...parsedInternalTheme.colors.$colorAvatarGradient]}
/>
{initials && (
<Text
as='span'
sx={{ ...common.centeredFlex('inline-flex'), width: '100%', position: 'absolute' }}
colorScheme='inherit'
sx={{
...common.centeredFlex('inline-flex'),
width: '100%',
position: 'absolute',
}}
>
{initials}
</Text>
Expand Down
1 change: 1 addition & 0 deletions packages/clerk-js/src/ui/foundations/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const colors = Object.freeze({
...whiteAlpha,
colorBackground: 'white',
colorInputBackground: 'white',
colorAvatarGradient: ['#6C47FF', '#5BC5EF', '#FBD486', '#BEF972', '#FF8F8F'],
colorText: 'black',
colorTextOnPrimaryBackground: 'white',
colorTextSecondary: 'rgba(0,0,0,0.65)',
Expand Down
14 changes: 14 additions & 0 deletions packages/clerk-js/src/ui/utils/fastDeepMerge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ describe('fastDeepMergeReplace', () => {
fastDeepMergeAndReplace(source, target);
expect(target).toEqual({ a: '1', b: '2', c: '3', obj: { a: '1', b: '2' } });
});

it('does not deep-merge arrays', () => {
const source = { obj: { a: 1 }, arr: [1, 2, 3] };
const target = { obj: { b: 2 }, arr: [1, 2, 3, 4, 5, 6] };
fastDeepMergeAndReplace(source, target);
expect(target).toEqual({ obj: { a: 1, b: 2 }, arr: [1, 2, 3] });
});
});

describe('fastDeepMergeKeep', () => {
Expand Down Expand Up @@ -58,4 +65,11 @@ describe('fastDeepMergeKeep', () => {
fastDeepMergeAndKeep(source, target);
expect(target).toEqual({ a: '10', b: '2', c: '3', obj: { a: '10', b: '20' } });
});

it('does not deep-merge arrays', () => {
const source = { obj: { a: 1 }, arr: [1, 2, 3] };
const target = { obj: { b: 2 }, arr: [1, 2, 3, 4, 5, 6] };
fastDeepMergeAndKeep(source, target);
expect(target).toEqual({ obj: { a: 1, b: 2 }, arr: [1, 2, 3, 4, 5, 6] });
});
});
6 changes: 4 additions & 2 deletions packages/clerk-js/src/ui/utils/fastDeepMerge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export const fastDeepMergeAndReplace = (
}

for (const key in source) {
if (source[key] !== null && typeof source[key] === `object`) {
// Deep merge objects but shallow-copy arrays
if (source[key] !== null && typeof source[key] === `object` && !Array.isArray(source[key])) {
if (target[key] === undefined) {
target[key] = new (Object.getPrototypeOf(source[key]).constructor)();
}
Expand All @@ -32,7 +33,8 @@ export const fastDeepMergeAndKeep = (
}

for (const key in source) {
if (source[key] !== null && typeof source[key] === `object`) {
// Deep merge objects but shallow-copy arrays
if (source[key] !== null && typeof source[key] === `object` && !Array.isArray(source[key])) {
if (target[key] === undefined) {
target[key] = new (Object.getPrototypeOf(source[key]).constructor)();
}
Expand Down
9 changes: 8 additions & 1 deletion packages/types/src/appearance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ export type ElementsConfig = {
formFieldInputCopyToClipboardButton: WithOptions<never, never, never>;
formFieldInputCopyToClipboardIcon: WithOptions<never, never, never>;

avatar: WithOptions<never, never, never>;
avatarBox: WithOptions<never, never, never>;
avatarImage: WithOptions<never, never, never>;

// TODO: We can remove "Popover" from these:
Expand Down Expand Up @@ -361,6 +361,13 @@ export type Variables = {
* The background color for the card container.
*/
colorBackground?: CssColor;

/*
* If a user hasn't provided an avatar image, a colorful gradient avatar will be shown as fallback.
* To customise the gradient,pass an array of CSS colors.
* @default ['#6C47FF', '#5BC5EF', '#FBD486', '#BEF972', '#FF8F8F'];
*/
colorAvatarGradient?: CssColor[];
/**
* The default text color inside input elements. To customise the input background color instead, use {@link Variables.colorInputBackground}.
* @default The value of {@link Variables.colorText}
Expand Down

0 comments on commit 96cde45

Please sign in to comment.