From 7b4376e01580cb36134d59f9c53f7f066554993d Mon Sep 17 00:00:00 2001 From: sivanova Date: Thu, 30 Oct 2025 09:46:29 +0200 Subject: [PATCH 1/2] feat(badge): design enhancement --- .../src/lib/badge/badge.component.spec.ts | 31 ++++- .../src/lib/badge/badge.component.ts | 18 ++- .../src/lib/badge/themes/_base.scss | 48 +++++-- .../src/lib/badge/themes/dark/_index.scss | 1 + .../src/lib/badge/themes/dark/_indigo.scss | 14 +++ .../src/lib/badge/themes/shared/_index.scss | 1 + .../lib/badge/themes/shared/bootstrap.scss | 14 ++- .../src/lib/badge/themes/shared/fluent.scss | 22 ++++ .../src/lib/badge/themes/shared/indigo.scss | 32 ++++- .../core/styles/typography/_bootstrap.scss | 2 +- .../lib/core/styles/typography/_fluent.scss | 2 +- .../lib/core/styles/typography/_indigo.scss | 6 +- .../lib/core/styles/typography/_material.scss | 2 +- src/app/badge/badge.sample.html | 119 ++++++++++++------ src/app/badge/badge.sample.scss | 48 ++++++- src/app/badge/badge.sample.ts | 10 +- 16 files changed, 303 insertions(+), 67 deletions(-) create mode 100644 projects/igniteui-angular/src/lib/badge/themes/dark/_indigo.scss create mode 100644 projects/igniteui-angular/src/lib/badge/themes/shared/fluent.scss diff --git a/projects/igniteui-angular/src/lib/badge/badge.component.spec.ts b/projects/igniteui-angular/src/lib/badge/badge.component.spec.ts index d6654f0974e..6d398d5e871 100644 --- a/projects/igniteui-angular/src/lib/badge/badge.component.spec.ts +++ b/projects/igniteui-angular/src/lib/badge/badge.component.spec.ts @@ -11,7 +11,8 @@ describe('Badge', () => { InitBadgeWithDefaultsComponent, InitBadgeWithIconComponent, IgxBadgeComponent, - InitBadgeWithIconARIAComponent + InitBadgeWithIconARIAComponent, + InitBadgeWithDotComponent ] }).compileComponents(); })); @@ -87,6 +88,26 @@ describe('Badge', () => { const container = fixture.nativeElement.querySelectorAll('.igx-badge')[0]; expect(container.getAttribute('aria-roledescription')).toMatch(expectedDescription); }); + + it('Initializes badge with dot property', () => { + const fixture = TestBed.createComponent(InitBadgeWithDotComponent); + fixture.detectChanges(); + const badge = fixture.componentInstance.badge; + + expect(badge.dot).toBeTruthy(); + expect(fixture.debugElement.query(By.css('.igx-badge--dot'))).toBeTruthy(); + }); + + it('Initializes success badge as dot', () => { + const fixture = TestBed.createComponent(InitBadgeWithDotComponent); + fixture.detectChanges(); + const badge = fixture.componentInstance.badge; + + expect(badge.type).toBe(IgxBadgeType.SUCCESS); + expect(badge.dot).toBeTruthy(); + expect(fixture.debugElement.query(By.css('.igx-badge--dot'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('.igx-badge--success'))).toBeTruthy(); + }); }); @Component({ @@ -120,3 +141,11 @@ class InitBadgeWithIconComponent { class InitBadgeWithIconARIAComponent { @ViewChild(IgxBadgeComponent, { static: true }) public badge: IgxBadgeComponent; } + +@Component({ + template: ``, + imports: [IgxBadgeComponent] +}) +class InitBadgeWithDotComponent { + @ViewChild(IgxBadgeComponent, { static: true }) public badge: IgxBadgeComponent; +} diff --git a/projects/igniteui-angular/src/lib/badge/badge.component.ts b/projects/igniteui-angular/src/lib/badge/badge.component.ts index 1ddc94f900e..331a86c9202 100644 --- a/projects/igniteui-angular/src/lib/badge/badge.component.ts +++ b/projects/igniteui-angular/src/lib/badge/badge.component.ts @@ -155,7 +155,9 @@ export class IgxBadgeComponent { /** @hidden @internal */ @HostBinding('class.igx-badge--square') public get _squareShape(): boolean { - return this.shape === 'square'; + if (!this.dot) { + return this.shape === 'square'; + } } /** @@ -185,6 +187,20 @@ export class IgxBadgeComponent { @HostBinding('class.igx-badge--outlined') public outlined = false; + /** + * Sets/gets whether the badge is displayed as a dot. + * When true, the badge will be rendered as a minimal 8px indicator without any content. + * Default value is `false`. + * + * @example + * ```html + * + * ``` + */ + @Input({transform: booleanAttribute}) + @HostBinding('class.igx-badge--dot') + public dot = false; + /** * Defines a human-readable, accessor, author-localized description for * the `type` and the `icon` or `value` of the element. diff --git a/projects/igniteui-angular/src/lib/badge/themes/_base.scss b/projects/igniteui-angular/src/lib/badge/themes/_base.scss index 6885840bbb1..48c0220213c 100644 --- a/projects/igniteui-angular/src/lib/badge/themes/_base.scss +++ b/projects/igniteui-angular/src/lib/badge/themes/_base.scss @@ -9,9 +9,13 @@ $theme: $material; @include layer(base) { @include b(igx-badge) { - --size: #{rem(22px)}; - --_badge-size: var(--size); - --igx-icon-size: calc(var(--_badge-size) / 2); + @include sizable(); + + --component-size: var(--ig-size, #{var-get($theme, 'default-size')}); + --badge-size: var(--component-size); + --_badge-size: #{var-get($theme, 'size')}; + + --igx-icon-size: #{sizable(rem(12px), rem(14px), rem(16px))}; --igx-icon-color: #{var-get($theme, 'icon-color')}; display: inline-flex; @@ -24,40 +28,60 @@ $theme: $material; border-radius: calc(var(--size) / 2); box-shadow: var-get($theme, 'elevation'); overflow: hidden; - - @include type-style(caption) { - margin: 0; - } + font-size: sizable(var(--ig-caption-font-size), var(--ig-body-2-font-size), var(--ig-body-2-font-size)); + font-weight: sizable(var(--ig-caption-font-weight), var(--ig-body-2-font-weight), var(--ig-body-2-font-weight)); + line-height: sizable(var(--ig-caption-line-height), var(--ig-body-2-line-height), var(--ig-body-2-line-height)); + letter-spacing: sizable(var(--ig-caption-letter-spacing), var(--ig-body-2-letter-spacing), var(--ig-body-2-letter-spacing)); + text-transform: sizable(var(--ig-caption-text-transform), var(--ig-body-2-text-transform), var(--ig-body-2-text-transform)); @include e(value) { white-space: nowrap; - padding-inline: rem(4px); + padding-inline: pad-inline(rem(4px), rem(6px), rem(8px)); } @include m(info) { - background: color($color: 'info'); + background: color($color: 'info', $variant: 800); } @include m(success) { - background: color($color: 'success'); + background: color($color: 'success', $variant: 900); } @include m(warning) { background: color($color: 'warn'); + color: contrast-color($color: 'warn', $variant: 500); + + igx-icon { + color: contrast-color($color: 'warn', $variant: 500); + } } @include m(error) { - background: color($color: 'error'); + background: color($color: 'error', $variant: 700); + color: contrast-color($color: 'error', $variant: 900); } @include m(outlined) { - box-shadow: inset 0 0 0 rem(2px) var-get($theme, 'border-color'); + box-shadow: 0 0 0 rem(2px) var-get($theme, 'border-color'); } @include m(square) { border-radius: var-get($theme, 'border-radius'); } + @include m(dot) { + --_dot-size: #{var-get($theme, 'dot-size')}; + + min-width: var(--_dot-size); + min-height: var(--_dot-size); + padding: 0; + + igx-icon, + > * { + display: none; + } + } + @include m(hidden) { visibility: hidden; } diff --git a/projects/igniteui-angular/src/lib/badge/themes/dark/_index.scss b/projects/igniteui-angular/src/lib/badge/themes/dark/_index.scss index 855eddbf96a..2b57c62473b 100644 --- a/projects/igniteui-angular/src/lib/badge/themes/dark/_index.scss +++ b/projects/igniteui-angular/src/lib/badge/themes/dark/_index.scss @@ -1,6 +1,7 @@ @use 'sass:meta'; @use 'tokens'; @use 'styles/themes/standalone' as *; +@use 'indigo'; $tokens: meta.module-variables(tokens); @include themes(igx-badge, $tokens, dark); diff --git a/projects/igniteui-angular/src/lib/badge/themes/dark/_indigo.scss b/projects/igniteui-angular/src/lib/badge/themes/dark/_indigo.scss new file mode 100644 index 00000000000..1a503ba3eb4 --- /dev/null +++ b/projects/igniteui-angular/src/lib/badge/themes/dark/_indigo.scss @@ -0,0 +1,14 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/color/functions' as *; +@use 'styles/themes/standalone' as *; +@use '../light/tokens' as *; + +@include themed-block(igx-badge, indigo, dark) { + @include m(warning) { + color: color($color: 'gray', $variant: 50); + + igx-icon { + color: color($color: 'gray', $variant: 50); + } + } +} diff --git a/projects/igniteui-angular/src/lib/badge/themes/shared/_index.scss b/projects/igniteui-angular/src/lib/badge/themes/shared/_index.scss index be6ed543149..e9d8e587687 100644 --- a/projects/igniteui-angular/src/lib/badge/themes/shared/_index.scss +++ b/projects/igniteui-angular/src/lib/badge/themes/shared/_index.scss @@ -1,2 +1,3 @@ @forward 'bootstrap'; @forward 'indigo'; +@forward 'fluent'; diff --git a/projects/igniteui-angular/src/lib/badge/themes/shared/bootstrap.scss b/projects/igniteui-angular/src/lib/badge/themes/shared/bootstrap.scss index 345ee74d9ec..78fa4c0eff2 100644 --- a/projects/igniteui-angular/src/lib/badge/themes/shared/bootstrap.scss +++ b/projects/igniteui-angular/src/lib/badge/themes/shared/bootstrap.scss @@ -1,13 +1,23 @@ @use 'igniteui-theming/sass/bem' as *; @use 'igniteui-theming/sass/typography' as *; @use 'igniteui-theming/sass/themes/functions' as *; +@use 'igniteui-theming/sass/color/functions' as *; @use 'styles/themes/standalone' as *; @use '../light/tokens' as *; $_theme: $bootstrap; @include themed-block(igx-badge, bootstrap) { - @include m(outlined) { - box-shadow: inset 0 0 0 rem(1px) var-get($_theme, 'border-color'); + @include m(success) { + background: color($color: 'success', $variant: 500); + } + + @include m(info) { + background: color($color: 'info', $variant: 500); + } + + @include m(error) { + background: color($color: 'error', $variant: 500); + color: contrast-color($color: 'error', $variant: 100); } } diff --git a/projects/igniteui-angular/src/lib/badge/themes/shared/fluent.scss b/projects/igniteui-angular/src/lib/badge/themes/shared/fluent.scss new file mode 100644 index 00000000000..8fc38531e2e --- /dev/null +++ b/projects/igniteui-angular/src/lib/badge/themes/shared/fluent.scss @@ -0,0 +1,22 @@ +@use 'igniteui-theming/sass/bem' as *; +@use 'igniteui-theming/sass/typography' as *; +@use 'igniteui-theming/sass/themes/functions' as *; +@use 'igniteui-theming/sass/color/functions' as *; +@use 'styles/themes/standalone' as *; +@use '../light/tokens' as *; + +$_theme: $fluent; + +@include themed-block(igx-badge, fluent) { + @include m(success) { + background: color($color: 'success', $variant: 500); + } + + @include m(info) { + background: color($color: 'info', $variant: 700); + } + + @include m(error) { + background: color($color: 'error', $variant: 500); + } +} diff --git a/projects/igniteui-angular/src/lib/badge/themes/shared/indigo.scss b/projects/igniteui-angular/src/lib/badge/themes/shared/indigo.scss index 2ebf543a42f..aaee8a9394d 100644 --- a/projects/igniteui-angular/src/lib/badge/themes/shared/indigo.scss +++ b/projects/igniteui-angular/src/lib/badge/themes/shared/indigo.scss @@ -1,13 +1,39 @@ @use 'igniteui-theming/sass/bem' as *; @use 'igniteui-theming/sass/typography' as *; @use 'igniteui-theming/sass/themes/functions' as *; +@use 'igniteui-theming/sass/color/functions' as *; @use 'styles/themes/standalone' as *; @use '../light/tokens' as *; @include themed-block(igx-badge, indigo) { - --igx-icon-size: #{rem(12px)}; + --igx-icon-size: #{sizable(rem(8px), rem(10px), rem(12px))}; - @include type-style(button) { - margin: 0; + @include type-style('button', false) { + font-size: sizable(rem(9px), rem(10px), var(--ig-button-font-size)); + line-height: sizable(rem(12px), rem(14px), var(--ig-button-line-height)); + } + + @include e(value) { + padding-inline: pad-inline(rem(4px), rem(6px), rem(6px)); + } + + @include m(success) { + background: color($color: 'success', $variant: 700); + } + + @include m(info) { + background: color($color: 'info', $variant: 500); + } + + @include m(error) { + background: color($color: 'error', $variant: 500); + } + + @include m(warning) { + color: color($color: 'gray', $variant: 900); + + igx-icon { + color: color($color: 'gray', $variant: 900); + } } } diff --git a/projects/igniteui-angular/src/lib/core/styles/typography/_bootstrap.scss b/projects/igniteui-angular/src/lib/core/styles/typography/_bootstrap.scss index 94b39380b4d..ece20c03398 100644 --- a/projects/igniteui-angular/src/lib/core/styles/typography/_bootstrap.scss +++ b/projects/igniteui-angular/src/lib/core/styles/typography/_bootstrap.scss @@ -36,7 +36,7 @@ @use '../components/input/file-input-theme' as *; @mixin typography($type-scale) { - @include badge-typography(); + // @include badge-typography(); // @include banner-typography(); // @include bottom-nav-typography(); @include button-typography(); diff --git a/projects/igniteui-angular/src/lib/core/styles/typography/_fluent.scss b/projects/igniteui-angular/src/lib/core/styles/typography/_fluent.scss index f8afb3acccf..8ad4d9ede7a 100644 --- a/projects/igniteui-angular/src/lib/core/styles/typography/_fluent.scss +++ b/projects/igniteui-angular/src/lib/core/styles/typography/_fluent.scss @@ -35,7 +35,7 @@ @use '../components/input/file-input-theme' as *; @mixin typography() { - @include badge-typography(); + // @include badge-typography(); // @include banner-typography($categories: ( // message: 'caption' // )); diff --git a/projects/igniteui-angular/src/lib/core/styles/typography/_indigo.scss b/projects/igniteui-angular/src/lib/core/styles/typography/_indigo.scss index bb73f123582..71d591ff515 100644 --- a/projects/igniteui-angular/src/lib/core/styles/typography/_indigo.scss +++ b/projects/igniteui-angular/src/lib/core/styles/typography/_indigo.scss @@ -35,9 +35,9 @@ @use '../components/input/file-input-theme' as *; @mixin typography($type-scale) { - @include badge-typography($categories: ( - text: 'button', - )); + // @include badge-typography($categories: ( + // text: 'button', + // )); // @include banner-typography(); // @include bottom-nav-typography(); @include button-typography(); diff --git a/projects/igniteui-angular/src/lib/core/styles/typography/_material.scss b/projects/igniteui-angular/src/lib/core/styles/typography/_material.scss index 5d174814b1d..78da6691095 100644 --- a/projects/igniteui-angular/src/lib/core/styles/typography/_material.scss +++ b/projects/igniteui-angular/src/lib/core/styles/typography/_material.scss @@ -35,7 +35,7 @@ @use '../components/input/file-input-theme' as *; @mixin typography() { - @include badge-typography(); + // @include badge-typography(); // @include banner-typography(); // @include bottom-nav-typography(); @include button-typography(); diff --git a/src/app/badge/badge.sample.html b/src/app/badge/badge.sample.html index 47e674f1fb3..eca8c546bad 100644 --- a/src/app/badge/badge.sample.html +++ b/src/app/badge/badge.sample.html @@ -1,43 +1,90 @@

Angular Badge

- -
- - - bluetooth - +
+
+ + With Value +
+
+ + bluetooth + + With Icon +
+
+ + + bluetooth + + On Avatar +
-
-
-

WC Badge

- 8 -
- - - - +

Dot Type Badges

+
+
+ + Primary Dot +
+
+ + Info Dot +
+
+ + Success Dot +
+
+ + Warning Dot +
+
+ + Error Dot +
+
+ + + Dot on Avatar +
+
+ +

Type Variants

+
+
+ + Primary +
+
+ + Info +
+
+ + Success +
+
+ + Warning +
+
+ + Error +
-
+
\ No newline at end of file diff --git a/src/app/badge/badge.sample.scss b/src/app/badge/badge.sample.scss index 85f3261b048..ef89f8276ec 100644 --- a/src/app/badge/badge.sample.scss +++ b/src/app/badge/badge.sample.scss @@ -1,16 +1,54 @@ +@use '../../../projects/igniteui-angular/src/lib/core/styles/themes/utilities' as *; + .wrapper { display: grid; - grid-template-columns: repeat(2, 1fr); + gap: rem(48px); + padding: rem(24px); } .badges { - place-items: center; - display: grid; - grid-template-columns: subgrid; + place-items: start; + display: flex; + flex-direction: column; gap: 24px; } -.avatar-sample { +.badge-examples { display: flex; + flex-wrap: wrap; + gap: rem(32px); align-items: center; + padding: rem(16px); + background: color($color: 'gray', $variant: 100); + border-radius: rem(8px); } + +.badge-item { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + position: relative; + + span { + font-size: 14px; + } +} + +.avatar-sample { + display: flex; + align-items: center; + position: relative; + + igx-avatar { + anchor-name: --avatar; + } + + igx-badge { + position: absolute; + position-anchor: --avatar; + bottom: anchor(--avatar top); + left: anchor(right); + transform: translate(-75%, 75%); + } +} \ No newline at end of file diff --git a/src/app/badge/badge.sample.ts b/src/app/badge/badge.sample.ts index f8bcb45c90a..9615cdfe83f 100644 --- a/src/app/badge/badge.sample.ts +++ b/src/app/badge/badge.sample.ts @@ -3,6 +3,7 @@ import { IgxBadgeComponent, IgxAvatarComponent, IgxIconComponent, + IgSizeDirective, } from 'igniteui-angular'; import { defineComponents, @@ -32,11 +33,18 @@ registerIconFromText('bluetooth', bluetooth); styleUrls: ['badge.sample.scss'], templateUrl: 'badge.sample.html', schemas: [CUSTOM_ELEMENTS_SCHEMA], - imports: [IgxBadgeComponent, IgxAvatarComponent, IgxIconComponent] + imports: [IgxBadgeComponent, IgxAvatarComponent, IgxIconComponent, IgSizeDirective] }) export class BadgeSampleComponent { public panelConfig: PropertyPanelConfig = { + size: { + control: { + type: 'button-group', + options: ['small', 'medium', 'large'], + defaultValue: 'medium' + } + }, shape: { control: { type: 'button-group', From 8c293de8ceca435de851188a422570b6dfb076d9 Mon Sep 17 00:00:00 2001 From: sivanova Date: Fri, 31 Oct 2025 16:12:25 +0200 Subject: [PATCH 2/2] fix(badge-sample): remove duplications after merge --- src/app/badge/badge.sample.html | 73 ++++++++++----------------------- src/app/badge/badge.sample.scss | 32 --------------- 2 files changed, 21 insertions(+), 84 deletions(-) diff --git a/src/app/badge/badge.sample.html b/src/app/badge/badge.sample.html index bc2608d4610..5240855c490 100644 --- a/src/app/badge/badge.sample.html +++ b/src/app/badge/badge.sample.html @@ -86,58 +86,27 @@

Type Variants

Error
+ -

Dot Type Badges

-
-
- - Primary Dot -
-
- - Info Dot -
-
- - Success Dot -
-
- - Warning Dot -
-
- - Error Dot -
-
- - - Dot on Avatar -
-
- -

Type Variants

-
-
- - Primary -
-
- - Info -
-
- - Success -
-
- - Warning -
-
- - Error -
+
+

WC Badge

+ 8 +
+ + + +
-
\ No newline at end of file + diff --git a/src/app/badge/badge.sample.scss b/src/app/badge/badge.sample.scss index 61b84ecf5d0..126f27254d0 100644 --- a/src/app/badge/badge.sample.scss +++ b/src/app/badge/badge.sample.scss @@ -37,8 +37,6 @@ .avatar-sample { display: flex; - flex-wrap: wrap; - gap: rem(32px); align-items: center; position: relative; @@ -54,33 +52,3 @@ transform: translate(-75%, 75%); } } - -.badge-item { - display: flex; - flex-direction: column; - align-items: center; - gap: 8px; - position: relative; - - span { - font-size: 14px; - } -} - -.avatar-sample { - display: flex; - align-items: center; - position: relative; - - igx-avatar { - anchor-name: --avatar; - } - - igx-badge { - position: absolute; - position-anchor: --avatar; - bottom: anchor(--avatar top); - left: anchor(right); - transform: translate(-75%, 75%); - } -} \ No newline at end of file