Skip to content
20 changes: 19 additions & 1 deletion projects/igniteui-angular/src/lib/badge/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# igx-badge

The **igx-badge** component is an absolutely positioned element that can be used in tandem with other components such as avatars, navigation menus, or anywhere else in an app where some active indication is required.
With the igx-badge you can display active count or an icon in several different predefined styles.
With the igx-badge you can display active count or an icon in several different predefined styles and sizes.
A walkthrough of how to get started can be found [here](https://www.infragistics.com/products/ignite-ui-angular/angular/components/badge.html)

# Usage
Expand All @@ -14,9 +14,12 @@ A walkthrough of how to get started can be found [here](https://www.infragistics
|:----------|:-------------:|:------|
| `id` | string | Unique identifier of the component. If not provided it will be automatically generated.|
| `type` | string | Set the type of the badge to either `primary`, `info`, `success`, `warning`, or `error`. This will change the background color of the badge according to the values set in the default theme. |
| `dot` | boolean | Set whether the badge is displayed as a minimal dot indicator without any content. Default is `false`. |
| `position` | string | Set the position of the badge relative to its parent container to either `top-right`, `top-left`, `bottom-right`, or `bottom-left`. |
| `value` | string | Set the value to be displayed inside the badge. |
| `icon` | string | Set an icon for the badge from the material icons set. Will not be displayed if `value` for the badge is already set. |
| `outlined` | boolean | Set whether the badge should have an outline. Default is `false`. |
| `shape` | string | Set the shape of the badge to either `rounded` or `square`. Default is `rounded`. |

# Examples

Expand All @@ -26,3 +29,18 @@ Using `igx-badge` with the `igx-avatar` component to show active status.
<igx-badge type="info" value="8"></igx-badge>
</igx-avatar>
```

Using `igx-badge` as a dot indicator for notifications.
```html
<igx-badge dot type="success"></igx-badge>
<igx-badge dot outlined type="error"></igx-badge>
```

Using different badge types.
```html
<igx-badge type="primary" value="1"></igx-badge>
<igx-badge type="info" value="2"></igx-badge>
<igx-badge type="success" value="3"></igx-badge>
<igx-badge type="warning" value="4"></igx-badge>
<igx-badge type="error" value="5"></igx-badge>
```
31 changes: 30 additions & 1 deletion projects/igniteui-angular/src/lib/badge/badge.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ describe('Badge', () => {
InitBadgeWithDefaultsComponent,
InitBadgeWithIconComponent,
IgxBadgeComponent,
InitBadgeWithIconARIAComponent
InitBadgeWithIconARIAComponent,
InitBadgeWithDotComponent
]
}).compileComponents();
}));
Expand Down Expand Up @@ -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({
Expand Down Expand Up @@ -120,3 +141,11 @@ class InitBadgeWithIconComponent {
class InitBadgeWithIconARIAComponent {
@ViewChild(IgxBadgeComponent, { static: true }) public badge: IgxBadgeComponent;
}

@Component({
template: `<igx-badge dot type="success"></igx-badge>`,
imports: [IgxBadgeComponent]
})
class InitBadgeWithDotComponent {
@ViewChild(IgxBadgeComponent, { static: true }) public badge: IgxBadgeComponent;
}
18 changes: 17 additions & 1 deletion projects/igniteui-angular/src/lib/badge/badge.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,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';
}
}

/**
Expand Down Expand Up @@ -183,6 +185,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
* <igx-badge dot type="success"></igx-badge>
* ```
*/
@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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
@extend %igx-badge--error !optional;
}

@include m(dot) {
@extend %igx-badge--dot !optional;
}

@include m(outlined) {
@extend %igx-badge--outlined !optional;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
/// @param {Map} $theme - The theme used to style the component.
@mixin badge($theme) {
@include css-vars($theme);

$theme-variant: map.get($theme, '_meta', 'variant');
$variant: map.get($theme, '_meta', 'theme');

%igx-badge-display {
--size: #{rem(22px)};
--_badge-size: var(--size);
@include sizable();

--component-size: var(--ig-size, #{var-get($theme, 'default-size')});
--badge-size: var(--component-size);
--_badge-size: #{var-get($theme, 'size')};

display: inline-flex;
justify-content: center;
Expand All @@ -25,18 +28,18 @@
overflow: hidden;

igx-icon {
--size: var(--igx-icon-size, calc(var(--_badge-size) / 2));
--size: var(--igx-icon-size, #{sizable(rem(12px), rem(14px), rem(16px))});
--component-size: var(--badge-size);

display: inline-flex;
justify-content: center;
align-items: center;
font-weight: 400;
color: var-get($theme, 'icon-color');
}

@if $variant == 'indigo' {
igx-icon {
$icon-size: rem(12px);
$icon-size: sizable(rem(8px), rem(10px), rem(12px));

--ig-icon-size: #{$icon-size};
--igx-icon-size: #{$icon-size};
Expand All @@ -45,7 +48,7 @@
}

%igx-badge--outlined {
box-shadow: inset 0 0 0 rem(if($variant != 'bootstrap', 2px, 1px)) var-get($theme, 'border-color');
box-shadow: 0 0 0 rem(2px) var-get($theme, 'border-color');
}

%igx-badge--square {
Expand All @@ -54,23 +57,57 @@

%igx-badge-value {
white-space: nowrap;
padding-inline: pad-inline(rem(4px));
padding-inline: pad-inline(rem(4px), rem(6px), if($variant == 'indigo', rem(6px), rem(8px)));
}

%igx-badge--success {
background: color($color: 'success');
background: color($color: 'success', $variant: if($variant != 'material', if($variant == 'indigo', 700, 500), 900));
}

%igx-badge--info {
background: color($color: 'info');
background: color($color: 'info', $variant: if($variant != 'material', if($variant == 'fluent', 700, 500), 800));
}

%igx-badge--warn {
background: color($color: 'warn');

@if $variant == 'indigo' and $theme-variant == 'light' {
color: color($color: 'gray', $variant: 900);

igx-icon {
color: color($color: 'gray', $variant: 900);
}
} @else if $variant == 'indigo' and $theme-variant == 'dark' {
color: color($color: 'gray', $variant: 50);

igx-icon {
color: color($color: 'gray', $variant: 50);
}
} @else {
color: contrast-color($color: 'warn', $variant: 500);

igx-icon {
color: contrast-color($color: 'warn', $variant: 500);
}
}
}

%igx-badge--error {
background: color($color: 'error');
background: color($color: 'error', $variant: if($variant == 'material', 700, 500));
color: contrast-color($color: 'error', $variant: if($variant == 'bootstrap', 100, 900));
}

%igx-badge--dot {
--_dot-size: #{var-get($theme, 'dot-size')};

min-width: var(--_dot-size);
min-height: var(--_dot-size);
padding: 0;

igx-icon,
> * {
display: none;
}
}

%igx-badge--hidden {
Expand All @@ -79,15 +116,28 @@
}

/// Adds typography styles for the igx-badge component.
/// Uses the 'caption' category from the typographic scale.
/// Uses 'caption' and 'body-2' categories from the typographic scale.
/// @group typography
/// @param {Map} $categories [(text: 'caption')] - The categories from the typographic scale used for type styles.
@mixin badge-typography($categories: (text: 'caption')) {
@mixin badge-typography($categories: (text: null), $theme: null) {
$text: map.get($categories, 'text');

%igx-badge-display {
@include type-style($text) {
margin: 0;
@if $text {
@include type-style($text);
} @else {
@if $theme == 'indigo' {
@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));
}
} @else {
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));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
@use '../components/input/file-input-theme' as *;

@mixin typography($type-scale) {
@include badge-typography();
@include badge-typography($theme: 'bootstrap');
@include banner-typography();
@include bottom-nav-typography();
@include button-typography();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
@use '../components/input/file-input-theme' as *;

@mixin typography() {
@include badge-typography();
@include badge-typography($theme: 'fluent');
@include banner-typography($categories: (
message: 'caption'
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@
@use '../components/input/file-input-theme' as *;

@mixin typography($type-scale) {
@include badge-typography($categories: (
text: 'button',
));
@include badge-typography($theme: 'indigo');
@include banner-typography();
@include bottom-nav-typography();
@include button-typography();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
@use '../components/input/file-input-theme' as *;

@mixin typography() {
@include badge-typography();
@include badge-typography($theme: 'material');
@include banner-typography();
@include bottom-nav-typography();
@include button-typography();
Expand Down
Loading
Loading