diff --git a/packages/bee-q/src/components.d.ts b/packages/bee-q/src/components.d.ts index b30493da3..1f08e8a2e 100644 --- a/packages/bee-q/src/components.d.ts +++ b/packages/bee-q/src/components.d.ts @@ -73,7 +73,7 @@ export namespace Components { */ "backgroundColor"?: string; /** - * The size of the badge + * The size of the badge. Relevant if badge has no content. */ "size"?: TBadgeSize; /** @@ -912,7 +912,7 @@ declare namespace LocalJSX { */ "backgroundColor"?: string; /** - * The size of the badge + * The size of the badge. Relevant if badge has no content. */ "size"?: TBadgeSize; /** diff --git a/packages/bee-q/src/components/avatar/__tests__/bq-avatar.e2e.ts b/packages/bee-q/src/components/avatar/__tests__/bq-avatar.e2e.ts index e834ff2d6..0a4605233 100644 --- a/packages/bee-q/src/components/avatar/__tests__/bq-avatar.e2e.ts +++ b/packages/bee-q/src/components/avatar/__tests__/bq-avatar.e2e.ts @@ -83,4 +83,24 @@ describe('bq-avatar', () => { expect(mediumSquareStyle).toEqual({ borderRadius: '12px', height: '48px', width: '48px' }); expect(largeSquareStyle).toEqual({ borderRadius: '12px', height: '64px', width: '64px' }); }); + + it('should render component', async () => { + const page = await newE2EPage(); + await page.setContent(` + + 9 + + `); + + const avatarElem = await page.find('bq-avatar'); + const sideMenuItems = await avatarElem.findAll('bq-badge'); + + expect(sideMenuItems).toHaveLength(1); + }); }); diff --git a/packages/bee-q/src/components/avatar/_storybook/bq-avatar.stories.tsx b/packages/bee-q/src/components/avatar/_storybook/bq-avatar.stories.tsx index 37f6d1f2a..d0df8d3df 100644 --- a/packages/bee-q/src/components/avatar/_storybook/bq-avatar.stories.tsx +++ b/packages/bee-q/src/components/avatar/_storybook/bq-avatar.stories.tsx @@ -23,6 +23,7 @@ const meta: Meta = { label: 'Avatar component label', shape: 'circle', size: 'medium', + 'badge-content': '9', }, }; export default meta; @@ -55,3 +56,21 @@ export const Initials: Story = { initials: 'JS', }, }; + +export const WithBadge: Story = { + render: (args: Args) => + html` + ${args['badge-content']} + `, + args: { + image: + 'https://images.unsplash.com/photo-1524593689594-aae2f26b75ab?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1000&q=80', + }, +}; diff --git a/packages/bee-q/src/components/avatar/bq-avatar.tsx b/packages/bee-q/src/components/avatar/bq-avatar.tsx index 214aebda9..ee56521d0 100644 --- a/packages/bee-q/src/components/avatar/bq-avatar.tsx +++ b/packages/bee-q/src/components/avatar/bq-avatar.tsx @@ -1,4 +1,4 @@ -import { h, Component, Prop, Watch, State, Element } from '@stencil/core'; +import { h, Component, Prop, Watch, State, Element, Host } from '@stencil/core'; import { TAvatarShape, TAvatarSize, AVATAR_SHAPE, AVATAR_SIZE } from './bq-avatar.types'; import { validatePropValue } from '../../shared/utils'; @@ -19,6 +19,8 @@ export class BqAvatar { // Own Properties // ==================== + trimmedInitials: string; + // Reference to host HTML element // =================================== @@ -67,6 +69,12 @@ export class BqAvatar { validatePropValue(AVATAR_SIZE, 'medium', this.el, 'size'); } + @Watch('initials') + @Watch('size') + onInitialsChnage() { + this.trimInitialsBasedOnSize(); + } + // Events section // Requires JSDocs for public API documentation // ============================================== @@ -76,6 +84,7 @@ export class BqAvatar { // ===================================== componentWillLoad() { + this.trimInitialsBasedOnSize(); this.checkPropValues(); } @@ -98,43 +107,79 @@ export class BqAvatar { this.hasError = true; }; + private trimInitialsBasedOnSize = (): void => { + AVATAR_SIZE.forEach((size: TAvatarSize) => { + if (this.size === size) { + this.trimmedInitials = this.initials.substring(0, this.getIndex(size)); + } + }); + }; + + private getIndex = (size: TAvatarSize): number => { + switch (size) { + case 'small': + return 2; + case 'medium': + return 3; + case 'large': + return 4; + default: + // also if size === xsmall + return 1; + } + }; + // render() function // Always the last one in the class. // =================================== render() { return ( - + + +
+ +
+
); } } diff --git a/packages/bee-q/src/components/avatar/scss/bq-avatar.scss b/packages/bee-q/src/components/avatar/scss/bq-avatar.scss index 66ed0772d..16f0206fe 100644 --- a/packages/bee-q/src/components/avatar/scss/bq-avatar.scss +++ b/packages/bee-q/src/components/avatar/scss/bq-avatar.scss @@ -5,23 +5,30 @@ @import './bq-avatar.variables'; :host { - @apply inline-block; + @apply relative inline-block; +} + +.bq-avatar { + @apply relative overflow-hidden bg-[var(--bq-avatar-background)]; + @apply border-[length:var(--bq-avatar--border-width)] border-[color:var(--bq-avatar--border-color)]; + + border-style: var(--bq-avatar--border-style); } .size { &--xsmall { - @apply h-[var(--bq-avatar--size-xsmall)] w-[var(--bq-avatar--size-xsmall)] text-xs; + @apply h-[var(--bq-avatar--size-xsmall)] w-[var(--bq-avatar--size-xsmall)] text-[length:var(--bq-avatar--font-size-xsmall)]; } &--small { - @apply h-[var(--bq-avatar--size-small)] w-[var(--bq-avatar--size-small)] text-xs; + @apply h-[var(--bq-avatar--size-small)] w-[var(--bq-avatar--size-small)] text-[length:var(--bq-avatar--font-size-small)]; } &--medium { - @apply h-[var(--bq-avatar--size-medium)] w-[var(--bq-avatar--size-medium)] text-m; + @apply h-[var(--bq-avatar--size-medium)] w-[var(--bq-avatar--size-medium)] text-[length:var(--bq-avatar--font-size-medium)]; } &--large { - @apply h-[var(--bq-avatar--size-large)] w-[var(--bq-avatar--size-large)] text-m; + @apply h-[var(--bq-avatar--size-large)] w-[var(--bq-avatar--size-large)] text-[length:var(--bq-avatar--font-size-large)]; } } diff --git a/packages/bee-q/src/components/avatar/scss/bq-avatar.variables.scss b/packages/bee-q/src/components/avatar/scss/bq-avatar.variables.scss index f4cd17584..60fd941a4 100644 --- a/packages/bee-q/src/components/avatar/scss/bq-avatar.variables.scss +++ b/packages/bee-q/src/components/avatar/scss/bq-avatar.variables.scss @@ -3,8 +3,52 @@ /* -------------------------------------------------------------------------- */ :host { + /** + * @prop --bq-avatar--background: Avatar background color + + * @prop --bq-avatar--border-color: Avatar border color + * @prop --bq-avatar--border-style: Avatar border style + * @prop --bq-avatar--border-width: Avatar border width + + * @prop --bq-avatar--border-radius-circle: Avatar border radius for circle & any size + * @prop --bq-avatar--border-radius-squareXs: Avatar border radius for square & size xsmall + * @prop --bq-avatar--border-radius-squareS: Avatar border radius for square & size small + * @prop --bq-avatar--border-radius-squareM: Avatar border radius for square & size medium/large + + * @prop --bq-avatar--size-xsmall: Avatar xsmall size + * @prop --bq-avatar--size-small: Avatar small size + * @prop --bq-avatar--size-medium: Avatar medium size + * @prop --bq-avatar--size-large: Avatar large size + + * @prop --bq-avatar--badge-top-square: Badge top position shape square + * @prop --bq-avatar--badge-left-square: Badge left position shape square + * @prop --bq-avatar--badge-top-circle: Badge top position shape circle + * @prop --bq-avatar--badge-left-circle: Badge left position shape circle + */ + + --bq-avatar-background: theme('colors.ui.secondary-light'); + + --bq-avatar--border-color: theme('colors.stroke.tiertary'); + --bq-avatar--border-style: solid; + --bq-avatar--border-width: 2px; + + --bq-avatar--border-radius-circle: theme('borderRadius.full'); + --bq-avatar--border-radius-squareXs: theme('borderRadius.xs'); + --bq-avatar--border-radius-squareS: theme('borderRadius.s'); + --bq-avatar--border-radius-squareM: theme('borderRadius.m'); + --bq-avatar--size-xsmall: 24px; --bq-avatar--size-small: 32px; --bq-avatar--size-medium: 48px; --bq-avatar--size-large: 64px; + + --bq-avatar--font-size-xsmall: theme('fontSize.xs'); + --bq-avatar--font-size-small: theme('fontSize.xs'); + --bq-avatar--font-size-medium: theme('fontSize.m'); + --bq-avatar--font-size-large: theme('fontSize.m'); + + --bq-avatar--badge-top-square: -5px; + --bq-avatar--badge-left-square: 80%; + --bq-avatar--badge-top-circle: 0; + --bq-avatar--badge-left-circle: 75%; } diff --git a/packages/bee-q/src/components/badge/bq-badge.tsx b/packages/bee-q/src/components/badge/bq-badge.tsx index 2b56e4d41..d1ad15492 100644 --- a/packages/bee-q/src/components/badge/bq-badge.tsx +++ b/packages/bee-q/src/components/badge/bq-badge.tsx @@ -43,7 +43,7 @@ export class BqBadge { /** Badge number color. The value should be a valid value of the palette color */ @Prop({ mutable: true, reflect: true }) textColor? = 'text--inverse'; - /** The size of the badge */ + /** The size of the badge. Relevant if badge has no content. */ @Prop({ reflect: true, mutable: true }) size?: TBadgeSize = 'small'; // Prop lifecycle events diff --git a/packages/bee-q/src/components/badge/readme.md b/packages/bee-q/src/components/badge/readme.md index 60d7e5845..523d50dc8 100644 --- a/packages/bee-q/src/components/badge/readme.md +++ b/packages/bee-q/src/components/badge/readme.md @@ -10,7 +10,7 @@ | Property | Attribute | Description | Type | Default | | ----------------- | ------------------ | ------------------------------------------------------------------------------ | --------------------- | ----------------- | | `backgroundColor` | `background-color` | Badge background color. The value should be a valid value of the palette color | `string` | `'ui--danger'` | -| `size` | `size` | The size of the badge | `"medium" \| "small"` | `'small'` | +| `size` | `size` | The size of the badge. Relevant if badge has no content. | `"medium" \| "small"` | `'small'` | | `textColor` | `text-color` | Badge number color. The value should be a valid value of the palette color | `string` | `'text--inverse'` |