Skip to content

Commit

Permalink
feat(badge): add dismissable badge (#101)
Browse files Browse the repository at this point in the history
## PR Checklist

Please check if your PR fulfills the following requirements:

<!--- [ ] Tests for the changes have been added (for bug
fixes/features)-->

- [x] Docs have been added/updated (for bug fixes/features)

## PR Type

What kind of change does this PR introduce?

<!-- Please check the one that applies to this PR using "x". -->

- [ ] Bugfix
- [x] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no API changes)
- [ ] Build related changes
- [ ] CI-related changes
- [ ] Documentation content changes
- [ ] Other... Please describe:

## Issue Number

<!-- Bugs and features must be linked to an issue. -->

Issue Number: #89 

## Does this PR introduce a breaking change?

<!-- If this PR contains a breaking change, please describe the impact
and migration path for existing applications below. -->

- [ ] Yes
- [x] No

## Other information

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

- **New Features**
- Introduced dismissible badges with customizable colors and dismissal
behavior.
	- Added a new Angular component for dismissible badges.

- **Documentation**
- Updated documentation to include a section for the dismissible badge
component with examples.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
MGREMY authored Dec 19, 2024
2 parents 8a07b30 + 6941e5b commit da6c209
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 2 deletions.
53 changes: 53 additions & 0 deletions apps/docs/docs/components/badge/_dismissable.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<flowbite-badge
[isDismissable]="true"
[onDismiss]="onDismiss">
Default
</flowbite-badge>
<flowbite-badge
[isDismissable]="true"
[onDismiss]="onDismiss"
color="primary">
Primary
</flowbite-badge>
<flowbite-badge
[isDismissable]="true"
[onDismiss]="onDismiss"
color="blue">
Blue
</flowbite-badge>
<flowbite-badge
[isDismissable]="true"
[onDismiss]="onDismiss"
color="red">
Red
</flowbite-badge>
<flowbite-badge
[isDismissable]="true"
[onDismiss]="onDismiss"
color="green">
Green
</flowbite-badge>
<flowbite-badge
[isDismissable]="true"
[onDismiss]="onDismiss"
color="yellow">
Yellow
</flowbite-badge>
<flowbite-badge
[isDismissable]="true"
[onDismiss]="onDismiss"
color="indigo">
Indigo
</flowbite-badge>
<flowbite-badge
[isDismissable]="true"
[onDismiss]="onDismiss"
color="purple">
Purple
</flowbite-badge>
<flowbite-badge
[isDismissable]="true"
[onDismiss]="onDismiss"
color="pink">
Pink
</flowbite-badge>
15 changes: 15 additions & 0 deletions apps/docs/docs/components/badge/_dismissable.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { BadgeComponent } from 'flowbite-angular/badge';

import { Component } from '@angular/core';

@Component({
selector: 'flowbite-demo-badge-dismissable',
imports: [BadgeComponent],
templateUrl: './_dismissable.component.html',
host: {
class: 'flex flex-wrap flex-row gap-3',
},
})
export class FlowbiteDismissableComponent {
onDismiss = () => alert('Badge have been dismissed');
}
16 changes: 16 additions & 0 deletions apps/docs/docs/components/badge/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,19 @@ keyword: BadgePage
```angular-ts file="./_icon-only.component.ts"#L1-L2 group="icon-only" name="typescript"
```

## Dismissable badge

{{ NgDocActions.demo('flowbiteDismissableComponent', {container: false}) }}

```angular-html file="./_dismissable.component.html" group="dismissable" name="html"
```

```angular-ts file="./_dismissable.component.ts"#L1-L1 group="dismissable" name="typescript"
```

