Skip to content

Instantly share code, notes, and snippets.

@elebetsamer
Created May 21, 2018 16:26
Show Gist options
  • Save elebetsamer/00a4e2e337899c6ac8593c29f09e1c6b to your computer and use it in GitHub Desktop.
Save elebetsamer/00a4e2e337899c6ac8593c29f09e1c6b to your computer and use it in GitHub Desktop.
Stencil Modal Component
import { Component, Element, Prop, Listen, Method, State } from '@stencil/core';
@Component({
tag: 'st-demo-modal',
styleUrl: 'st-demo-modal.scss'
})
export class DemoModal {
modal: HTMLStModalElement;
@Element()
el: HTMLElement;
componentDidLoad() {
this.modal = this.el.querySelector('st-modal');
}
@Method()
close() {
this.modal.close();
}
@Method()
open() {
this.modal.open();
}
handleCancelClick(event: UIEvent) {
event.preventDefault();
this.close();
}
handleOpenModalClick(event: UIEvent) {
event.preventDefault();
this.open();
}
handleSaveClick(event: UIEvent) {
event.preventDefault();
// Do some work here
this.close();
}
render() {
return ([
<st-button clicked={this.handleOpenModalClick.bind(this)}>Open Demo Modal</st-button>,
<st-modal>
<div slot="header">
This is the modal header
</div>
<div slot="body">
This is the modal body
</div>
<div slot="footer">
<st-button clicked={this.handleSaveClick.bind(this)}>Save</st-button>
<st-button type="flat" clicked={this.handleCancelClick.bind(this)}>Cancel</st-button>
</div>
</st-modal>
]);
}
}
import { Component, Element, Event, EventEmitter, Method, Prop, Watch } from '@stencil/core';
@Component({
tag: 'st-modal',
styleUrl: 'st-modal.scss'
})
export class ModalComponent {
@Prop()
bannerMessage: string;
@Prop()
bannerType: string;
@Element()
element: HTMLElement;
@Prop()
loading: boolean = false;
@Prop()
loadingMessage: string = 'Loading...';
@Event()
modalClosed: EventEmitter;
@Event()
modalOpened: EventEmitter;
@Prop()
show = false;
@Prop()
size: string = '';
@Method()
close() {
document.body.classList.remove('st-modal--is-open');
this.element.classList.remove('st-modal--open');
this.modalClosed.emit('closed');
}
@Method()
open() {
document.body.classList.add('st-modal--is-open');
this.element.classList.add('st-modal--open');
this.modalOpened.emit();
}
render() {
const contentClasses: string[] = ['st-modal__content'];
const bodySlotElement = this.element.querySelector('[slot=body]');
const footerSlotElement = this.element.querySelector('[slot=footer]');
const headerSlotElement = this.element.querySelector('[slot=header]');
if (this.size) {
contentClasses.push(`st-modal__content--${this.size}`);
}
if (bodySlotElement) {
bodySlotElement.classList.add('st-modal__body');
this.element.classList.add('st-modal--has-body');
} else {
this.element.classList.remove('st-modal--has-body');
}
if (footerSlotElement) {
footerSlotElement.classList.add('st-modal__footer');
this.element.classList.add('st-modal--has-footer');
} else {
this.element.classList.remove('st-modal--has-footer');
}
if (headerSlotElement) {
headerSlotElement.classList.add('st-modal__header');
this.element.classList.add('st-modal--has-header');
} else {
this.element.classList.remove('st-modal--has-header');
}
return ([
<div class={contentClasses.join(' ')}>
{this.renderBanner()}
{this.renderLoadingMessage()}
<slot name="header" />
<slot name="body" />
<slot name="footer" />
</div>,
<st-backdrop onClick={() => this.close()}></st-backdrop>
]);
}
renderBanner() {
const classes = {
'st-modal__banner': true,
[`st-modal__banner--${this.bannerType}`]: this.bannerType ? true : false
};
if (this.bannerMessage) {
return (
<div class={classes}>{this.bannerMessage}</div>
);
}
return null;
}
renderLoadingMessage() {
if (this.loading) {
return (
<st-loading-spinner color="#49c877" fill>{this.loadingMessage}</st-loading-spinner>
);
}
return null;
}
@Watch('show')
watchShowHandler(shown: boolean) {
if (shown) {
this.open();
} else {
this.close();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment