Skip to content

Commit 3ba45e7

Browse files
committed
feat(badge): add dismissable badge
1 parent 8a07b30 commit 3ba45e7

File tree

7 files changed

+179
-2
lines changed

7 files changed

+179
-2
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<flowbite-badge [isDismissable]="true">Default</flowbite-badge>
2+
<flowbite-badge
3+
[isDismissable]="true"
4+
[onDismiss]="onDismiss"
5+
color="primary">
6+
Primary
7+
</flowbite-badge>
8+
<flowbite-badge
9+
[isDismissable]="true"
10+
[onDismiss]="onDismiss"
11+
color="blue">
12+
Blue
13+
</flowbite-badge>
14+
<flowbite-badge
15+
[isDismissable]="true"
16+
[onDismiss]="onDismiss"
17+
color="red">
18+
Red
19+
</flowbite-badge>
20+
<flowbite-badge
21+
[isDismissable]="true"
22+
[onDismiss]="onDismiss"
23+
color="green">
24+
Green
25+
</flowbite-badge>
26+
<flowbite-badge
27+
[isDismissable]="true"
28+
[onDismiss]="onDismiss"
29+
color="yellow">
30+
Yellow
31+
</flowbite-badge>
32+
<flowbite-badge
33+
[isDismissable]="true"
34+
[onDismiss]="onDismiss"
35+
color="indigo">
36+
Indigo
37+
</flowbite-badge>
38+
<flowbite-badge
39+
[isDismissable]="true"
40+
[onDismiss]="onDismiss"
41+
color="purple">
42+
Purple
43+
</flowbite-badge>
44+
<flowbite-badge
45+
[isDismissable]="true"
46+
[onDismiss]="onDismiss"
47+
color="pink">
48+
Pink
49+
</flowbite-badge>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { BadgeComponent } from 'flowbite-angular/badge';
2+
3+
import { Component } from '@angular/core';
4+
5+
@Component({
6+
selector: 'flowbite-demo-badge-dismissable',
7+
imports: [BadgeComponent],
8+
templateUrl: './_dismissable.component.html',
9+
host: {
10+
class: 'flex flex-wrap flex-row gap-3',
11+
},
12+
})
13+
export class FlowbiteDismissableComponent {
14+
onDismiss = () => alert('Badge have been dismissed');
15+
}

apps/docs/docs/components/badge/index.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,19 @@ keyword: BadgePage
7373
```angular-ts file="./_icon-only.component.ts"#L1-L2 group="icon-only" name="typescript"
7474
7575
```
76+
77+
## Dismissable badge
78+
79+
{{ NgDocActions.demo('flowbiteDismissableComponent', {container: false}) }}
80+
81+
```angular-html file="./_dismissable.component.html" group="dismissable" name="html"
82+
83+
```
84+
85+
```angular-ts file="./_dismissable.component.ts"#L1-L1 group="dismissable" name="typescript"
86+
87+
```
88+
89+
```angular-ts file="./_dismissable.component.ts"#L14 group="dismissable" name="typescript"
90+
91+
```

apps/docs/docs/components/badge/ng-doc.page.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import ComponentCategory from '../ng-doc.category';
22
import { FlowbiteBorderedComponent } from './_bordered.component';
33
import { FlowbiteDefaultComponent } from './_default.component';
4+
import { FlowbiteDismissableComponent } from './_dismissable.component';
45
import { FlowbiteIconOnlyComponent } from './_icon-only.component';
56
import { FlowbiteIconComponent } from './_icon.component';
67
import { FlowbiteLargeComponent } from './_large.component';
@@ -25,6 +26,7 @@ const badge: NgDocPage = {
2526
flowbiteIconComponent: FlowbiteIconComponent,
2627
flowbiteLargeComponent: FlowbiteLargeComponent,
2728
flowbiteLinkComponent: FlowbiteLinkComponent,
29+
flowbiteDismissableComponent: FlowbiteDismissableComponent,
2830
},
2931
};
3032

libs/flowbite-angular/badge/badge.component.ts

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { BadgeThemeService } from './badge.theme.service';
33

