From 58d311cc678d21b63cea8c1928a57137952ce029 Mon Sep 17 00:00:00 2001 From: Toppanto Bence Date: Mon, 28 Apr 2025 13:30:18 +0200 Subject: [PATCH 1/2] feat(ui-themes,shared-types): add new primitive and contrast colors --- packages/shared-types/src/Colors.ts | 28 +++++++++++++++++++ .../sharedThemeTokens/colors/primitives.ts | 24 +++++++++++++++- .../ui-themes/src/themes/canvas/colors.ts | 8 +++++- .../src/themes/canvasHighContrast/colors.ts | 8 +++++- 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/packages/shared-types/src/Colors.ts b/packages/shared-types/src/Colors.ts index 1e916366a1..337ebbb8e1 100644 --- a/packages/shared-types/src/Colors.ts +++ b/packages/shared-types/src/Colors.ts @@ -63,6 +63,28 @@ type Primitives = { red57: string red70: string red82: string + + sea12: string + sea30: string + sea45: string + sea70: string + sea110: string + sea35: string + sea40: string + sea50: string + sea57: string + sea90: string + + violet12: string + violet30: string + violet45: string + violet70: string + violet110: string + violet35: string + violet40: string + violet50: string + violet57: string + violet90: string } type AdditionalPrimitives = { @@ -219,6 +241,12 @@ type Contrasts = { red1212: Primitives['red12'] red4570: Primitives['red45'] | Primitives['red70'] red5782: Primitives['red57'] | Primitives['red82'] + + violet1212: Primitives['violet12'] + violet4570: Primitives['violet45'] | Primitives['violet70'] + violet5790: Primitives['violet57'] | Primitives['violet90'] + sea4570: Primitives['sea45'] | Primitives['sea70'] + sea5790: Primitives['sea57'] | Primitives['sea90'] } type UI = { diff --git a/packages/ui-themes/src/sharedThemeTokens/colors/primitives.ts b/packages/ui-themes/src/sharedThemeTokens/colors/primitives.ts index 6476cd9a4b..b7e30d5311 100644 --- a/packages/ui-themes/src/sharedThemeTokens/colors/primitives.ts +++ b/packages/ui-themes/src/sharedThemeTokens/colors/primitives.ts @@ -64,7 +64,29 @@ export const primitives: Primitives = { red45: '#E62429', red57: '#C71F23', red70: '#AE1B1F', - red82: '#9B181C' + red82: '#9B181C', + + sea12: '#DAEEEF', + sea30: '#37A1AA', + sea35: '#1E95A0', + sea40: '#0A8C97', + sea45: '#00828E', + sea50: '#007B86', + sea57: '#00717B', + sea70: '#00626B', + sea90: '#005158', + sea110: '#004349', + + violet12: '#F1E6F5', + violet30: '#B57FCC', + violet35: '#AC6FC6', + violet40: '#A564C2', + violet45: '#9E58BD', + violet50: '#994FB9', + violet57: '#9242B4', + violet70: '#7F399E', + violet90: '#682F82', + violet110: '#56276B' } export const additionalPrimitives: AdditionalPrimitives = { diff --git a/packages/ui-themes/src/themes/canvas/colors.ts b/packages/ui-themes/src/themes/canvas/colors.ts index 713bb71cca..26da842d21 100644 --- a/packages/ui-themes/src/themes/canvas/colors.ts +++ b/packages/ui-themes/src/themes/canvas/colors.ts @@ -61,7 +61,13 @@ const contrasts: Contrasts = { red1212: primitives.red12, red4570: primitives.red45, - red5782: primitives.red57 + red5782: primitives.red57, + + violet1212: primitives.violet12, + violet4570: primitives.violet45, + violet5790: primitives.violet57, + sea4570: primitives.sea45, + sea5790: primitives.sea57 } const ui: UI = getUIColors(contrasts) diff --git a/packages/ui-themes/src/themes/canvasHighContrast/colors.ts b/packages/ui-themes/src/themes/canvasHighContrast/colors.ts index f27b18220a..a678f458e2 100644 --- a/packages/ui-themes/src/themes/canvasHighContrast/colors.ts +++ b/packages/ui-themes/src/themes/canvasHighContrast/colors.ts @@ -61,7 +61,13 @@ const contrasts: Contrasts = { red1212: primitives.red12, red4570: primitives.red70, - red5782: primitives.red82 + red5782: primitives.red82, + + violet1212: primitives.violet12, + violet4570: primitives.violet70, + violet5790: primitives.violet90, + sea4570: primitives.sea70, + sea5790: primitives.sea90 } const ui: UI = getUIColors(contrasts) From bb93031731dddfcdc4691f1aa8ab7509407a9215 Mon Sep 17 00:00:00 2001 From: Toppanto Bence Date: Wed, 14 May 2025 19:20:32 +0200 Subject: [PATCH 2/2] feat(ui-avatar,shared-types): add new ai color variant --- .../src/ComponentThemeVariables.ts | 22 +-- packages/ui-avatar/src/Avatar/README.md | 124 ++++++++------- packages/ui-avatar/src/Avatar/props.ts | 4 +- packages/ui-avatar/src/Avatar/styles.ts | 141 ++++++++++++++---- packages/ui-avatar/src/Avatar/theme.ts | 6 +- 5 files changed, 201 insertions(+), 96 deletions(-) diff --git a/packages/shared-types/src/ComponentThemeVariables.ts b/packages/shared-types/src/ComponentThemeVariables.ts index 1ebafa179d..5af3c1cf81 100644 --- a/packages/shared-types/src/ComponentThemeVariables.ts +++ b/packages/shared-types/src/ComponentThemeVariables.ts @@ -66,21 +66,25 @@ export type AlertTheme = { } export type AvatarTheme = { - background: Colors['contrasts']['white1010'] + background: string borderWidthSmall: Border['widthSmall'] borderWidthMedium: Border['widthMedium'] - borderColor: Colors['contrasts']['grey1214'] + borderColor: string boxShadowColor: string boxShadowBlur: string fontFamily: Typography['fontFamily'] fontWeight: Typography['fontWeightBold'] - color: Colors['contrasts']['blue4570'] - colorShamrock: Colors['contrasts']['green4570'] - colorBarney: Colors['contrasts']['blue4570'] - colorCrimson: Colors['contrasts']['orange4570'] - colorFire: Colors['contrasts']['red4570'] - colorLicorice: Colors['contrasts']['grey125125'] - colorAsh: Colors['contrasts']['grey4570'] + color: string + colorShamrock: string + colorBarney: string + colorCrimson: string + colorFire: string + colorLicorice: string + colorAsh: string + + aiTopGradientColor: string + aiBottomGradientColor: string + aiFontColor: string } export type BadgeTheme = { diff --git a/packages/ui-avatar/src/Avatar/README.md b/packages/ui-avatar/src/Avatar/README.md index a030d951c7..6b5824fb87 100644 --- a/packages/ui-avatar/src/Avatar/README.md +++ b/packages/ui-avatar/src/Avatar/README.md @@ -14,15 +14,35 @@ type: example readonly: true ---
- - - } margin="0 small 0 0" /> - - + + + } margin="0 space8 0 0" /> + + } shape="rectangle" />
``` +### AI Avatar + +There is a need for special, `ai avatars`. These have a specific look. You can achieve it the following way + +```js +--- +type: example +readonly: true +--- + + + + + + + + + +``` + ### Size The `size` prop allows you to select from `xx-small`, `x-small`, `small`, `medium`, `large`, `x-large`, and `xx-large`. If the `auto` prop is set, the avatar size will adjust according to the font-size @@ -34,30 +54,30 @@ type: example ---
- - - - - - + + + + + + - - - - - - + + + + + + - } size="xx-small" margin="0 small 0 0" /> - } size="x-small" margin="0 small 0 0" /> - } size="small" margin="0 small 0 0" /> - } size="medium" margin="0 small 0 0" /> - } size="large" margin="0 small 0 0" /> - } size="x-large" margin="0 small 0 0" /> + } size="xx-small" margin="0 space8 0 0" /> + } size="x-small" margin="0 space8 0 0" /> + } size="small" margin="0 space8 0 0" /> + } size="medium" margin="0 space8 0 0" /> + } size="large" margin="0 space8 0 0" /> + } size="x-large" margin="0 space8 0 0" /> } size="xx-large" />
@@ -73,21 +93,21 @@ type: example ---
- - - - - - + + + + + + - } name="Arthur C. Clarke" margin="0 small 0 0" /> - } name="James Arias" color="shamrock" margin="0 small 0 0" /> - } name="Charles Kimball" color="barney" margin="0 small 0 0" /> - } name="Melissa Reed" color="crimson" margin="0 small 0 0" /> - } name="Heather Wheeler" color="fire" margin="0 small 0 0" /> - } name="David Herbert" color="licorice" margin="0 small 0 0" /> + } name="Arthur C. Clarke" margin="0 space8 0 0" /> + } name="James Arias" color="shamrock" margin="0 space8 0 0" /> + } name="Charles Kimball" color="barney" margin="0 space8 0 0" /> + } name="Melissa Reed" color="crimson" margin="0 space8 0 0" /> + } name="Heather Wheeler" color="fire" margin="0 space8 0 0" /> + } name="David Herbert" color="licorice" margin="0 space8 0 0" /> } name="Isaac Asimov" color="ash" />
@@ -103,21 +123,21 @@ type: example ---
- - - - - - + + + + + + - } name="Arthur C. Clarke" hasInverseColor margin="0 small 0 0" /> - } name="James Arias" color="shamrock" hasInverseColor margin="0 small 0 0" /> - } name="Charles Kimball" color="barney" hasInverseColor margin="0 small 0 0" /> - } name="Melissa Reed" color="crimson" hasInverseColor margin="0 small 0 0" /> - } name="Heather Wheeler" color="fire" hasInverseColor margin="0 small 0 0" /> - } name="David Herbert" color="licorice" hasInverseColor margin="0 small 0 0" /> + } name="Arthur C. Clarke" hasInverseColor margin="0 space8 0 0" /> + } name="James Arias" color="shamrock" hasInverseColor margin="0 space8 0 0" /> + } name="Charles Kimball" color="barney" hasInverseColor margin="0 space8 0 0" /> + } name="Melissa Reed" color="crimson" hasInverseColor margin="0 space8 0 0" /> + } name="Heather Wheeler" color="fire" hasInverseColor margin="0 space8 0 0" /> + } name="David Herbert" color="licorice" hasInverseColor margin="0 space8 0 0" /> } name="Isaac Asimov" color="ash" hasInverseColor />
@@ -130,9 +150,9 @@ In case you need more control over the color, feel free to use the `themeOverrid type: example ---
- } themeOverride={{ color: '#efb410' }} margin="0 small 0 0" /> - - } hasInverseColor themeOverride={{ color: 'lightblue', background: 'black' }} margin="0 small 0 0" /> + } themeOverride={{ color: '#efb410' }} margin="0 space8 0 0" /> + + } hasInverseColor themeOverride={{ color: 'lightblue', background: 'black' }} margin="0 space8 0 0" />
``` @@ -146,8 +166,8 @@ By default only avatars without an image have borders but you can force it to `a type: example ---
- - } margin="0 small 0 0" showBorder="never"/> + + } margin="0 space8 0 0" showBorder="never"/>
``` diff --git a/packages/ui-avatar/src/Avatar/props.ts b/packages/ui-avatar/src/Avatar/props.ts index 2029bf44d9..8b673376d2 100644 --- a/packages/ui-avatar/src/Avatar/props.ts +++ b/packages/ui-avatar/src/Avatar/props.ts @@ -68,6 +68,7 @@ type AvatarOwnProps = { | 'fire' | 'licorice' | 'ash' + | 'ai' /** * In inverse color mode the background and text/icon colors are inverted */ @@ -139,7 +140,8 @@ const propTypes: PropValidators = { 'crimson', 'fire', 'licorice', - 'ash' + 'ash', + 'ai' ]), hasInverseColor: PropTypes.bool, showBorder: PropTypes.oneOf(['auto', 'always', 'never']), diff --git a/packages/ui-avatar/src/Avatar/styles.ts b/packages/ui-avatar/src/Avatar/styles.ts index bad4f54386..277786006f 100644 --- a/packages/ui-avatar/src/Avatar/styles.ts +++ b/packages/ui-avatar/src/Avatar/styles.ts @@ -51,44 +51,98 @@ const generateStyle = ( const { loaded, size, color, hasInverseColor, shape, src, showBorder } = params + // TODO: this is a temporary solution and should be revised on component update + // NOTE: this is needed due to design changes. The size of the component is calculated from "em" which means it is + // tied to the fontSize. The font sizes changed for the icons, which meant that the container (component) size would've + // changed too without additional calculations + const calcNewScaler = ( + originalFontSize: number, + newFontSize: number, + originalScaler: number + ) => { + return `${(originalFontSize * originalScaler) / newFontSize}em` + } + const sizeStyles = { auto: { fontSize: 'inherit', - borderWidth: componentTheme.borderWidthSmall + borderWidth: componentTheme.borderWidthSmall, + width: '2.5em', + height: '2.5em' }, 'xx-small': { - fontSize: '0.5rem', - borderWidth: componentTheme.borderWidthSmall + fontSize: '0.625rem', + borderWidth: componentTheme.borderWidthSmall, + width: calcNewScaler(0.5, 0.625, shape === 'circle' ? 2.5 : 3), + height: calcNewScaler(0.5, 0.625, 2.5) }, 'x-small': { - fontSize: '0.75rem', - borderWidth: componentTheme.borderWidthSmall + fontSize: '0.875rem', + borderWidth: componentTheme.borderWidthSmall, + width: calcNewScaler(0.75, 0.875, shape === 'circle' ? 2.5 : 3), + height: calcNewScaler(0.75, 0.875, 2.5) }, small: { - fontSize: '1rem', - borderWidth: componentTheme.borderWidthSmall + fontSize: '1.25rem', + borderWidth: componentTheme.borderWidthSmall, + width: calcNewScaler(1, 1.25, shape === 'circle' ? 2.5 : 3), + height: calcNewScaler(1, 1.25, 2.5) }, medium: { - fontSize: '1.25rem', - borderWidth: componentTheme.borderWidthMedium + fontSize: '1.5rem', + borderWidth: componentTheme.borderWidthMedium, + width: calcNewScaler(1.25, 1.5, shape === 'circle' ? 2.5 : 3), + height: calcNewScaler(1.25, 1.5, 2.5) }, large: { - fontSize: '1.5rem', - borderWidth: componentTheme.borderWidthMedium + fontSize: '1.75rem', + borderWidth: componentTheme.borderWidthMedium, + width: calcNewScaler(1.5, 1.75, shape === 'circle' ? 2.5 : 3), + height: calcNewScaler(1.5, 1.75, 2.5) }, 'x-large': { - fontSize: '1.75rem', - borderWidth: componentTheme.borderWidthMedium + fontSize: '2rem', + borderWidth: componentTheme.borderWidthMedium, + width: calcNewScaler(1.75, 2, shape === 'circle' ? 2.5 : 3), + height: calcNewScaler(1.75, 2, 2.5) }, 'xx-large': { - fontSize: '2rem', - borderWidth: componentTheme.borderWidthMedium + fontSize: '2.25rem', + borderWidth: componentTheme.borderWidthMedium, + width: calcNewScaler(2, 2.25, shape === 'circle' ? 2.5 : 3), + height: calcNewScaler(2, 2.25, 2.5) } } - const variantStyles = { + const initialSizeStyles = { + auto: { + fontSize: 'inherit' + }, + 'xx-small': { + fontSize: '0.5rem' + }, + 'x-small': { + fontSize: '0.75rem' + }, + small: { + fontSize: '1rem' + }, + medium: { + fontSize: '1.25rem' + }, + large: { + fontSize: '1.5rem' + }, + 'x-large': { + fontSize: '1.75rem' + }, + 'xx-large': { + fontSize: '2rem' + } + } + + const shapeStyles = { circle: { - width: '2.5em', position: 'relative', borderRadius: '100%', overflow: 'hidden' @@ -105,34 +159,54 @@ const generateStyle = ( crimson: componentTheme.colorCrimson, fire: componentTheme.colorFire, licorice: componentTheme.colorLicorice, - ash: componentTheme.colorAsh + ash: componentTheme.colorAsh, + ai: ` + linear-gradient(to bottom, ${componentTheme.aiTopGradientColor} 0%, ${componentTheme.aiBottomGradientColor} 100%) padding-box, + linear-gradient(to bottom right, ${componentTheme.aiTopGradientColor} 0%, ${componentTheme.aiBottomGradientColor} 100%) border-box` } - const backgroundColor = hasInverseColor - ? colorVariants[color!] - : componentTheme.background + const background = () => { + if (color === 'ai') { + return { + background: ` + linear-gradient(to bottom, ${componentTheme.aiTopGradientColor} 0%, ${componentTheme.aiBottomGradientColor} 100%) padding-box, + linear-gradient(to bottom right, ${componentTheme.aiTopGradientColor} 0%, ${componentTheme.aiBottomGradientColor} 100%) border-box`, + border: 'solid transparent' + } + } + return hasInverseColor + ? { + backgroundColor: colorVariants[color!], + backgroundClip: 'content-box' + } + : { + backgroundColor: componentTheme.background, + backgroundClip: 'content-box' + } + } - const contentColor = hasInverseColor - ? componentTheme.background - : colorVariants[color!] + const contentColor = () => { + if (color === 'ai') { + return componentTheme.aiFontColor + } + return hasInverseColor ? componentTheme.background : colorVariants[color!] + } return { avatar: { label: 'avatar', - height: '2.5em', boxSizing: 'border-box', - backgroundColor: backgroundColor, + borderStyle: 'solid', + borderColor: componentTheme.borderColor, + ...background(), backgroundPosition: 'center', backgroundSize: 'cover', - backgroundClip: 'content-box', backgroundRepeat: 'no-repeat', overflow: 'hidden', lineHeight: 0, textAlign: 'center', - borderStyle: 'solid', - borderColor: componentTheme.borderColor, ...sizeStyles[size!], - ...variantStyles[shape!], + ...shapeStyles[shape!], ...(loaded ? { backgroundImage: `url('${src}')`, @@ -155,11 +229,12 @@ const generateStyle = ( }, initials: { label: 'avatar__initials', - color: contentColor, + color: contentColor(), lineHeight: '2.375em', fontFamily: componentTheme.fontFamily, fontWeight: componentTheme.fontWeight, - letterSpacing: '0.0313em' + letterSpacing: '0.0313em', + ...initialSizeStyles[size!] }, loadImage: { label: 'avatar__loadImage', @@ -174,7 +249,7 @@ const generateStyle = ( width: '100%', svg: { - fill: contentColor, + fill: contentColor(), height: '1em', width: '1em' } diff --git a/packages/ui-avatar/src/Avatar/theme.ts b/packages/ui-avatar/src/Avatar/theme.ts index 8bef04e26b..bb7573352b 100644 --- a/packages/ui-avatar/src/Avatar/theme.ts +++ b/packages/ui-avatar/src/Avatar/theme.ts @@ -52,7 +52,11 @@ const generateComponentTheme = (theme: Theme): AvatarTheme => { colorCrimson: colors?.contrasts?.red4570, colorFire: colors?.contrasts?.orange4570, colorLicorice: colors?.contrasts?.grey125125, - colorAsh: colors?.contrasts?.grey4570 + colorAsh: colors?.contrasts?.grey4570, + + aiTopGradientColor: colors?.contrasts?.violet4570, + aiBottomGradientColor: colors?.contrasts?.sea4570, + aiFontColor: colors?.contrasts?.white1010 } return {