From 562d950e58bb000922ec8bdcdff81df965b1ad69 Mon Sep 17 00:00:00 2001 From: Lars Rickert Date: Wed, 8 Jan 2025 12:13:37 +0100 Subject: [PATCH 1/3] refactor(OnyxAvatar): update default initials --- .../components/OnyxAvatar/OnyxAvatar.ct.tsx | 16 ++++++++++---- .../OnyxAvatar/OnyxAvatar.stories.ts | 7 ++----- .../src/components/OnyxAvatar/OnyxAvatar.vue | 21 +++++++------------ .../src/components/OnyxAvatar/types.ts | 5 +++++ .../modules/OnyxUserMenu/OnyxUserMenu.vue | 3 ++- .../OnyxNavBar/modules/OnyxUserMenu/types.ts | 3 ++- 6 files changed, 31 insertions(+), 24 deletions(-) diff --git a/packages/sit-onyx/src/components/OnyxAvatar/OnyxAvatar.ct.tsx b/packages/sit-onyx/src/components/OnyxAvatar/OnyxAvatar.ct.tsx index 74e0e9f47..5b9c2b433 100644 --- a/packages/sit-onyx/src/components/OnyxAvatar/OnyxAvatar.ct.tsx +++ b/packages/sit-onyx/src/components/OnyxAvatar/OnyxAvatar.ct.tsx @@ -44,9 +44,11 @@ test.describe("Screenshot tests", () => { columns: ["default", "truncation"], rows: AVATAR_SIZES, component: (column, row) => ( - - {column === "truncation" ? "+999999" : "+42"} - + ), }); }); @@ -60,7 +62,7 @@ test("should contain correct initials", async ({ mount }) => { }); // ASSERT - await expect(component).toContainText("AB"); + await expect(component).toContainText("AD"); // ACT await component.update({ props: { label: "abcd" } }); @@ -73,6 +75,12 @@ test("should contain correct initials", async ({ mount }) => { // ASSERT await expect(component).toContainText("A"); + + // ACT + await component.update({ props: { label: "abcd", initials: "HI" } }); + + // ASSERT + await expect(component).toContainText("HI"); }); test("should show custom image", async ({ mount, page }) => { diff --git a/packages/sit-onyx/src/components/OnyxAvatar/OnyxAvatar.stories.ts b/packages/sit-onyx/src/components/OnyxAvatar/OnyxAvatar.stories.ts index 488925b1c..4e68a4346 100644 --- a/packages/sit-onyx/src/components/OnyxAvatar/OnyxAvatar.stories.ts +++ b/packages/sit-onyx/src/components/OnyxAvatar/OnyxAvatar.stories.ts @@ -7,9 +7,6 @@ import OnyxAvatar from "./OnyxAvatar.vue"; const meta: Meta = { title: "Basic/Avatar", component: OnyxAvatar, - argTypes: { - default: { control: { type: "text" } }, - }, }; export default meta; @@ -36,11 +33,11 @@ export const WithImage = { } satisfies Story; /** - * This example shows an avatar with custom content instead of the default initials. + * This example shows an avatar with custom initials instead of the automatically detected ones. */ export const WithCustomInitials = { args: { label: "4 more avatars", - default: "+4", + initials: "+4", }, } satisfies Story; diff --git a/packages/sit-onyx/src/components/OnyxAvatar/OnyxAvatar.vue b/packages/sit-onyx/src/components/OnyxAvatar/OnyxAvatar.vue index 672342977..fb8d9892d 100644 --- a/packages/sit-onyx/src/components/OnyxAvatar/OnyxAvatar.vue +++ b/packages/sit-onyx/src/components/OnyxAvatar/OnyxAvatar.vue @@ -6,18 +6,13 @@ const props = withDefaults(defineProps(), { size: "48px", }); -const slots = defineSlots<{ - /** - * Optional slot to override the default initials. Will only be used if `type` is `initials`. - */ - default?(): unknown; -}>(); - const initials = computed(() => { - const names = props.label.split(" "); - const initials = - names.length > 1 ? `${names[0].charAt(0)}${names[1].charAt(0)}` : names[0].substring(0, 2); - return initials.toUpperCase(); + if (props.initials) return props.initials; + + const names = props.label.trim().toUpperCase().split(" "); + if (names.length === 1) return names[0].substring(0, 2); + + return `${names[0].charAt(0)}${names.at(-1)?.charAt(0)}`; }); const hasImageError = ref(false); @@ -32,7 +27,7 @@ watch( diff --git a/packages/sit-onyx/src/components/OnyxAvatar/types.ts b/packages/sit-onyx/src/components/OnyxAvatar/types.ts index 6810fd61f..8e6e1ef8a 100644 --- a/packages/sit-onyx/src/components/OnyxAvatar/types.ts +++ b/packages/sit-onyx/src/components/OnyxAvatar/types.ts @@ -11,4 +11,9 @@ export type OnyxAvatarProps = IconSizeProp> & { * with the initials. */ src?: string; + /** + * Initials to use. If unset, they will be inferred automatically from the `label` property + * by using the first character of the first and last word. + */ + initials?: string; }; diff --git a/packages/sit-onyx/src/components/OnyxNavBar/modules/OnyxUserMenu/OnyxUserMenu.vue b/packages/sit-onyx/src/components/OnyxNavBar/modules/OnyxUserMenu/OnyxUserMenu.vue index 501708a08..2fcd4535f 100644 --- a/packages/sit-onyx/src/components/OnyxNavBar/modules/OnyxUserMenu/OnyxUserMenu.vue +++ b/packages/sit-onyx/src/components/OnyxNavBar/modules/OnyxUserMenu/OnyxUserMenu.vue @@ -24,6 +24,7 @@ const slots = defineSlots<{ }>(); const avatar = computed(() => { + if (typeof props.avatar === "object") return props.avatar; return { src: props.avatar, label: props.username }; }); @@ -50,7 +51,7 @@ const isMobile = inject(