diff --git a/packages/calcite-components/src/components/avatar/avatar.e2e.ts b/packages/calcite-components/src/components/avatar/avatar.e2e.ts
index 8c769695707..f42dcbf6e4f 100644
--- a/packages/calcite-components/src/components/avatar/avatar.e2e.ts
+++ b/packages/calcite-components/src/components/avatar/avatar.e2e.ts
@@ -1,6 +1,8 @@
import { newE2EPage } from "@stencil/core/testing";
import { accessible, defaults, hidden, renders } from "../../tests/commonTests";
import { placeholderImage } from "../../../.storybook/placeholderImage";
+import { html } from "../../../support/formatting";
+import { CSS } from "./resources";
const placeholderUrl = placeholderImage({
width: 120,
@@ -63,7 +65,7 @@ describe("calcite-avatar", () => {
const background = document.querySelector("calcite-avatar").shadowRoot.querySelector(".background");
return background.getAttribute("style");
});
- expect(style).toEqual("background-color: rgb(245, 219, 214);");
+ expect(style).toEqual("background-color: rgb(245, 214, 236);");
});
it("renders default icon when no information is passed", async () => {
@@ -73,4 +75,27 @@ describe("calcite-avatar", () => {
const visible = await icon.isVisible();
expect(visible).toBe(true);
});
+
+ it("generates unique background if names are similar", async () => {
+ const page = await newE2EPage();
+ await page.setContent(html`
+
+
+
+ `);
+
+ const avatars = [
+ await page.find(`calcite-avatar:nth-child(1) >>> .${CSS.background}`),
+ await page.find(`calcite-avatar:nth-child(2) >>> .${CSS.background}`),
+ await page.find(`calcite-avatar:nth-child(3) >>> .${CSS.background}`),
+ ];
+
+ const [firstBgColor, secondBgColor, thirdBgColor] = await Promise.all(
+ avatars.map((avatar) => avatar.getComputedStyle().then(({ backgroundColor }) => backgroundColor)),
+ );
+
+ expect(firstBgColor).not.toEqual(secondBgColor);
+ expect(secondBgColor).not.toEqual(thirdBgColor);
+ expect(firstBgColor).not.toEqual(thirdBgColor);
+ });
});
diff --git a/packages/calcite-components/src/components/avatar/avatar.tsx b/packages/calcite-components/src/components/avatar/avatar.tsx
index df4030b1b6c..922bf1cad8d 100644
--- a/packages/calcite-components/src/components/avatar/avatar.tsx
+++ b/packages/calcite-components/src/components/avatar/avatar.tsx
@@ -2,6 +2,7 @@ import { Component, Element, h, Prop, State } from "@stencil/core";
import { getModeName } from "../../utils/dom";
import { isValidHex } from "../color-picker/utils";
import { Scale } from "../interfaces";
+import { CSS } from "./resources";
import { hexToHue, stringToHex } from "./utils";
@Component({
@@ -65,7 +66,7 @@ export class Avatar {
return (
(this.thumbnailFailedToLoad = true)}
src={this.thumbnail}
/>
@@ -76,16 +77,16 @@ export class Avatar {
return (
{initials ? (
-
+
{initials}
) : (
-
+
)}
);
diff --git a/packages/calcite-components/src/components/avatar/resources.ts b/packages/calcite-components/src/components/avatar/resources.ts
new file mode 100644
index 00000000000..5cacd848092
--- /dev/null
+++ b/packages/calcite-components/src/components/avatar/resources.ts
@@ -0,0 +1,6 @@
+export const CSS = {
+ thumbnail: "thumbnail",
+ background: "background",
+ initials: "initials",
+ icon: "icon",
+};
diff --git a/packages/calcite-components/src/components/avatar/utils.ts b/packages/calcite-components/src/components/avatar/utils.ts
index 406247145d0..7757a83bedd 100644
--- a/packages/calcite-components/src/components/avatar/utils.ts
+++ b/packages/calcite-components/src/components/avatar/utils.ts
@@ -5,12 +5,15 @@ import { hexToRGB } from "../color-picker/utils";
* Convert a string to a valid hex by hashing its contents
* and using the hash as a seed for three distinct color values
*
- * @param str
+ * @param string
*/
-export function stringToHex(str: string): string {
+export function stringToHex(string: string): string {
+ // improve random color generation for similar strings.
+ string = mixStringDeterministically(string);
+
let hash = 0;
- for (let i = 0; i < str.length; i++) {
- hash = str.charCodeAt(i) + ((hash << 5) - hash);
+ for (let i = 0; i < string.length; i++) {
+ hash = string.charCodeAt(i) + ((hash << 5) - hash);
}
let hex = "#";
@@ -21,6 +24,18 @@ export function stringToHex(str: string): string {
return hex;
}
+/**
+ * The function splits the string into two halves, reverses each half, and then concatenates them.
+ *
+ * @param {string} string - The input string to be mixed.
+ * @returns {string} - The mixed string.
+ */
+function mixStringDeterministically(string: string): string {
+ const midPoint = Math.floor(string.length / 2);
+ const reversed = string.split("").reverse().join("");
+ return reversed.substring(midPoint) + reversed.slice(0, midPoint);
+}
+
/**
* Find the hue of a color given the separate RGB color channels
*