44
import type { DeepPartial } from 'flowbite-angular';
55
import { BaseComponent, booleanToFlowbiteBoolean } from 'flowbite-angular';
6+
import { IconComponent, IconRegistry } from 'flowbite-angular/icon';
67
import { FlowbiteRouterLinkDirective } from 'flowbite-angular/router-link';
8+
import { CLOSE_SVG_ICON } from 'flowbite-angular/utils';
79

810
import {
911
ChangeDetectionStrategy,
@@ -14,6 +16,7 @@ import {
1416
model,
1517
ViewEncapsulation,
1618
} from '@angular/core';
19+
import { DomSanitizer } from '@angular/platform-browser';
1720

1821
export const FLOWBITE_BADGE_COLOR_DEFAULT_VALUE = new InjectionToken<keyof BadgeColors>(
1922
'FLOWBITE_BADGE_COLOR_DEFAULT_VALUE'
@@ -39,6 +42,14 @@ export const FLOWBITE_BADGE_CUSTOM_STYLE_DEFAULT_VALUE = new InjectionToken<
3942
DeepPartial<BadgeTheme>
4043
>('FLOWBITE_BADGE_CUSTOM_STYLE_DEFAULT_VALUE');
4144

45+
export const FLOWBITE_BADGE_IS_DISMISSABLE_DEFAULT_VALUE = new InjectionToken<boolean>(
46+
'FLOWBITE_BADGE_IS_DISMISSABLE_DEFAULT_VALUE'
47+
);
48+
49+
export const FLOWBITE_BADGE_ON_DISMISS_DEFAULT_VALUE = new InjectionToken<(() => void) | undefined>(
50+
'FLOWBITE_BADGE_ON_DISMISS_DEFAULT_VALUE'
51+
);
52+
4253
export const badgeDefaultValueProvider = makeEnvironmentProviders([
4354
{
4455
provide: FLOWBITE_BADGE_COLOR_DEFAULT_VALUE,
@@ -64,15 +75,38 @@ export const badgeDefaultValueProvider = makeEnvironmentProviders([
6475
provide: FLOWBITE_BADGE_CUSTOM_STYLE_DEFAULT_VALUE,
6576
useValue: {},
6677
},
78+
{
79+
provide: FLOWBITE_BADGE_IS_DISMISSABLE_DEFAULT_VALUE,
80+
useValue: false,
81+
},
82+
{
83+
provide: FLOWBITE_BADGE_ON_DISMISS_DEFAULT_VALUE,
84+
useValue: undefined,
85+
},
6786
]);
6887

6988
/**
7089
* @see https://flowbite.com/docs/components/badge/
7190
*/
7291
@Component({
7392
standalone: true,
93+
imports: [IconComponent],
7494
selector: 'flowbite-badge',
75-
template: `<ng-content />`,
95+
template: `
96+
<ng-content />
97+
@if (isDismissable()) {
98+
<button
99+
type="button"
100+
[class]="contentClasses()!.closeButtonClass"
101+
aria-label="Close"
102+
(click)="onDismissClick()">
103+
<span class="sr-only">Close</span>
104+
<flowbite-icon
105+
svgIcon="flowbite-angular:close"
106+
class="h-3 w-3" />
107+
</button>
108+
}
109+
`,
76110
encapsulation: ViewEncapsulation.None,
77111
changeDetection: ChangeDetectionStrategy.OnPush,
78112
})
@@ -85,6 +119,14 @@ export class BadgeComponent extends BaseComponent<BadgeClass> {
85119
* Service injected used to generate class
86120
*/
87121
public readonly themeService = inject(BadgeThemeService);
122+
/**
123+
* `IcoRegistry` service
124+
*/
125+
public readonly iconRegistry = inject(IconRegistry);
126+
/**
127+
* `DomSanitizer` service
128+
*/
129+
public readonly domSanitizer = inject(DomSanitizer);
88130

89131
//#region properties
90132
/**
@@ -95,6 +137,8 @@ export class BadgeComponent extends BaseComponent<BadgeClass> {
95137
public color = model(inject(FLOWBITE_BADGE_COLOR_DEFAULT_VALUE));
96138
/**
97139
* Set if the badge has border
140+
*
141+
* @default false
98142
*/
99143
public hasBorder = model(inject(FLOWBITE_BADGE_HAS_BORDER_DEFAULT_VALUE));
100144
/**
@@ -119,6 +163,18 @@ export class BadgeComponent extends BaseComponent<BadgeClass> {
119163
* Set the custom style for this badge
120164
*/
121165
public customStyle = model(inject(FLOWBITE_BADGE_CUSTOM_STYLE_DEFAULT_VALUE));
166+
/**
167+
* Set if the badge is dismissable
168+
*
169+
* @default false
170+
*/
171+
public isDismissable = model(inject(FLOWBITE_BADGE_IS_DISMISSABLE_DEFAULT_VALUE));
172+
/**
173+
* Set the function called when the badge is dismissed
174+
*
175+
* @default undefined
176+
*/
177+
public onDismiss = model(inject(FLOWBITE_BADGE_ON_DISMISS_DEFAULT_VALUE));
122178
//#endregion
123179

124180
//#region BaseComponent implementation
@@ -133,5 +189,22 @@ export class BadgeComponent extends BaseComponent<BadgeClass> {
133189
customStyle: this.customStyle(),
134190
});
135191
}
192+
193+
public override init(): void {
194+
this.iconRegistry.addRawSvgIconInNamepsace(
195+
'flowbite-angular',
196+
'close',
197+
this.domSanitizer.bypassSecurityTrustHtml(CLOSE_SVG_ICON)
198+
);
199+
}
136200
//#endregion
201+
202+
/**
203+
* Call the onDismiss function if it's not undefined
204+
*/
205+
public onDismissClick() {
206+
const func = this.onDismiss();
207+
208+
if (func) func();
209+
}
137210
}

libs/flowbite-angular/badge/badge.theme.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export class BadgeThemeService implements FlowbiteThemeService<BadgeProperties>
4141
theme.root.isIconOnly[properties.isIconOnly],
4242
theme.root.link[properties.link ? 'enabled' : 'disabled']
4343
),
44+
closeButtonClass: twMerge(theme.closeButton.base, theme.closeButton.color[properties.color]),
4445
};
4546

