Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(badge): add dismissable badge #101

Merged
merged 2 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}
Loading