19 changed files with 338 additions and 217 deletions
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
import { DialogRef } from "@angular/cdk/dialog"; |
||||
import { Directive, Input, Optional } from "@angular/core"; |
||||
|
||||
@Directive({ |
||||
selector: "[bitDialogClose]", |
||||
host: { |
||||
"(click)": "close()", |
||||
}, |
||||
}) |
||||
export class DialogCloseDirective { |
||||
@Input("bit-dialog-close") dialogResult: any; |
||||
|
||||
constructor(@Optional() public dialogRef: DialogRef<any>) {} |
||||
|
||||
close() { |
||||
this.dialogRef.close(this.dialogResult); |
||||
} |
||||
} |
||||
@ -0,0 +1,78 @@
@@ -0,0 +1,78 @@
|
||||
import { DialogModule, DialogRef, DIALOG_DATA } from "@angular/cdk/dialog"; |
||||
import { Component, Inject } from "@angular/core"; |
||||
import { Meta, moduleMetadata, Story } from "@storybook/angular"; |
||||
|
||||
import { ButtonModule } from "../button"; |
||||
|
||||
import { DialogCloseDirective } from "./dialog-close.directive"; |
||||
import { DialogService } from "./dialog.service"; |
||||
import { DialogComponent } from "./dialog/dialog.component"; |
||||
|
||||
interface Animal { |
||||
animal: string; |
||||
} |
||||
|
||||
@Component({ |
||||
selector: "app-story-dialog", |
||||
template: `<button bitButton (click)="openDialog()">Open Dialog</button>`, |
||||
}) |
||||
class StoryDialogComponent { |
||||
constructor(public dialogService: DialogService) {} |
||||
|
||||
openDialog() { |
||||
this.dialogService.open(StoryDialogContentComponent, { |
||||
data: { |
||||
animal: "panda", |
||||
}, |
||||
}); |
||||
} |
||||
} |
||||
|
||||
@Component({ |
||||
selector: "story-dialog-content", |
||||
template: ` |
||||
<bit-dialog [dialogSize]="large"> |
||||
<span bit-dialog-title>Dialog Title</span> |
||||
<span bit-dialog-content> |
||||
Dialog body text goes here. |
||||
<br /> |
||||
Animal: {{ animal }} |
||||
</span> |
||||
<div bit-dialog-footer class="tw-flex tw-flex-row tw-gap-2"> |
||||
<button bitButton buttonType="primary" (click)="dialogRef.close()">Save</button> |
||||
<button bitButton buttonType="secondary" bitDialogClose>Cancel</button> |
||||
</div> |
||||
</bit-dialog> |
||||
`,
|
||||
}) |
||||
class StoryDialogContentComponent { |
||||
constructor(public dialogRef: DialogRef, @Inject(DIALOG_DATA) private data: Animal) {} |
||||
|
||||
get animal() { |
||||
return this.data?.animal; |
||||
} |
||||
} |
||||
|
||||
export default { |
||||
title: "Component Library/Dialogs/Service", |
||||
component: StoryDialogComponent, |
||||
decorators: [ |
||||
moduleMetadata({ |
||||
declarations: [DialogComponent, StoryDialogContentComponent, DialogCloseDirective], |
||||
imports: [ButtonModule, DialogModule], |
||||
providers: [DialogService], |
||||
}), |
||||
], |
||||
parameters: { |
||||
design: { |
||||
type: "figma", |
||||
url: "https://www.figma.com/file/Zt3YSeb6E6lebAffrNLa0h/Tailwind-Component-Library", |
||||
}, |
||||
}, |
||||
} as Meta; |
||||
|
||||
const Template: Story<StoryDialogComponent> = (args: StoryDialogComponent) => ({ |
||||
props: args, |
||||
}); |
||||
|
||||
export const Default = Template.bind({}); |
||||
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
import { DialogModule as CdkDialogModule } from "@angular/cdk/dialog"; |
||||
import { CommonModule } from "@angular/common"; |
||||
import { NgModule } from "@angular/core"; |
||||
|
||||
import { DialogCloseDirective } from "./dialog-close.directive"; |
||||
import { DialogService } from "./dialog.service"; |
||||
import { DialogComponent } from "./dialog/dialog.component"; |
||||
import { SimpleDialogComponent } from "./simple-dialog/simple-dialog.component"; |
||||
|
||||
@NgModule({ |
||||
imports: [CommonModule, CdkDialogModule], |
||||
declarations: [DialogCloseDirective, DialogComponent, SimpleDialogComponent], |
||||
exports: [CdkDialogModule, DialogComponent, SimpleDialogComponent], |
||||
providers: [DialogService], |
||||
}) |
||||
export class DialogModule {} |
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
import { Dialog, DialogConfig, DialogRef } from "@angular/cdk/dialog"; |
||||
import { ComponentType } from "@angular/cdk/overlay"; |
||||
import { Injectable, TemplateRef } from "@angular/core"; |
||||
|
||||
@Injectable() |
||||
export class DialogService extends Dialog { |
||||
override open<R = unknown, D = unknown, C = unknown>( |
||||
componentOrTemplateRef: ComponentType<C> | TemplateRef<C>, |
||||
config?: DialogConfig<D, DialogRef<R, C>> |
||||
): DialogRef<R, C> { |
||||
config = { |
||||
backdropClass: ["tw-fixed", "tw-bg-black", "tw-bg-opacity-30", "tw-inset-0", "tw-z-40"], |
||||
...config, |
||||
}; |
||||
|
||||
return super.open(componentOrTemplateRef, config); |
||||
} |
||||
} |
||||
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
import { Component, Input } from "@angular/core"; |
||||
|
||||
@Component({ |
||||
selector: "bit-dialog", |
||||
templateUrl: "./dialog.component.html", |
||||
}) |
||||
export class DialogComponent { |
||||
@Input() dialogSize: "small" | "default" | "large" = "default"; |
||||
|
||||
get width() { |
||||
switch (this.dialogSize) { |
||||
case "small": { |
||||
return "tw-w-96"; |
||||
} |
||||
case "large": { |
||||
return "tw-w-75vw"; |
||||
} |
||||
default: { |
||||
return "tw-w-50vw"; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
import { Meta, moduleMetadata, Story } from "@storybook/angular"; |
||||
|
||||
import { ButtonModule } from "../../button"; |
||||
|
||||
import { DialogComponent } from "./dialog.component"; |
||||
|
||||
export default { |
||||
title: "Component Library/Dialogs/Dialog", |
||||
component: DialogComponent, |
||||
decorators: [ |
||||
moduleMetadata({ |
||||
imports: [ButtonModule], |
||||
}), |
||||
], |
||||
args: { |
||||
dialogSize: "small", |
||||
}, |
||||
parameters: { |
||||
design: { |
||||
type: "figma", |
||||
url: "https://www.figma.com/file/Zt3YSeb6E6lebAffrNLa0h/Tailwind-Component-Library", |
||||
}, |
||||
}, |
||||
} as Meta; |
||||
|
||||
const Template: Story<DialogComponent> = (args: DialogComponent) => ({ |
||||
props: args, |
||||
template: ` |
||||
<bit-dialog [dialogSize]="dialogSize"> |
||||
<span bit-dialog-title>{{title}}</span> |
||||
<span bit-dialog-content>Dialog body text goes here.</span> |
||||
<div bit-dialog-footer class="tw-flex tw-flex-row tw-gap-2"> |
||||
<button bitButton buttonType="primary">Save</button> |
||||
<button bitButton buttonType="secondary">Cancel</button> |
||||
</div> |
||||
</bit-dialog> |
||||
`,
|
||||
}); |
||||
|
||||
export const Default = Template.bind({}); |
||||
Default.args = { |
||||
dialogSize: "default", |
||||
title: "Default", |
||||
}; |
||||
|
||||
export const Small = Template.bind({}); |
||||
Small.args = { |
||||
dialogSize: "small", |
||||
title: "Small", |
||||
}; |
||||
|
||||
export const Large = Template.bind({}); |
||||
Large.args = { |
||||
dialogSize: "large", |
||||
title: "Large", |
||||
}; |
||||
|
||||
const TemplateScrolling: Story<DialogComponent> = (args: DialogComponent) => ({ |
||||
props: args, |
||||
template: ` |
||||
<bit-dialog [dialogSize]="dialogSize"> |
||||
<span bit-dialog-title>Scrolling Example</span> |
||||
<span bit-dialog-content> |
||||
Dialog body text goes here.<br> |
||||
<ng-container *ngFor="let _ of [].constructor(100)"> |
||||
repeating lines of characters <br> |
||||
</ng-container> |
||||
end of sequence! |
||||
</span> |
||||
<div bit-dialog-footer class="tw-flex tw-flex-row tw-gap-2"> |
||||
<button bitButton buttonType="primary">Save</button> |
||||
<button bitButton buttonType="secondary">Cancel</button> |
||||
</div> |
||||
</bit-dialog> |
||||
`,
|
||||
}); |
||||
|
||||
export const ScrollingContent = TemplateScrolling.bind({}); |
||||
ScrollingContent.args = { |
||||
dialogSize: "small", |
||||
}; |
||||
@ -0,0 +1,2 @@
@@ -0,0 +1,2 @@
|
||||
export * from "./dialog.module"; |
||||
export * from "./dialog.service"; |
||||
@ -1,13 +1,13 @@
@@ -1,13 +1,13 @@
|
||||
import { Component, ContentChild, Directive } from "@angular/core"; |
||||
|
||||
@Directive({ selector: "[bit-modal-icon]" }) |
||||
@Directive({ selector: "[bit-dialog-icon]" }) |
||||
export class IconDirective {} |
||||
|
||||
@Component({ |
||||
selector: "bit-simple-modal", |
||||
templateUrl: "./modal-simple.component.html", |
||||
selector: "bit-simple-dialog", |
||||
templateUrl: "./simple-dialog.component.html", |
||||
}) |
||||
export class ModalSimpleComponent { |
||||
export class SimpleDialogComponent { |
||||
@ContentChild(IconDirective) icon!: IconDirective; |
||||
|
||||
get hasIcon() { |
||||
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
import { Meta, moduleMetadata, Story } from "@storybook/angular"; |
||||
|
||||
import { ButtonModule } from "../../button"; |
||||
|
||||
import { IconDirective, SimpleDialogComponent } from "./simple-dialog.component"; |
||||
|
||||
export default { |
||||
title: "Component Library/Dialogs/Simple Dialog", |
||||
component: SimpleDialogComponent, |
||||
decorators: [ |
||||
moduleMetadata({ |
||||
imports: [ButtonModule], |
||||
declarations: [IconDirective], |
||||
}), |
||||
], |
||||
parameters: { |
||||
design: { |
||||
type: "figma", |
||||
url: "https://www.figma.com/file/Zt3YSeb6E6lebAffrNLa0h/Tailwind-Component-Library", |
||||
}, |
||||
}, |
||||
} as Meta; |
||||
|
||||
const Template: Story<SimpleDialogComponent> = (args: SimpleDialogComponent) => ({ |
||||
props: args, |
||||
template: ` |
||||
<bit-simple-dialog> |
||||
<span bit-dialog-title>Alert Dialog</span> |
||||
<span bit-dialog-content>Message Content</span> |
||||
<div bit-dialog-footer class="tw-flex tw-flex-row tw-gap-2"> |
||||
<button bitButton buttonType="primary">Yes</button> |
||||
<button bitButton buttonType="secondary">No</button> |
||||
</div> |
||||
</bit-simple-dialog> |
||||
`,
|
||||
}); |
||||
|
||||
export const Default = Template.bind({}); |
||||
|
||||
const TemplateWithIcon: Story<SimpleDialogComponent> = (args: SimpleDialogComponent) => ({ |
||||
props: args, |
||||
template: ` |
||||
<bit-simple-dialog> |
||||
<i bit-dialog-icon class="bwi bwi-star tw-text-3xl tw-text-success" aria-hidden="true"></i> |
||||
<span bit-dialog-title>Premium Subscription Available</span> |
||||
<span bit-dialog-content> Message Content</span> |
||||
<div bit-dialog-footer class="tw-flex tw-flex-row tw-gap-2"> |
||||
<button bitButton buttonType="primary">Yes</button> |
||||
<button bitButton buttonType="secondary">No</button> |
||||
</div> |
||||
</bit-simple-dialog> |
||||
`,
|
||||
}); |
||||
|
||||
export const CustomIcon = TemplateWithIcon.bind({}); |
||||
|
||||
const TemplateScroll: Story<SimpleDialogComponent> = (args: SimpleDialogComponent) => ({ |
||||
props: args, |
||||
template: ` |
||||
<bit-simple-dialog> |
||||
<span bit-dialog-title>Alert Dialog</span> |
||||
<span bit-dialog-content> |
||||
Message Content |
||||
Message text goes here.<br> |
||||
<ng-container *ngFor="let _ of [].constructor(100)"> |
||||
repeating lines of characters <br> |
||||
</ng-container> |
||||
end of sequence! |
||||
</span> |
||||
<div bit-dialog-footer class="tw-flex tw-flex-row tw-gap-2"> |
||||
<button bitButton buttonType="primary">Yes</button> |
||||
<button bitButton buttonType="secondary">No</button> |
||||
</div> |
||||
</bit-simple-dialog> |
||||
`,
|
||||
}); |
||||
|
||||
export const ScrollingContent = TemplateScroll.bind({}); |
||||
ScrollingContent.args = { |
||||
useDefaultIcon: true, |
||||
}; |
||||
@ -1,3 +0,0 @@
@@ -1,3 +0,0 @@
|
||||
export * from "./modal.component"; |
||||
export * from "./modal-simple.component"; |
||||
export * from "./modal.module"; |
||||
@ -1,85 +0,0 @@
@@ -1,85 +0,0 @@
|
||||
import { Meta, moduleMetadata, Story } from "@storybook/angular"; |
||||
|
||||
import { ButtonModule } from "../button"; |
||||
|
||||
import { IconDirective, ModalSimpleComponent } from "./modal-simple.component"; |
||||
|
||||
export default { |
||||
title: "Component Library/Modals/Simple Modal", |
||||
component: ModalSimpleComponent, |
||||
decorators: [ |
||||
moduleMetadata({ |
||||
imports: [ButtonModule], |
||||
declarations: [IconDirective], |
||||
}), |
||||
], |
||||
parameters: { |
||||
design: { |
||||
type: "figma", |
||||
url: "https://www.figma.com/file/Zt3YSeb6E6lebAffrNLa0h/Tailwind-Component-Library", |
||||
}, |
||||
}, |
||||
} as Meta; |
||||
|
||||
const Template: Story<ModalSimpleComponent> = (args: ModalSimpleComponent) => ({ |
||||
props: args, |
||||
template: ` |
||||
<bit-simple-modal> |
||||
<span bit-modal-title> Alert Modal |
||||
</span> |
||||
<span bit-modal-content> Message Content |
||||
</span> |
||||
<div bit-modal-footer class="tw-flex tw-flex-row tw-gap-2"> |
||||
<button bitButton buttonType="primary"> Yes </button> |
||||
<button bitButton buttonType="secondary"> No </button> |
||||
</div> |
||||
</bit-simple-modal> |
||||
`,
|
||||
}); |
||||
|
||||
export const Default = Template.bind({}); |
||||
|
||||
const TemplateWithIcon: Story<ModalSimpleComponent> = (args: ModalSimpleComponent) => ({ |
||||
props: args, |
||||
template: ` |
||||
<bit-simple-modal> |
||||
<i bit-modal-icon class="bwi bwi-star tw-text-3xl tw-text-success" aria-hidden="true"></i> |
||||
<span bit-modal-title> Premium Subscription Available |
||||
</span> |
||||
<span bit-modal-content> Message Content |
||||
</span> |
||||
<div bit-modal-footer class="tw-flex tw-flex-row tw-gap-2"> |
||||
<button bitButton buttonType="primary"> Yes </button> |
||||
<button bitButton buttonType="secondary"> No </button> |
||||
</div> |
||||
</bit-simple-modal> |
||||
`,
|
||||
}); |
||||
|
||||
export const CustomIcon = TemplateWithIcon.bind({}); |
||||
|
||||
const TemplateScroll: Story<ModalSimpleComponent> = (args: ModalSimpleComponent) => ({ |
||||
props: args, |
||||
template: ` |
||||
<bit-simple-modal> |
||||
<span bit-modal-title> Alert Modal |
||||
</span> |
||||
<span bit-modal-content> Message Content |
||||
Message text goes here.<br> |
||||
<ng-container *ngFor="let _ of [].constructor(100)"> |
||||
repeating lines of characters <br> |
||||
</ng-container> |
||||
end of sequence! |
||||
</span> |
||||
<div bit-modal-footer class="tw-flex tw-flex-row tw-gap-2"> |
||||
<button bitButton buttonType="primary"> Yes </button> |
||||
<button bitButton buttonType="secondary"> No </button> |
||||
</div> |
||||
</bit-simple-modal> |
||||
`,
|
||||
}); |
||||
|
||||
export const ScrollingContent = TemplateScroll.bind({}); |
||||
ScrollingContent.args = { |
||||
useDefaultIcon: true, |
||||
}; |
||||
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
import { Component, Input } from "@angular/core"; |
||||
|
||||
@Component({ |
||||
selector: "bit-modal", |
||||
templateUrl: "./modal.component.html", |
||||
}) |
||||
export class ModalComponent { |
||||
@Input() modalSize: "small" | "default" | "large"; |
||||
|
||||
get width() { |
||||
switch (this.modalSize) { |
||||
case "small": { |
||||
return "tw-max-w-xs"; |
||||
} |
||||
case "large": { |
||||
return "tw-max-w-4xl"; |
||||
} |
||||
default: { |
||||
return "tw-max-w-xl"; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,12 +0,0 @@
@@ -1,12 +0,0 @@
|
||||
import { CommonModule } from "@angular/common"; |
||||
import { NgModule } from "@angular/core"; |
||||
|
||||
import { ModalSimpleComponent } from "./modal-simple.component"; |
||||
import { ModalComponent } from "./modal.component"; |
||||
|
||||
@NgModule({ |
||||
imports: [CommonModule], |
||||
exports: [ModalComponent, ModalSimpleComponent], |
||||
declarations: [ModalComponent, ModalSimpleComponent], |
||||
}) |
||||
export class ModalModule {} |
||||
@ -1,80 +0,0 @@
@@ -1,80 +0,0 @@
|
||||
import { Meta, moduleMetadata, Story } from "@storybook/angular"; |
||||
|
||||
import { ButtonModule } from "../button"; |
||||
|
||||
import { ModalComponent } from "./modal.component"; |
||||
|
||||
export default { |
||||
title: "Component Library/Modals/Modal", |
||||
component: ModalComponent, |
||||
decorators: [ |
||||
moduleMetadata({ |
||||
imports: [ButtonModule], |
||||
}), |
||||
], |
||||
args: { |
||||
modalSize: "small", |
||||
}, |
||||
parameters: { |
||||
design: { |
||||
type: "figma", |
||||
url: "https://www.figma.com/file/Zt3YSeb6E6lebAffrNLa0h/Tailwind-Component-Library", |
||||
}, |
||||
}, |
||||
} as Meta; |
||||
|
||||
const Template: Story<ModalComponent> = (args: ModalComponent) => ({ |
||||
props: args, |
||||
template: ` |
||||
<bit-modal [modalSize]="modalSize"> |
||||
<span bit-modal-title> Modal Title </span> |
||||
<span bit-modal-content> |
||||
Modal body text goes here. |
||||
</span> |
||||
<div bit-modal-footer class="tw-flex tw-flex-row tw-gap-2"> |
||||
<button bitButton buttonType="primary"> Save </button> |
||||
<button bitButton buttonType="secondary"> Cancel </button> |
||||
</div> |
||||
</bit-modal> |
||||
`,
|
||||
}); |
||||
|
||||
export const Default = Template.bind({}); |
||||
Default.args = { |
||||
modalSize: "default", |
||||
}; |
||||
|
||||
export const Small = Template.bind({}); |
||||
Small.args = { |
||||
modalSize: "small", |
||||
}; |
||||
|
||||
export const Large = Template.bind({}); |
||||
Large.args = { |
||||
modalSize: "large", |
||||
}; |
||||
|
||||
const TemplateScrolling: Story<ModalComponent> = (args: ModalComponent) => ({ |
||||
props: args, |
||||
template: ` |
||||
<bit-modal [modalSize]="modalSize"> |
||||
<span bit-modal-title> Modal Title </span> |
||||
<span bit-modal-content> |
||||
Modal body text goes here.<br> |
||||
<ng-container *ngFor="let _ of [].constructor(100)"> |
||||
repeating lines of characters <br> |
||||
</ng-container> |
||||
end of sequence! |
||||
</span> |
||||
<div bit-modal-footer class="tw-flex tw-flex-row tw-gap-2"> |
||||
<button bitButton buttonType="primary"> Save </button> |
||||
<button bitButton buttonType="secondary"> Cancel </button> |
||||
</div> |
||||
</bit-modal> |
||||
`,
|
||||
}); |
||||
|
||||
export const ScrollingContent = TemplateScrolling.bind({}); |
||||
ScrollingContent.args = { |
||||
modalSize: "small", |
||||
}; |
||||
Loading…
Reference in new issue