4647
return output;

libs/flowbite-angular/badge/badge.theme.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ export interface BadgeTheme {
5454
isIconOnly: FlowbiteBoolean;
5555
link: FlowbiteBoolean;
5656
};
57+
closeButton: {
58+
base: string;
59+
color: BadgeColors;
60+
};
5761
}
5862

5963
/**
@@ -99,9 +103,26 @@ export const badgeTheme: BadgeTheme = createTheme({
99103
disabled: 'px-2 py-0.5',
100104
},
101105
},
106+
closeButton: {
107+
base: 'ms-1 inline-flex items-center rounded-sm p-1 focus:ring-2',
108+
color: {
109+
primary:
110+
'text-primary-500 dark:text-primary-600 hover:bg-primary-200 dark:hover:bg-primary-300',
111+
dark: 'text-gray-500 dark:text-gray-600 hover:bg-gray-200 dark:hover:bg-gray-300',
112+
blue: 'text-blue-500 dark:text-blue-600 hover:bg-blue-200 dark:hover:bg-blue-300',
113+
red: 'text-red-500 dark:text-red-600 hover:bg-red-200 dark:hover:bg-red-300',
114+
green: 'text-green-500 dark:text-green-600 hover:bg-green-200 dark:hover:bg-green-300',
115+
yellow: 'text-yellow-500 dark:text-yellow-600 hover:bg-yellow-200 dark:hover:bg-yellow-300',
116+
indigo: 'text-indigo-500 dark:text-indigo-600 hover:bg-indigo-200 dark:hover:bg-indigo-300',
117+
purple: 'text-purple-500 dark:text-purple-600 hover:bg-purple-200 dark:hover:bg-purple-300',
118+
pink: 'text-pink-500 dark:text-pink-600 hover:bg-pink-200 dark:hover:bg-pink-300',
119+
},
120+
},
102121
});
103122

104123
/**
105124
* Generated class definition for `BadgeComponent`
106125
*/
107-
export type BadgeClass = FlowbiteClass;
126+
export interface BadgeClass extends FlowbiteClass {
127+
closeButtonClass: string;
128+
}

0 commit comments

Comments
 (0)