[CL-38] Follow Angular styleguide naming convention, simplify hostbinding logic (#787)

This commit is contained in:
Oscar Hinton 2022-06-02 11:16:59 +02:00 committed by GitHub
parent 78d2f957d5
commit 2b647df001
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 92 additions and 113 deletions

View File

@ -1,4 +1,4 @@
import { Directive, ElementRef, HostBinding, Input, OnChanges, OnInit } from "@angular/core";
import { Directive, ElementRef, HostBinding, Input } from "@angular/core";
type BadgeTypes = "primary" | "secondary" | "success" | "danger" | "warning" | "info";
@ -21,28 +21,10 @@ const hoverStyles: Record<BadgeTypes, string[]> = {
};
@Directive({
selector: "span[bit-badge], a[bit-badge], button[bit-badge]",
selector: "span[bitBadge], a[bitBadge], button[bitBadge]",
})
export class BadgeComponent implements OnInit, OnChanges {
@HostBinding("class") @Input("class") classList = "";
@Input() badgeType: BadgeTypes = "primary";
private isSpan = false;
constructor(private el: ElementRef<Element>) {
this.isSpan = el?.nativeElement?.nodeName == "SPAN";
}
ngOnInit(): void {
this.classList = this.classes.join(" ");
}
ngOnChanges() {
this.ngOnInit();
}
get classes() {
export class BadgeDirective {
@HostBinding("class") get classList() {
return [
"tw-inline-block",
"tw-py-1",
@ -63,6 +45,14 @@ export class BadgeComponent implements OnInit, OnChanges {
"focus:tw-ring-primary-700",
]
.concat(styles[this.badgeType])
.concat(this.isSpan ? [] : hoverStyles[this.badgeType]);
.concat(this.hasHoverEffects ? hoverStyles[this.badgeType] : []);
}
@Input() badgeType: BadgeTypes = "primary";
private hasHoverEffects = false;
constructor(el: ElementRef<Element>) {
this.hasHoverEffects = el?.nativeElement?.nodeName != "SPAN";
}
}

View File

@ -1,11 +1,11 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { BadgeComponent } from "./badge.component";
import { BadgeDirective } from "./badge.directive";
@NgModule({
imports: [CommonModule],
exports: [BadgeComponent],
declarations: [BadgeComponent],
exports: [BadgeDirective],
declarations: [BadgeDirective],
})
export class BadgeModule {}

View File

@ -1,12 +1,12 @@
import { Meta, Story } from "@storybook/angular";
import { BadgeComponent } from "./badge.component";
import { BadgeDirective } from "./badge.directive";
export default {
title: "Jslib/Badge",
component: BadgeComponent,
component: BadgeDirective,
args: {
type: "primary",
badgeType: "primary",
},
parameters: {
design: {
@ -16,14 +16,14 @@ export default {
},
} as Meta;
const Template: Story<BadgeComponent> = (args: BadgeComponent) => ({
const Template: Story<BadgeDirective> = (args: BadgeDirective) => ({
props: args,
template: `
<span class="tw-text-main">Span </span><span bit-badge [badgeType]="type">Badge</span>
<span class="tw-text-main">Span </span><span bitBadge [badgeType]="badgeType">Badge</span>
<br><br>
<span class="tw-text-main">Link </span><a href="#" bit-badge [badgeType]="type">Badge</a>
<span class="tw-text-main">Link </span><a href="#" bitBadge [badgeType]="badgeType">Badge</a>
<br><br>
<span class="tw-text-main">Button </span><button bit-badge [badgeType]="type">Badge</button>
<span class="tw-text-main">Button </span><button bitBadge [badgeType]="badgeType">Badge</button>
`,
});
@ -32,25 +32,25 @@ Primary.args = {};
export const Secondary = Template.bind({});
Secondary.args = {
type: "secondary",
badgeType: "secondary",
};
export const Success = Template.bind({});
Success.args = {
type: "success",
badgeType: "success",
};
export const Danger = Template.bind({});
Danger.args = {
type: "danger",
badgeType: "danger",
};
export const Warning = Template.bind({});
Warning.args = {
type: "warning",
badgeType: "warning",
};
export const Info = Template.bind({});
Info.args = {
type: "info",
badgeType: "info",
};

View File

@ -1,2 +1,2 @@
export * from "./badge.component";
export * from "./badge.directive";
export * from "./badge.module";

View File

@ -67,8 +67,8 @@ describe("Button", () => {
@Component({
selector: "test-app",
template: `
<button type="button" bit-button [buttonType]="buttonType" [block]="block">Button</button>
<a href="#" bit-button [buttonType]="buttonType" [block]="block"> Link </a>
<button type="button" bitButton [buttonType]="buttonType" [block]="block">Button</button>
<a href="#" bitButton [buttonType]="buttonType" [block]="block"> Link </a>
`,
})
class TestApp {

View File

@ -1,8 +1,8 @@
import { Input, HostBinding, OnChanges, Directive, OnInit } from "@angular/core";
import { Input, HostBinding, Directive } from "@angular/core";
export type ButtonTypes = "primary" | "secondary" | "danger";
const buttonStyles: Record<ButtonTypes, string> = {
const buttonStyles: Record<ButtonTypes, string[]> = {
primary: [
"tw-border-primary-500",
"tw-bg-primary-500",
@ -11,7 +11,7 @@ const buttonStyles: Record<ButtonTypes, string> = {
"hover:tw-border-primary-700",
"focus:tw-bg-primary-700",
"focus:tw-border-primary-700",
].join(" "),
],
secondary: [
"tw-bg-transparent",
"tw-border-text-muted",
@ -22,7 +22,7 @@ const buttonStyles: Record<ButtonTypes, string> = {
"focus:tw-bg-secondary-500",
"focus:tw-border-secondary-500",
"focus:!tw-text-contrast",
].join(" "),
],
danger: [
"tw-bg-transparent",
"tw-border-danger-500",
@ -33,30 +33,14 @@ const buttonStyles: Record<ButtonTypes, string> = {
"focus:tw-bg-danger-500",
"focus:tw-border-danger-500",
"focus:!tw-text-contrast",
].join(" "),
],
};
@Directive({
selector: "button[bit-button], a[bit-button]",
selector: "button[bitButton], a[bitButton]",
})
export class ButtonComponent implements OnInit, OnChanges {
@HostBinding("class") @Input() classList = "";
@Input()
buttonType: ButtonTypes = "secondary";
@Input()
block = false;
ngOnInit(): void {
this.classList = this.classes.join(" ");
}
ngOnChanges() {
this.ngOnInit();
}
get classes(): string[] {
export class ButtonDirective {
@HostBinding("class") get classList() {
return [
"tw-font-semibold",
"tw-py-1.5",
@ -75,8 +59,14 @@ export class ButtonComponent implements OnInit, OnChanges {
"focus:tw-ring-offset-2",
"focus:tw-ring-primary-700",
"focus:tw-z-10",
this.block ? "tw-w-full tw-block" : "tw-inline-block",
buttonStyles[this.buttonType ?? "secondary"],
];
]
.concat(this.block ? ["tw-w-full", "tw-block"] : ["tw-inline-block"])
.concat(buttonStyles[this.buttonType] ?? []);
}
@Input()
buttonType: ButtonTypes = "secondary";
@Input()
block = false;
}

View File

@ -1,11 +1,11 @@
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { ButtonComponent } from "./button.component";
import { ButtonDirective } from "./button.directive";
@NgModule({
imports: [CommonModule],
exports: [ButtonComponent],
declarations: [ButtonComponent],
exports: [ButtonDirective],
declarations: [ButtonDirective],
})
export class ButtonModule {}

View File

@ -1,10 +1,10 @@
import { Meta, Story } from "@storybook/angular";
import { ButtonComponent } from "./button.component";
import { ButtonDirective } from "./button.directive";
export default {
title: "Jslib/Button",
component: ButtonComponent,
component: ButtonDirective,
args: {
buttonType: "primary",
},
@ -16,11 +16,11 @@ export default {
},
} as Meta;
const Template: Story<ButtonComponent> = (args: ButtonComponent) => ({
const Template: Story<ButtonDirective> = (args: ButtonDirective) => ({
props: args,
template: `
<button bit-button [buttonType]="buttonType" [block]="block">Button</button>
<a bit-button [buttonType]="buttonType" [block]="block" href="#" class="tw-ml-2">Link</a>
<button bitButton [buttonType]="buttonType" [block]="block">Button</button>
<a bitButton [buttonType]="buttonType" [block]="block" href="#" class="tw-ml-2">Link</a>
`,
});
@ -42,9 +42,9 @@ Danger.args = {
const DisabledTemplate: Story = (args) => ({
props: args,
template: `
<button bit-button disabled buttonType="primary" class="tw-mr-2">Primary</button>
<button bit-button disabled buttonType="secondary" class="tw-mr-2">Secondary</button>
<button bit-button disabled buttonType="danger" class="tw-mr-2">Danger</button>
<button bitButton disabled buttonType="primary" class="tw-mr-2">Primary</button>
<button bitButton disabled buttonType="secondary" class="tw-mr-2">Secondary</button>
<button bitButton disabled buttonType="danger" class="tw-mr-2">Danger</button>
`,
});

View File

@ -1,2 +1,2 @@
export * from "./button.component";
export * from "./button.directive";
export * from "./button.module";

View File

@ -68,7 +68,7 @@ const Template: Story<BitFormFieldComponent> = (args: BitFormFieldComponent) =>
<input bitInput formControlName="email" />
</bit-form-field>
<button type="submit" bit-button buttonType="primary">Submit</button>
<button type="submit" bitButton buttonType="primary">Submit</button>
<bit-error-summary [formGroup]="formObj"></bit-error-summary>
</form>
`,

View File

@ -87,7 +87,7 @@ const Template: Story<BitFormFieldComponent> = (args: BitFormFieldComponent) =>
<input bitInput formControlName="email" />
</bit-form-field>
<button type="submit" bit-button buttonType="primary">Submit</button>
<button type="submit" bitButton buttonType="primary">Submit</button>
</form>
`,
});
@ -167,12 +167,12 @@ const ButtonGroupTemplate: Story<BitFormFieldComponent> = (args: BitFormFieldCom
<bit-form-field>
<bit-label>Label</bit-label>
<input bitInput placeholder="Placeholder" />
<button bitPrefix bit-button>Button</button>
<button bitPrefix bit-button>Button</button>
<button bitSuffix bit-button>
<button bitPrefix bitButton>Button</button>
<button bitPrefix bitButton>Button</button>
<button bitSuffix bitButton>
<i aria-hidden="true" class="bwi bwi-lg bwi-eye"></i>
</button>
<button bitSuffix bit-button>
<button bitSuffix bitButton>
<i aria-hidden="true" class="bwi bwi-lg bwi-clone"></i>
</button>
</bit-form-field>

View File

@ -1,5 +1,5 @@
export * from "./menu.module";
export * from "./menu.component";
export * from "./menu-trigger-for.directive";
export * from "./menu-item.component";
export * from "./menu-item.directive";
export * from "./menu-divider.component";

View File

@ -1,11 +1,10 @@
import { FocusableOption } from "@angular/cdk/a11y";
import { Component, ElementRef, HostBinding } from "@angular/core";
import { Directive, ElementRef, HostBinding } from "@angular/core";
@Component({
selector: "[bit-menu-item]",
template: `<ng-content></ng-content>`,
@Directive({
selector: "[bitMenuItem]",
})
export class MenuItemComponent implements FocusableOption {
export class MenuItemDirective implements FocusableOption {
@HostBinding("class") classList = [
"tw-block",
"tw-py-1",
@ -25,7 +24,7 @@ export class MenuItemComponent implements FocusableOption {
"focus:tw-ring-primary-700",
"active:!tw-ring-0",
"active:!tw-ring-offset-0",
].join(" ");
];
@HostBinding("attr.role") role = "menuitem";
@HostBinding("tabIndex") tabIndex = "-1";

View File

@ -69,8 +69,8 @@ describe("Menu", () => {
<button type="button" [bitMenuTriggerFor]="testMenu" class="testclass">Open menu</button>
<bit-menu #testMenu>
<a id="item1" bit-menu-item>Item 1</a>
<a id="item2" bit-menu-item>Item 2</a>
<a id="item1" bitMenuItem>Item 1</a>
<a id="item2" bitMenuItem>Item 2</a>
</bit-menu>
`,
})

View File

@ -10,7 +10,7 @@ import {
AfterContentInit,
} from "@angular/core";
import { MenuItemComponent } from "./menu-item.component";
import { MenuItemDirective } from "./menu-item.directive";
@Component({
selector: "bit-menu",
@ -20,9 +20,9 @@ import { MenuItemComponent } from "./menu-item.component";
export class MenuComponent implements AfterContentInit {
@ViewChild(TemplateRef) templateRef: TemplateRef<any>;
@Output() closed = new EventEmitter<void>();
@ContentChildren(MenuItemComponent, { descendants: true })
menuItems: QueryList<MenuItemComponent>;
keyManager: FocusKeyManager<MenuItemComponent>;
@ContentChildren(MenuItemDirective, { descendants: true })
menuItems: QueryList<MenuItemDirective>;
keyManager: FocusKeyManager<MenuItemDirective>;
ngAfterContentInit() {
this.keyManager = new FocusKeyManager(this.menuItems).withWrap();

View File

@ -3,13 +3,13 @@ import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { MenuDividerComponent } from "./menu-divider.component";
import { MenuItemComponent } from "./menu-item.component";
import { MenuItemDirective } from "./menu-item.directive";
import { MenuTriggerForDirective } from "./menu-trigger-for.directive";
import { MenuComponent } from "./menu.component";
@NgModule({
imports: [CommonModule, OverlayModule],
declarations: [MenuComponent, MenuTriggerForDirective, MenuItemComponent, MenuDividerComponent],
exports: [MenuComponent, MenuTriggerForDirective, MenuItemComponent, MenuDividerComponent],
declarations: [MenuComponent, MenuTriggerForDirective, MenuItemDirective, MenuDividerComponent],
exports: [MenuComponent, MenuTriggerForDirective, MenuItemDirective, MenuDividerComponent],
})
export class MenuModule {}

View File

@ -4,7 +4,7 @@ import { Meta, moduleMetadata, Story } from "@storybook/angular";
import { ButtonModule } from "../button/button.module";
import { MenuDividerComponent } from "./menu-divider.component";
import { MenuItemComponent } from "./menu-item.component";
import { MenuItemDirective } from "./menu-item.directive";
import { MenuTriggerForDirective } from "./menu-trigger-for.directive";
import { MenuComponent } from "./menu.component";
@ -16,7 +16,7 @@ export default {
declarations: [
MenuTriggerForDirective,
MenuComponent,
MenuItemComponent,
MenuItemDirective,
MenuDividerComponent,
],
imports: [OverlayModule, ButtonModule],
@ -34,11 +34,11 @@ const Template: Story<MenuTriggerForDirective> = (args: MenuTriggerForDirective)
props: args,
template: `
<bit-menu #myMenu="menuComponent">
<a href="#" bit-menu-item>Anchor link</a>
<a href="#" bit-menu-item>Another link</a>
<button type="button" bit-menu-item>Button</button>
<a href="#" bitMenuItem>Anchor link</a>
<a href="#" bitMenuItem>Another link</a>
<button type="button" bitMenuItem>Button</button>
<bit-menu-divider></bit-menu-divider>
<button type="button" bit-menu-item>Button after divider</button>
<button type="button" bitMenuItem>Button after divider</button>
</bit-menu>
<div class="tw-h-40">
@ -53,15 +53,15 @@ const TemplateWithButton: Story<MenuTriggerForDirective> = (args: MenuTriggerFor
props: args,
template: `
<div class="tw-h-40">
<button bit-button [buttonType]="secondary" [bitMenuTriggerFor]="myMenu">Open menu</button>
<button bitButton buttonType="secondary" [bitMenuTriggerFor]="myMenu">Open menu</button>
</div>
<bit-menu #myMenu>
<a href="#" bit-menu-item>Anchor link</a>
<a href="#" bit-menu-item>Another link</a>
<button type="button" bit-menu-item>Button</button>
<a href="#" bitMenuItem>Anchor link</a>
<a href="#" bitMenuItem>Another link</a>
<button type="button" bitMenuItem>Button</button>
<bit-menu-divider></bit-menu-divider>
<button type="button" bit-menu-item>Button after divider</button>
<button type="button" bitMenuItem>Button after divider</button>
</bit-menu>`,
});