Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(avatar): DLT-1916 remove dt-icon from Avatar vue 2 #474

Merged
merged 15 commits into from
Sep 6, 2024
Merged
12 changes: 8 additions & 4 deletions packages/dialtone-vue2/components/avatar/avatar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const MOCK_INITIALS = 'JN';
const MOCK_SIZE = 'lg';
const MOCK_GROUP = 25;
const MOCK_CUSTOM_CLASS = 'my-custom-class';
const MOCK_ICON_SLOT = '<template #icon=>Icon</template>';
ninamarina marked this conversation as resolved.
Show resolved Hide resolved
let MOCK_ELEMENT = null;

const baseProps = {
Expand All @@ -20,6 +21,7 @@ const baseListeners = {};
let mockProps = {};
let mockListeners = {};
const testContext = {};
let mockSlots = {};

describe('DtAvatar Tests', () => {
let wrapper;
Expand All @@ -32,6 +34,7 @@ describe('DtAvatar Tests', () => {
propsData: { ...baseProps, ...mockProps },
listeners: { ...baseListeners, ...mockListeners },
localVue: testContext.localVue,
slots: { ...mockSlots },
});

image = wrapper.find('[data-qa="dt-avatar-image"]');
Expand All @@ -50,6 +53,7 @@ describe('DtAvatar Tests', () => {
afterEach(() => {
mockProps = {};
mockListeners = {};
mockSlots = {};
});

describe('Presentation Tests', () => {
Expand Down Expand Up @@ -83,19 +87,19 @@ describe('DtAvatar Tests', () => {
});
});

describe('When the iconName is provided', () => {
describe('When the icon slot is provided', () => {
beforeEach(() => {
mockProps = { iconName: 'accessibility' };
mockSlots = { icon: MOCK_ICON_SLOT };

updateWrapper();
});

it('icon should exist', () => {
expect(wrapper.find('svg').exists()).toBeTruthy();
expect(wrapper.find('[data-qa="dt-avatar-icon"]').exists()).toBeTruthy();
});

it('should have correct class', () => {
expect(wrapper.find('svg').classes(AVATAR_KIND_MODIFIERS.icon)).toBe(true);
expect(wrapper.find('[data-qa="dt-avatar-icon"]').classes(AVATAR_KIND_MODIFIERS.icon)).toBe(true);
});
});

Expand Down
67 changes: 30 additions & 37 deletions packages/dialtone-vue2/components/avatar/avatar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,19 @@
:src="imageSrc"
:alt="imageAlt"
>
<dt-icon
v-else-if="iconName"
:name="iconName"
:aria-label="iconAriaLabel"
:size="iconSize || AVATAR_ICON_SIZES[size]"
<div
v-else-if="isIconType"
:class="[iconClass, AVATAR_KIND_MODIFIERS.icon]"
data-qa="dt-avatar-icon"
/>
:aria-label="clickable ? iconAriaLabel : ''"
:data-qa="iconDataQa"
:role="clickable ? 'button' : ''"
>
<!-- @slot Slot for avatar icon. It will display if no imageSrc is provided -->
<slot
name="icon"
:icon-size="iconSize || AVATAR_ICON_SIZES[size]"
/>
</div>
<span
v-else
:class="[AVATAR_KIND_MODIFIERS.initials]"
Expand All @@ -38,13 +43,13 @@
</span>
</div>
<div
v-if="overlayIcon || overlayText"
v-if="hasOverlayIcon || overlayText"
:class="overlayClasses"
>
<dt-icon
v-if="overlayIcon"
class="d-avatar__overlay-icon"
:name="overlayIcon"
<!-- @slot Slot for overlay icon. -->
<slot
v-if="hasOverlayIcon"
name="overlayIcon"
/>
<p
v-else-if="overlayText"
Expand Down Expand Up @@ -74,7 +79,6 @@
<script>
import { getUniqueString, getRandomElement } from '@/common/utils';
import { DtPresence } from '../presence';
import { DtIcon } from '@/components/icon';
import {
AVATAR_KIND_MODIFIERS,
AVATAR_SIZE_MODIFIERS,
Expand All @@ -84,19 +88,16 @@ import {
AVATAR_GROUP_VALIDATOR,
AVATAR_ICON_SIZES,
} from './avatar_constants';
import { getIconNames } from '@/common/storybook_utils.js';
import { ICON_SIZE_MODIFIERS } from '@/components/icon/icon_constants.js';
import { extractInitialsFromName } from './utils';

const ICONS_LIST = getIconNames();

/**
* An avatar is a visual representation of a user or object.
* @see https://dialtone.dialpad.com/components/avatar.html
*/
export default {
name: 'DtAvatar',
components: { DtPresence, DtIcon },
components: { DtPresence },

inheritAttrs: false,

Expand Down Expand Up @@ -194,14 +195,6 @@ export default {
validator: (group) => AVATAR_GROUP_VALIDATOR(group),
},

/**
* The icon that overlays the avatar
*/
overlayIcon: {
type: String,
default: '',
},

/**
* The text that overlays the avatar
*/
Expand Down Expand Up @@ -236,15 +229,6 @@ export default {
default: undefined,
},

/**
* Icon name to be displayed on the avatar
*/
iconName: {
type: String,
default: undefined,
validator: (name) => ICONS_LIST.includes(name),
},

/**
* Icon size to be displayed on the avatar
* @values 100, 200, 300, 400, 500, 600, 700, 800
Expand Down Expand Up @@ -305,8 +289,16 @@ export default {
},

computed: {
isNotIconType () {
return !this.iconName;
isIconType () {
return this.$scopedSlots.icon && this.$scopedSlots.icon();
},

hasOverlayIcon () {
return !!this.$slots.overlayIcon;
},

iconDataQa () {
return 'dt-avatar-icon';
},

avatarClasses () {
Expand All @@ -316,7 +308,7 @@ export default {
this.avatarClass,
{
'd-avatar--group': this.showGroup,
[`d-avatar--color-${this.getColor()}`]: this.isNotIconType,
[`d-avatar--color-${this.getColor()}`]: !this.isIconType,
'd-avatar--clickable': this.clickable,
},
];
Expand All @@ -326,6 +318,7 @@ export default {
return [
'd-avatar__overlay',
this.overlayClass,
{ 'd-avatar__overlay-icon': this.hasOverlayIcon },
];
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@
:seed="$attrs.seed"
:size="size"
full-name="Avatar Icon"
icon-name="user"
/>
>
<template #icon="{ iconSize }">
<dt-icon-user :size="iconSize" />
</template>
</dt-avatar>
</div>
</div>
<div>
Expand Down Expand Up @@ -64,7 +67,11 @@
:image-src="$attrs.imageSrc"
:image-alt="$attrs.imageAlt"
overlay-icon="hear"
/>
>
<template #overlayIcon>
<dt-icon-hear />
</template>
</dt-avatar>
<dt-avatar
:seed="$attrs.seed"
size="xl"
Expand All @@ -85,10 +92,13 @@
/>
<dt-avatar
:seed="$attrs.seed"
icon-name="user"
icon-aria-label="user icon"
clickable
/>
>
<template #icon="{ iconSize }">
<dt-icon-user :size="iconSize" />
</template>
</dt-avatar>
<dt-avatar
:seed="$attrs.seed"
full-name="Person avatar"
Expand All @@ -108,9 +118,12 @@
/>
<dt-avatar
:seed="$attrs.seed"
icon-name="user"
:group="10"
/>
>
<template #icon="{ iconSize }">
<dt-icon-user :size="iconSize" />
</template>
</dt-avatar>
<dt-avatar
:seed="$attrs.seed"
full-name="Person avatar"
Expand All @@ -124,12 +137,13 @@
</template>

<script>
import { DtIconUser, DtIconHear } from '@dialpad/dialtone-icons/vue2';
import DtAvatar from './avatar.vue';
import { AVATAR_PRESENCE_STATES, AVATAR_SIZE_MODIFIERS } from './avatar_constants.js';

export default {
name: 'DtAvatarVariants',
components: { DtAvatar },
components: { DtAvatar, DtIconUser, DtIconHear },
data () {
return {
avatarSizes: Object.keys(AVATAR_SIZE_MODIFIERS),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,17 @@
:full-name="displayName"
:image-src="avatarImageUrl"
image-alt=""
:icon-name="iconName"
:seed="avatarSeed"
/>
>
<template
v-if="noInitials"
#icon="{ iconSize }"
>
<dt-icon-user
:size="iconSize"
/>
</template>
</dt-avatar>
</slot>
</div>
<!-- show time instead of avatar when headers not present -->
Expand Down Expand Up @@ -118,6 +126,7 @@ import { DtLazyShow } from '@/components/lazy_show';
import { DtListItem } from '@/components/list_item';
import { DtBadge } from '@/components/badge';
import Modal from '@/common/mixins/modal';
import { DtIconUser } from '@dialpad/dialtone-icons/vue2';

export default {
name: 'DtRecipeFeedItemRow',
Expand All @@ -127,6 +136,7 @@ export default {
DtLazyShow,
DtListItem,
DtBadge,
DtIconUser,
},

mixins: [Modal],
Expand Down Expand Up @@ -271,10 +281,6 @@ export default {
};
},

iconName () {
return this.noInitials ? 'user' : null;
},

listItemClasses () {
return [
'dt-feed-item-row',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/* eslint-disable max-lines */
import { action } from '@storybook/addon-actions';
import { createRenderConfig, getIconNames } from '@/common/storybook_utils';
import { createRenderConfig } from '@/common/storybook_utils';
import DtRecipeContactInfo from './contact_info.vue';

import DtRecipeContactInfoDefaultTemplate from './contact_info_default.story.vue';
import DtRecipeContactInfoVariantsTemplate from './contact_info_variants.story.vue';
import { AVATAR_SIZE_MODIFIERS, AVATAR_COLORS } from '@/components/avatar';
import { PRESENCE_STATES_LIST } from '@/components/presence';
import { DtIconUser } from '@dialpad/dialtone-icons/vue2';

import avatarImage from '@/common/assets/avatar1.png';
const iconsList = getIconNames();

// Default Prop Values
export const argsData = {
Expand Down Expand Up @@ -39,13 +39,7 @@ export const argTypesData = {
},

avatarIcon: {
options: iconsList,
control: {
type: 'select',
labels: {
undefined: '(empty)',
},
},
ninamarina marked this conversation as resolved.
Show resolved Hide resolved
control: 'object',
},

avatarColor: {
Expand Down Expand Up @@ -146,6 +140,7 @@ export const Default = {
render: (argsData) => createRenderConfig(DtRecipeContactInfo, DtRecipeContactInfoDefaultTemplate, argsData),

args: {
avatarIcon: DtIconUser,
avatarSrc: avatarImage,
avatarSeed: 'JL',
avatarFullName: 'Joseph Lumaban',
Expand Down
Loading
Loading