```angular-ts file="./_dismissable.component.ts"#L14 group="dismissable" name="typescript"
```
2 changes: 2 additions & 0 deletions apps/docs/docs/components/badge/ng-doc.page.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ComponentCategory from '../ng-doc.category';
import { FlowbiteBorderedComponent } from './_bordered.component';
import { FlowbiteDefaultComponent } from './_default.component';
import { FlowbiteDismissableComponent } from './_dismissable.component';
import { FlowbiteIconOnlyComponent } from './_icon-only.component';
import { FlowbiteIconComponent } from './_icon.component';
import { FlowbiteLargeComponent } from './_large.component';
Expand All @@ -25,6 +26,7 @@ const badge: NgDocPage = {
flowbiteIconComponent: FlowbiteIconComponent,
flowbiteLargeComponent: FlowbiteLargeComponent,
flowbiteLinkComponent: FlowbiteLinkComponent,
flowbiteDismissableComponent: FlowbiteDismissableComponent,
},
};

Expand Down
75 changes: 74 additions & 1 deletion libs/flowbite-angular/badge/badge.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { BadgeThemeService } from './badge.theme.service';

import type { DeepPartial } from 'flowbite-angular';
import { BaseComponent, booleanToFlowbiteBoolean } from 'flowbite-angular';
import { IconComponent, IconRegistry } from 'flowbite-angular/icon';
import { FlowbiteRouterLinkDirective } from 'flowbite-angular/router-link';
import { CLOSE_SVG_ICON } from 'flowbite-angular/utils';

