Skip to content

Commit 6543175

Browse files
committed
feat: create clickable/selectable tag components
Signed-off-by: Akshat Patel <[email protected]>
1 parent 3793bfa commit 6543175

File tree

5 files changed

+222
-8
lines changed

5 files changed

+222
-8
lines changed

src/tag/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
export * from "./tag-filter.component";
22
export * from "./tag.component";
3+
export * from "./tag-icon.directive";
4+
export * from "./tag-selectable.component";
35
export * from "./tag.module";
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {
2+
ChangeDetectionStrategy,
3+
Component,
4+
HostBinding,
5+
Input
6+
} from "@angular/core";
7+
import { Tag } from "./tag.component";
8+
9+
@Component({
10+
selector: "cds-tag-operational, ibm-tag-operational",
11+
template: `
12+
<ng-container *ngIf="!skeleton">
13+
<ng-content select="[cdsTagIcon],[ibmTagIcon]"></ng-content>
14+
<span class="cds--tag__label">
15+
<ng-content></ng-content>
16+
</span>
17+
</ng-container>
18+
`,
19+
changeDetection: ChangeDetectionStrategy.OnPush
20+
})
21+
export class TagOperationalComponent extends Tag {
22+
@HostBinding("attr.role") role = "button";
23+
@HostBinding("attr.type") buttonType = "button";
24+
@HostBinding("attr.tabindex") tabIndex = 0;
25+
26+
@Input() disabled = false;
27+
28+
/**
29+
* @todo
30+
* Remove `cds--tag--${this.size}` in v7
31+
*/
32+
@HostBinding("attr.class") get attrClass() {
33+
const disabledClass = this.disabled ? "cds--tag--disabled" : "";
34+
const sizeClass = `cds--tag--${this.size} cds--layout--size-${this.size}`;
35+
const skeletonClass = this.skeleton ? "cds--skeleton" : "";
36+
37+
return `cds--tag cds--tag--operational cds--tag--${this.type} ${disabledClass} ${sizeClass} ${skeletonClass} ${this.class}`;
38+
}
39+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {
2+
ChangeDetectionStrategy,
3+
Component,
4+
EventEmitter,
5+
HostBinding,
6+
HostListener,
7+
Input,
8+
Output
9+
} from "@angular/core";
10+
11+
@Component({
12+
selector: "cds-tag-selectable, ibm-tag-selectable",
13+
template: `
14+
<ng-container *ngIf="!skeleton">
15+
<ng-content select="[cdsTagIcon],[ibmTagIcon]"></ng-content>
16+
<span class="cds--tag__label">
17+
<ng-content></ng-content>
18+
</span>
19+
</ng-container>
20+
`,
21+
changeDetection: ChangeDetectionStrategy.OnPush
22+
})
23+
export class TagSelectableComponent {
24+
@HostBinding("attr.role") role = "button";
25+
@HostBinding("attr.type") buttonType = "button";
26+
@HostBinding("attr.tabindex") tabIndex = 0;
27+
@HostBinding("attr.aria-pressed") get ariaPressed() {
28+
return this.selected;
29+
}
30+
31+
@Input() size: "sm" | "md" | "lg" = "md";
32+
@Input() skeleton = false;
33+
@Input() disabled = false;
34+
@Input() class = "";
35+
@Input() selected = false;
36+
37+
@Output() selectedChange = new EventEmitter<boolean>();
38+
39+
@HostListener("click")
40+
onClick() {
41+
this.selected = !this.selected;
42+
this.selectedChange.emit(this.selected);
43+
}
44+
45+
/**
46+
* @todo
47+
* Remove `cds--tag--${this.size}` in v7
48+
*/
49+
@HostBinding("attr.class") get attrClass() {
50+
const disabledClass = this.disabled ? "cds--tag--disabled" : "";
51+
const sizeClass = `cds--tag--${this.size} cds--layout--size-${this.size}`;
52+
const skeletonClass = this.skeleton ? "cds--skeleton" : "";
53+
const selectedClass = this.selected ? "cds--tag--selectable-selected" : "";
54+
55+
return `cds--tag cds--tag--selectable ${selectedClass} ${disabledClass} ${sizeClass} ${skeletonClass} ${this.class}`;
56+
}
57+
}

src/tag/tag.module.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,25 @@ import { CommonModule } from "@angular/common";
44
import { Tag } from "./tag.component";
55
import { TagFilter } from "./tag-filter.component";
66
import { IconModule } from "carbon-components-angular/icon";
7+
import { TagIconDirective } from "./tag-icon.directive";
8+
import { TagSelectableComponent } from "./tag-selectable.component";
9+
import { TagOperationalComponent } from "./tag-operational.component";
710

811
@NgModule({
9-
declarations: [ Tag, TagFilter ],
10-
exports: [ Tag, TagFilter ],
11-
imports: [ CommonModule, IconModule ]
12+
declarations: [
13+
Tag,
14+
TagFilter,
15+
TagIconDirective,
16+
TagSelectableComponent,
17+
TagOperationalComponent
18+
],
19+
exports: [
20+
Tag,
21+
TagFilter,
22+
TagIconDirective,
23+
TagSelectableComponent,
24+
TagOperationalComponent
25+
],
26+
imports: [CommonModule, IconModule]
1227
})
13-
export class TagModule { }
28+
export class TagModule {}

src/tag/tag.stories.ts

Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,24 @@
22

33
import { moduleMetadata, Meta } from "@storybook/angular";
44
import { TagModule, Tag } from "./";
5+
import { IconModule } from "../icon";
6+
import { PopoverModule } from "../popover";
57

68
export default {
79
title: "Components/Tag",
810
decorators: [
911
moduleMetadata({
10-
imports: [TagModule]
12+
imports: [
13+
TagModule,
14+
IconModule,
15+
PopoverModule
16+
]
1117
})
1218
],
1319
args: {
14-
type: "red"
20+
size: "md",
21+
type: "red",
22+
skeleton: false
1523
},
1624
argTypes: {
1725
type: {
@@ -37,7 +45,15 @@ export default {
3745
const Template = (args) => ({
3846
props: args,
3947
template: `
40-
<cds-tag [type]="type" [size]="size">Tag</cds-tag>
48+
<cds-tag
49+
[type]="type"
50+
[skeleton]="skeleton"
51+
[size]="size">
52+
<div cdsTagIcon>
53+
<svg ibmIcon="settings" size="16"></svg>
54+
</div>
55+
Read only
56+
</cds-tag>
4157
`
4258
});
4359
export const Basic = Template.bind({});
@@ -48,10 +64,95 @@ const FilteredTemplate = (args) => ({
4864
<cds-tag-filter
4965
[type]="type"
5066
[size]="size"
67+
[skeleton]="skeleton"
5168
title="Filter"
5269
closeButtonLabel="Clear">
53-
filter
70+
<div cdsTagIcon>
71+
<svg ibmIcon="settings" size="16"></svg>
72+
</div>
73+
Filtered
5474
</cds-tag-filter>
5575
`
5676
});
5777
export const Filter = FilteredTemplate.bind({});
78+
79+
const SelectedTagTemplate = (args) => ({
80+
props: args,
81+
template: `
82+
<cds-tag-selectable
83+
[size]="size"
84+
[skeleton]="skeleton"
85+
[selected]="selected"
86+
(selectedChange)="selectedChange($event)"
87+
(click)="onClick($event)">
88+
<div cdsTagIcon>
89+
<svg ibmIcon="settings" size="16"></svg>
90+
</div>
91+
Selectable
92+
</cds-tag-selectable>
93+
`
94+
});
95+
export const SelectedTag = SelectedTagTemplate.bind({});
96+
SelectedTag.args = {
97+
selected: false
98+
};
99+
SelectedTag.argTypes = {
100+
onClick: { action: "clicked" },
101+
selectedChange: { action: "Selected change" }
102+
};
103+
104+
const OperationalTagTemplate = (args) => ({
105+
props: args,
106+
template: `
107+
<cds-tag-operational
108+
type="cyan"
109+
[size]="size"
110+
[skeleton]="skeleton"
111+
(click)="onClick($event)">
112+
<div cdsTagIcon>
113+
<svg ibmIcon="settings" size="16"></svg>
114+
</div>
115+
Operational
116+
</cds-tag-operational>
117+
118+
119+
<div
120+
cdsPopover
121+
[isOpen]="isOpen"
122+
[highContrast]="true">
123+
<cds-tag-operational
124+
[type]="type"
125+
[size]="size"
126+
[skeleton]="skeleton"
127+
(click)="isOpen = !isOpen">
128+
<div cdsTagIcon>
129+
<svg ibmIcon="settings" size="16"></svg>
130+
</div>
131+
Operational w/ popover
132+
</cds-tag-operational>
133+
<cds-popover-content>
134+
<div class="popover-content">
135+
Tag 1 name <br>
136+
Tag 2 name <br>
137+
Tag 3 name <br>
138+
Tag 4 name <br>
139+
<cds-tag type="green">Tag 5 name</cds-tag>
140+
</div>
141+
</cds-popover-content>
142+
</div>
143+
`,
144+
styles: [
145+
`.popover-content {
146+
line-height: 1.5;
147+
padding: 1rem;
148+
font-size: 14px;
149+
}`
150+
]
151+
});
152+
export const OperationalTag = OperationalTagTemplate.bind({});
153+
// OperationalTag.args = {
154+
// isOpen: false
155+
// };
156+
OperationalTag.argTypes = {
157+
onClick: { action: "clicked" }
158+
};

0 commit comments

Comments
 (0)