JSFiddle - React, Tailwind, and code Playground
by uiwwnw
SCSS
.ux-dialog {
z-index: 1000;
position: fixed;
top: 0;
left: 0;
overflow: hidden;
width: 100%;
height: 100%;
font-size: 0;
text-align: center;
&.close {
pointer-events: none;
}
&:before {
display: inline-block;
height: 100%;
vertical-align: middle;
content: '';
}
&--close {
position: absolute;
top: 0;
right: 0;
width: 20px;
height: 20px;
margin: -10px;
padding: 0;
border: 0;
border-radius: 50%;
font-size: 0;
background: #fff;
&:before {
font-size: 20px;
content: '\d7';
}
}
&--content {
position: relative;
max-width: 80%;
display: inline-block;
vertical-align: middle;
padding: 10px;
font-size: 12px;
border-radius: 3px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
background: #fff;
animation: open-content .6s;
.close > & {
animation: close-content .6s;
}
}
&--header {
white-space: nowrap;
text-align: left;
font-size: 12px;
border-bottom: 2px solid #333;
}
&--container {
overflow: auto;
max-height: 80vh;
padding: 10px 0;
}
&--footer {
font-size: 0;
button {
display: inline-block;
font-size: 12px;
border: 0;
background: 0;
}
}
&--dim {
z-index: -1;
top: 0;
left: 0;
position: absolute;
width: 100%;
height: 100%;
opacity: .3;
background: #000;
animation: open-dim .4s;
.close > & {
animation: close-dim .6s;
}
}
}
@keyframes open-dim {
0% {
opacity: 0;
}
100% {
opacity: .3;
}
}
@keyframes close-dim {
0% {
opacity: .3;
}
100% {
opacity: 0;
}
}
@keyframes open-content {
0% {
transform: scale3d(.9, .9, .9);
}
50% {
transform: scale3d(1.05, 1.05, 1.05);
}
100% {
transform: scale3d(1, 1, 1);
}
}
@keyframes close-content {
0% {
transform: scale3d(1, 1, 1);
}
50% {
transform: scale3d(1.05, 1.05, 1.05);
...
TypeScript
interface Button {
callback?: Function;
text?: string;
}
interface Contents {
title?: string;
content?: string | Node;
confirm?: Button | null;
cancel?: Button | null;
}
const defaultText = {
confirm: '확인',
cancel: '취소'
};
const contentsType = {
confirm: 'boolean',
cancel: 'boolean',
title: 'string',
content: 'string',
callback: 'function',
text: 'string',
};
class UxDialog {
private element: any;
private contents: Contents;
constructor(contents: Contents) {
this.getDefaultContents(contents);
}
private checkType(object: object): void {
Object.entries(object).map((val) => {
const key = val[0];
const value = val[1];
if (typeof value === 'object') {
this.checkType(value);
} else {
const type = contentsType[key];
if (typeof value !== type) {
throw `${value}는 ${type}이 아닙니다.`
}
}
});
}
private makeNode(contents: Contents): any {
let confirm = '';
let cancel = '';
if (contents.confirm) {
confirm = `<button name="confirm" type="button">${contents.confirm.text || defaultText.confirm}</button>`
}
if (contents.cancel) {
cancel = `<button name="cancel" type="button">${contents.cancel.text || defaultText.cancel}</button>`
}
const dialog = `
<div class="ux-dialog">
<div class="ux-dialog--content">
<button type="button" class="ux-dialog--close">this dialog close</button>
<div class="ux-dialog--header">${contents.title}</div>
<div class="ux-dialog--container">${contents.content}</div>
<div class="ux-dialog--footer">${confirm}${cancel}</div>
</div>
<i class="ux-dialog--dim"></i>
</div>
`;
return...