diff --git a/bg1.png b/bg1.png new file mode 100644 index 0000000..d0cd365 Binary files /dev/null and b/bg1.png differ diff --git a/demo.css b/demo.css new file mode 100644 index 0000000..c0a4e71 --- /dev/null +++ b/demo.css @@ -0,0 +1,207 @@ +html, +body { + border: 0; + margin: 0; +} + +body { + font-family: 'PT Sans', sans-serif; + width: 100%; + height: 100%; + background-color: #18181b; +} + +form { + width: 40%; + margin: 15px auto; + padding: 35px; + color: #fdfeff; + background-color: #363842; + background-image: url(bg1.png); + border: 1px solid #c6c6c6; + border-radius: 5px; + box-shadow: 0 0 8px#999999; + box-sizing: border-box; +} + +form h1 { + font-size: 3em; + font-weight: 300; + text-align: center; + /*color: #2196f3;*/ + color: #01b075; + padding-top: 0; + margin-top: 0; +} + +form hr.sep { + /*background: #2196f3;*/ + background-color: #01b075; + box-shadow: none; + border: none; + height: 2px; + width: 25%; + margin: 0px auto 45px auto; +} + + +/* +form .emoji { + font-size: 1.2em; +} +*/ + +input, +textarea, +select { + border: 1px solid #c6c6c6; + border-radius: 5px; + text-align: left; + width: 100%; + box-sizing: border-box; +} + +.group { + position: relative; + margin: 45px 0; + box-sizing: border-box; +} + +.group textarea { + resize: none; +} + +.group input, +.group textarea, +.group select { + background: none; + color: #c6c6c6; + font-size: 18px; + padding: 10px 10px 10px 5px; + display: block; + border: none; + border-radius: 0; + border-bottom: 1px solid #c6c6c6; +} + +.group select option { + color: #ededee; + background-color: #22232a; +} + +.group input:focus, +.group textarea:focus, +.group select:focus { + outline: none; +} + +.group input:focus~label, +.group textarea:focus~label, +.group select:focus~label, +.group input:valid~label, +.group textarea:valid~label, +.group select:valid~label { + top: -14px; + font-size: 12px; + /*color: #2196f3;*/ + color: #04c484; +} + +.group input:focus~.bar:before, +.group textarea:focus~.bar:before, +.group select:focus~.bar:before { + width: 100%; +} + +.group input[type="password"] { + letter-spacing: 0.3em; +} + +.group label { + color: #c6c6c6; + font-size: 16px; + font-weight: normal; + position: absolute; + pointer-events: none; + left: 5px; + top: 10px; + transition: 300ms ease all; +} + +.group .bar { + position: relative; + display: block; +} + +.group .bar:before { + content: ''; + height: 2px; + width: 0; + bottom: 0px; + position: absolute; + /*background: #2196f3;*/ + background-color: #04c484; + transition: 300ms ease all; + left: 0%; +} + +.btn { + background: #fff; + color: #959595; + border: none; + padding: 10px 20px; + font-size: 1.1em; + border-radius: 3px; + letter-spacing: 0.06em; + text-decoration: none; + outline: none; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); + transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); +} + +.btn:hover { + color: #8b8b8b; + box-shadow: 0 7px 14px rgba(0, 0, 0, 0.18), 0 5px 5px rgba(0, 0, 0, 0.12); +} + +.btn.btn-link { + background: #2196f3; + color: #d3eafd; +} + +.btn.btn-link:hover { + background: #0d8aee; + color: #deeffd; +} + +.btn.btn-submit { + cursor: pointer; + background-color: #01b075; + color: #fff; +} + +.btn.btn-submit:hover { + /*background: #0d8aee;*/ + background-color: #04c484; + color: #deeffd; +} + +.btn.btn-submit:active { + background-color: #13e29d; + color: rgb(80, 77, 77); + /*color: #0d8aee;*/ +} + +.btn.btn-cancel { + background: #eee; +} + +.btn.btn-cancel:hover { + background: #e1e1e1; + color: #8b8b8b; +} + +.btn-box { + text-align: center; + margin: 20px 10px; +} \ No newline at end of file diff --git a/notification.css b/notification.css new file mode 100644 index 0000000..d3a69bc --- /dev/null +++ b/notification.css @@ -0,0 +1,222 @@ +/* Notification */ + +.notification-container { + font-size: 14px; + box-sizing: border-box; + position: fixed; + z-index: 1000; +} + +.notification { + position: relative; + overflow: hidden; + margin: 0 0 6px; + opacity: 0.9; + border-radius: 4px; + box-shadow: 0 0 30px 0 rgba(36, 30, 30, 0.2); + min-height: 56px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + transition: all .5s linear; +} + +.notification:hover { + box-shadow: 0 0 30px #000000; + opacity: 1; + cursor: pointer; +} + +.position-bottom-right { + bottom: 10px; + right: 10px; +} + +.notification-error { + background: #bd362f; + color: #fff; + border-left: 4px solid rgb(241, 234, 234); +} + +.notification-success { + background: #51a351; + color: #fff; + border-left: 4px solid rgb(241, 234, 234); +} + +.notification-warning { + background: #f87400; + color: #fff; + border-left: 4px solid rgb(241, 234, 234); +} + +.notification-info { + background: #2f96b4; + color: #fff; + border-left: 4px solid rgb(241, 234, 234); +} + +.position-top-right { + top: 10px; + right: 10px; +} + +.notification-close { + position: absolute; + right: 8px; + top: 8px; + display: block; + height: 24px; + width: 24px; + transition: color .1s; + cursor: pointer; +} + +.notification-close svg { + display: block; +} + +.notification-close .close-x { + /*stroke: rgb(252, 7, 7);*/ + stroke: #fff; + fill: transparent; + stroke-linecap: round; + stroke-width: 5; +} + +.notification-body { + align-items: center; + display: flex; + min-height: 56px; + width: 270px; + padding: 10px; + letter-spacing: 1px; +} + +.notification-icon { + font-size: 36px; + line-height: 36px; + width: 36px; + color: #fff; + text-align: center; + padding: 0; + margin: 0; +} + +.notification-warning .notification-icon::before { + content: "\0021"; +} + +.notification-error .notification-icon::before { + content: "\26A0"; +} + +.notification-success .notification-icon::before { + content: "\2714"; +} + +.notification-info .notification-icon::before { + content: "\24D8"; +} + +.notification-body>div { + padding: 4px; + height: 100%; +} + +.notification-title { + font-size: 18px; + font-weight: 600; + padding: 4px; + margin-top: -2px; +} + +.notification-desc { + padding: 4px; + color: rgba(255, 255, 255, 0.9) +} + +.position-bottom-right .notification.animation-slide-in, +.position-top-right .notification.animation-slide-in { + animation: position-right-slide-in .5s forwards, bounceIn .7s forwards; + transform: translateX(100%); +} + +.position-bottom-right .notification.animation-slide-out, +.position-top-right .notification.animation-slide-out { + animation: position-right-slide-out .2s forwards; + margin-right: -20px; + transform: translateX(0); +} + +.notification.animation-fade-in { + animation: fade-in .5s forwards; + opacity: 0; +} + +.notification.animation-fade-out { + animation: fade-out .5s forwards; +} + +.notification-buttons { + border-top: 2px solid rgba(0, 0, 0, .1); + display: none; +} + +.notification-button { + background: rgba(0, 0, 0, .02); + align-items: center; + color: #000; + display: flex; + flex-grow: 1; + font-size: 14px; + font-weight: 600; + justify-content: center; + min-height: 39px; + min-width: 50%; + text-align: center; + cursor: pointer; +} + +.notification-button:hover { + background: rgba(0, 0, 0, .01); + color: #000; + text-decoration: none; +} + +.notification-cancel { + color: darkred; + border-left: 1px solid rgba(0, 0, 0, .1); +} + +.notification-action { + color: darksalmon +} + +@keyframes position-right-slide-in { + to { + transform: translateX(0); + } +} + +@keyframes position-right-slide-out { + to { + transform: translateX(100%); + } +} + +@keyframes bounceIn { + 50% { + transform: scale(0.9); + opacity: 0.5; + } + 75% { + transform: scale(1.2); + opacity: 0.9; + } + 100% { + transform: scale(1); + opacity: 1; + } +} \ No newline at end of file diff --git a/notification.js b/notification.js new file mode 100644 index 0000000..d00e68c --- /dev/null +++ b/notification.js @@ -0,0 +1,114 @@ +function Notification(opts) { + const defaultOpts = { + position: 'position-bottom-right', + duration: 3000, + type: 'notification-error' + }; + opts = Object.assign({}, defaultOpts, opts); + opts.duration = parseInt(opts.duration); + + const timeouts = []; + + const classMainSelector = 'notification-container'; + const classPopup = 'notification'; + const animationInClass = 'animation-slide-in'; + const animationOutClass = 'animation-slide-out'; + const titleSelector = '.notification-title'; + const descSelector = '.notification-desc'; + const titleByType = { + 'notification-error': 'Error', + 'notification-info': 'Info', + 'notification-success': 'Success', + 'notification-warning': 'Warning' + }; + + const tempatePopup = () => { + return ` + + + + + +
+
+
+
+
+
+
`; + }; + + const dialogButtons = () => { + return `
+ Ok + Cancel +
` + }; + + const createMainContainer = (position) => { + let container = document.querySelector(`.${classMainSelector}.${position}`); + + if (!container) { + container = document.createElement('div'); + container.classList = classMainSelector + ' ' + position; + document.body.appendChild(container); + } + + return container; + } + + const createPopup = () => { + let elPopup = document.createElement('div'); + elPopup.classList = classPopup + ' ' + animationInClass + ` ${opts.type}`; + elPopup.insertAdjacentHTML('beforeend', tempatePopup()); + return elPopup; + } + + const hidePopUp = (elPopup) => { + const selector = `.${classMainSelector}.${opts.position}`; + const container = document.querySelector(selector); + + const firstTimeout = timeouts.shift(); + clearTimeout(firstTimeout); + + elPopup.classList.remove(animationInClass); + elPopup.classList.add(animationOutClass); + + // after end of animation - remove element from container + setTimeout(function() { + container.removeChild(elPopup); + }, 500); + + // Remove container if empty + if (container.querySelectorAll('.notification').length === 0) { + document.body.removeChild(container); + } + } + + return ({ title, message } = {}) => { + const container = createMainContainer(opts.position); + const elPopup = createPopup(); + + const elTitle = elPopup.querySelector(titleSelector); + const elText = elPopup.querySelector(descSelector); + const titlePopup = title || titleByType[opts.type]; + + elTitle.innerText = titlePopup; + elText.innerText = message; + + if (opts.position.includes('bottom')) { + container.prepend(elPopup); + } else { + container.appendChild(elPopup); + } + + + + const timeout = setTimeout(() => { + hidePopUp(elPopup) + }, opts.duration); + timeouts.push(timeout); + + elPopup.addEventListener('click', () => clearTimeout(timeout)); + } +}; \ No newline at end of file