import {
ChangeDetectionStrategy,
Expand All @@ -14,6 +16,7 @@ import {
model,
ViewEncapsulation,
} from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

export const FLOWBITE_BADGE_COLOR_DEFAULT_VALUE = new InjectionToken<keyof BadgeColors>(
'FLOWBITE_BADGE_COLOR_DEFAULT_VALUE'
Expand All @@ -39,6 +42,14 @@ export const FLOWBITE_BADGE_CUSTOM_STYLE_DEFAULT_VALUE = new InjectionToken<
DeepPartial<BadgeTheme>
>('FLOWBITE_BADGE_CUSTOM_STYLE_DEFAULT_VALUE');

export const FLOWBITE_BADGE_IS_DISMISSABLE_DEFAULT_VALUE = new InjectionToken<boolean>(
'FLOWBITE_BADGE_IS_DISMISSABLE_DEFAULT_VALUE'
);

export const FLOWBITE_BADGE_ON_DISMISS_DEFAULT_VALUE = new InjectionToken<(() => void) | undefined>(
'FLOWBITE_BADGE_ON_DISMISS_DEFAULT_VALUE'
);

export const badgeDefaultValueProvider = makeEnvironmentProviders([
{
provide: FLOWBITE_BADGE_COLOR_DEFAULT_VALUE,
Expand All @@ -64,15 +75,38 @@ export const badgeDefaultValueProvider = makeEnvironmentProviders([
provide: FLOWBITE_BADGE_CUSTOM_STYLE_DEFAULT_VALUE,
useValue: {},
},
{
provide: FLOWBITE_BADGE_IS_DISMISSABLE_DEFAULT_VALUE,
useValue: false,
},
{
provide: FLOWBITE_BADGE_ON_DISMISS_DEFAULT_VALUE,
useValue: undefined,
},
]);

/**
* @see https://flowbite.com/docs/components/badge/
*/
@Component({
standalone: true,
imports: [IconComponent],
selector: 'flowbite-badge',
template: `<ng-content />`,
template: `
<ng-content />
@if (isDismissable()) {
<button
type="button"
[class]="contentClasses()!.closeButtonClass"
aria-label="Close"
(click)="onDismissClick()">
<span class="sr-only">Close</span>
<flowbite-icon
svgIcon="flowbite-angular:close"
class="h-3 w-3" />
</button>
}
`,
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
Expand All @@ -85,6 +119,14 @@ export class BadgeComponent extends BaseComponent<BadgeClass> {
* Service injected used to generate class
*/
public readonly themeService = inject(BadgeThemeService);
/**
* `IcoRegistry` service
*/
public readonly iconRegistry = inject(IconRegistry);
/**
* `DomSanitizer` service
*/
public readonly domSanitizer = inject(DomSanitizer);

//#region properties
/**
Expand All @@ -95,6 +137,8 @@ export class BadgeComponent extends BaseComponent<BadgeClass> {
public color = model(inject(FLOWBITE_BADGE_COLOR_DEFAULT_VALUE));
/**
* Set if the badge has border
*
* @default false
*/
public hasBorder = model(inject(FLOWBITE_BADGE_HAS_BORDER_DEFAULT_VALUE));
/**
Expand All @@ -119,6 +163,18 @@ export class BadgeComponent extends BaseComponent<BadgeClass> {
* Set the custom style for this badge
*/
public customStyle = model(inject(FLOWBITE_BADGE_CUSTOM_STYLE_DEFAULT_VALUE));
/**
* Set if the badge is dismissable
*
* @default false
*/
public isDismissable = model(inject(FLOWBITE_BADGE_IS_DISMISSABLE_DEFAULT_VALUE));
/**
* Set the function called when the badge is dismissed
*
* @default undefined
*/
public onDismiss = model(inject(FLOWBITE_BADGE_ON_DISMISS_DEFAULT_VALUE));
//#endregion

//#region BaseComponent implementation
Expand All @@ -133,5 +189,22 @@ export class BadgeComponent extends BaseComponent<BadgeClass> {
customStyle: this.customStyle(),
});
}

public override init(): void {
this.iconRegistry.addRawSvgIconInNamepsace(
'flowbite-angular',
'close',
this.domSanitizer.bypassSecurityTrustHtml(CLOSE_SVG_ICON)
);
}
//#endregion

/**
* Call the onDismiss function if it's not undefined
*/
public onDismissClick() {
const func = this.onDismiss();

if (func) func();
}
}
1 change: 1 addition & 0 deletions libs/flowbite-angular/badge/badge.theme.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export class BadgeThemeService implements FlowbiteThemeService<BadgeProperties>
theme.root.isIconOnly[properties.isIconOnly],
theme.root.link[properties.link ? 'enabled' : 'disabled']
),
closeButtonClass: twMerge(theme.closeButton.base, theme.closeButton.color[properties.color]),
};

return output;
Expand Down
23 changes: 22 additions & 1 deletion libs/flowbite-angular/badge/badge.theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ export interface BadgeTheme {
isIconOnly: FlowbiteBoolean;
link: FlowbiteBoolean;
};
closeButton: {
base: string;
color: BadgeColors;
};
}

/**
Expand Down Expand Up @@ -99,9 +103,26 @@ export const badgeTheme: BadgeTheme = createTheme({
disabled: 'px-2 py-0.5',
},
},
closeButton: {
base: 'ms-1 inline-flex items-center rounded-sm p-1 focus:ring-2',
color: {
primary:
'text-primary-500 dark:text-primary-600 hover:bg-primary-200 dark:hover:bg-primary-300',
dark: 'text-gray-500 dark:text-gray-600 hover:bg-gray-200 dark:hover:bg-gray-300',
blue: 'text-blue-500 dark:text-blue-600 hover:bg-blue-200 dark:hover:bg-blue-300',
red: 'text-red-500 dark:text-red-600 hover:bg-red-200 dark:hover:bg-red-300',
green: 'text-green-500 dark:text-green-600 hover:bg-green-200 dark:hover:bg-green-300',
yellow: 'text-yellow-500 dark:text-yellow-600 hover:bg-yellow-200 dark:hover:bg-yellow-300',
indigo: 'text-indigo-500 dark:text-indigo-600 hover:bg-indigo-200 dark:hover:bg-indigo-300',
purple: 'text-purple-500 dark:text-purple-600 hover:bg-purple-200 dark:hover:bg-purple-300',
pink: 'text-pink-500 dark:text-pink-600 hover:bg-pink-200 dark:hover:bg-pink-300',
},
},
});

/**
* Generated class definition for `BadgeComponent`
*/
export type BadgeClass = FlowbiteClass;
export interface BadgeClass extends FlowbiteClass {
closeButtonClass: string;
}

0 comments on commit da6c209

Please sign in to comment.