Add modal
This commit is contained in:
parent
8f383240ce
commit
7be76dd2f9
18
index.html
18
index.html
|
|
@ -8,23 +8,7 @@
|
|||
<link rel="icon" href="./favicon.ico" type="image/x-icon">
|
||||
</head>
|
||||
<body>
|
||||
<script type="module" src="src/components/app-base.js" defer></script>
|
||||
<script type="module" src="src/components/main-window.js" defer></script>
|
||||
<script type="module" src="src/components/custom-button.js" defer></script>
|
||||
<script type="module" src="src/components/item-list.js" defer></script>
|
||||
<style>
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
background: transparent linear-gradient(135deg, #A1C4FD 0%, #C2E9FB 100%) 0% 0% no-repeat padding-box;
|
||||
opacity: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100%;
|
||||
}
|
||||
</style>
|
||||
<script type="module" src="src/app.js" defer></script>
|
||||
<app-base></app-base>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
import Store from '../modules/store.js';
|
||||
import text from '../modules/text.js';
|
||||
import './components/main-window.js';
|
||||
import './components/custom-button.js';
|
||||
import './components/item-list.js';
|
||||
import './components/custom-modal.js';
|
||||
|
||||
import Store from './modules/store.js';
|
||||
import text from './modules/text.js';
|
||||
|
||||
class AppBase extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
this.text = text;
|
||||
this.properties = {
|
||||
color: '#324BFF',
|
||||
|
|
@ -23,47 +27,51 @@ class AppBase extends HTMLElement {
|
|||
}
|
||||
|
||||
render(action = 'INIT') {
|
||||
if (![Store.actions.ADD_LINE, Store.actions.REMOVE_LINE, Store.actions.UNDO, 'INIT'].includes(action)) {
|
||||
if (![Store.actions.OPEN_MODAL, Store.actions.CLOSE_MODAL, Store.actions.ADD_LINE, Store.actions.REMOVE_LINE, Store.actions.UNDO, 'INIT'].includes(action)) {
|
||||
return; // Only render if content changed
|
||||
}
|
||||
|
||||
this.shadowRoot.innerHTML = `
|
||||
this.innerHTML = `
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
background: transparent linear-gradient(135deg, #A1C4FD 0%, #C2E9FB 100%) 0% 0% no-repeat padding-box;
|
||||
opacity: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100%;
|
||||
font-family: "Montserrat", sans-serif;
|
||||
font-weight: normal;
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
#title {
|
||||
height: 49px;;
|
||||
height: 49px;
|
||||
margin-bottom: -12px;
|
||||
text-align: center;
|
||||
font-size: 40px;
|
||||
font-family: "Montserrat", sans-serif;
|
||||
font-weight: normal;
|
||||
letter-spacing: 0px;
|
||||
font-weight: inherit;
|
||||
color: #333333;
|
||||
opacity: 1;
|
||||
|
||||
}
|
||||
#description {
|
||||
text-align: center;
|
||||
height: 74px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-family: "Montserrat", sans-serif;
|
||||
font-weight: normal;
|
||||
letter-spacing: 0px;
|
||||
color: #333333;
|
||||
opacity: 1;
|
||||
}
|
||||
#list {
|
||||
padding: 13px;
|
||||
}
|
||||
#list > option {
|
||||
height: 40px;
|
||||
align-content: center;
|
||||
padding-left: 15px;
|
||||
font-size: 18px;
|
||||
font-family: "Montserrat", sans-serif;
|
||||
font-weight: normal;
|
||||
}
|
||||
#list > option:checked {
|
||||
background: ${this.properties.color} linear-gradient(0deg, ${this.properties.color} 0%, ${this.properties.color} 100%);
|
||||
|
|
@ -71,24 +79,24 @@ class AppBase extends HTMLElement {
|
|||
color: #fff;
|
||||
outline: none;
|
||||
}
|
||||
#button-bar {
|
||||
.button-bar {
|
||||
display: flex;
|
||||
column-gap: 35px
|
||||
}
|
||||
#button-bar > custom-button:last-child {
|
||||
.button-bar > .right-button {
|
||||
margin-left: auto;
|
||||
}
|
||||
#undo-char {
|
||||
margin-top: 3px;
|
||||
}
|
||||
</style>
|
||||
<main-window width="900px" height="577px" gap="35px">
|
||||
<main-window width="900px" gap="35px">
|
||||
<h1 id="title">${this.text.title}</h1>
|
||||
<p id="description">${this.text.description}</p>
|
||||
<select id="list" multiple is="item-list">
|
||||
<select id="list" multiple is="item-list" height="227px">
|
||||
${this.renderOptions()}
|
||||
</select>
|
||||
<span id="button-bar">
|
||||
<span class="button-bar">
|
||||
<custom-button action="${Store.actions.UNDO}" outline width="81px" color="${this.properties.color}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" id="undo-char" width="21" height="19" viewBox="0 0 5.556 5.027">
|
||||
<path d="M.681 2.22a2.38 2.38 0 0 1 4.742.294v0a2.38 2.38 0 0 1-4.526 1.03" style="fill:none;stroke:${this.properties.color};stroke-width:.264583;stroke-linecap:round;stroke-dasharray:none"/>
|
||||
|
|
@ -97,9 +105,17 @@ class AppBase extends HTMLElement {
|
|||
|
||||
</custom-button>
|
||||
<custom-button action="${Store.actions.REMOVE_LINE}" outline width="124px" color="${this.properties.color}">Delete</custom-button>
|
||||
<custom-button action="${Store.actions.ADD_LINE}" width="138px" color="${this.properties.color}">Add</custom-button>
|
||||
<custom-button class="right-button" action="${Store.actions.OPEN_MODAL}" width="138px" color="${this.properties.color}">Add</custom-button>
|
||||
</span>
|
||||
</main-window>
|
||||
<custom-modal active="${this.store.state.modalActive}">
|
||||
<p>${text.modal.description}</p>
|
||||
<input type="text"/>
|
||||
<span class="button-bar">
|
||||
<custom-button class="right-button" action="${Store.actions.ADD_LINE}" width="138px" color="${this.properties.color}">Add</custom-button>
|
||||
<custom-button action="${Store.actions.CLOSE_MODAL}" outline width="124px" color="${this.properties.color}">Cancel</custom-button>
|
||||
</span>
|
||||
</custom-modal>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
class CustomModal extends HTMLElement {
|
||||
static observedAttributes = ['active'];
|
||||
|
||||
#templateHtml = `
|
||||
<style>
|
||||
div.overlay {
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
padding-top: 50px;
|
||||
justify-content: center;
|
||||
background: #0000001A 0% 0% no-repeat padding-box;
|
||||
opacity: 1;
|
||||
transition: all 0.35s ease-in;
|
||||
}
|
||||
mainWindow {
|
||||
top: 25px;
|
||||
transition: all 0.35s ease-in;
|
||||
}
|
||||
</style>
|
||||
<div class="overlay">
|
||||
<main-window width="700px" gap="25px">
|
||||
<slot></slot>
|
||||
</main-window>
|
||||
</div>
|
||||
`;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.attachShadow({ mode: 'open' });
|
||||
const template = document.createElement('template')
|
||||
template.innerHTML = this.#templateHtml;
|
||||
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
||||
|
||||
this.overlay = this.shadowRoot.querySelector('div.overlay');
|
||||
console.log(this.overlay);
|
||||
this.mainWindow = this.shadowRoot.querySelector('main-window');
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.updateStyle();
|
||||
}
|
||||
|
||||
attributeChangedCallback() {
|
||||
console.log("attributeChanged");
|
||||
this.updateStyle();
|
||||
}
|
||||
|
||||
updateStyle() {
|
||||
console.log(this.getAttribute('active'), typeof this.getAttribute('active'));
|
||||
this.overlay.style.visibility = this.getAttribute('active') === "true" ? 'visible' : 'hidden';
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('custom-modal', CustomModal);
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import Store from '../modules/store.js';
|
||||
|
||||
class ItemList extends HTMLSelectElement {
|
||||
static observedAttributes = ['height'];
|
||||
constructor() {
|
||||
super();
|
||||
this.publish = Store.publish
|
||||
|
|
@ -20,16 +21,23 @@ class ItemList extends HTMLSelectElement {
|
|||
this.removeEventListener('click', this.onChange.bind(this));
|
||||
}
|
||||
|
||||
attributeChangedCallback() {
|
||||
this.updateParametrizedStyle();
|
||||
}
|
||||
|
||||
updateParametrizedStyle() {
|
||||
this.style.height = this.getAttribute('height');
|
||||
}
|
||||
|
||||
updateStyle() {
|
||||
this.style.width = '100%';
|
||||
this.style.height = '227px';
|
||||
this.style.background = '#F7F7F7 0% 0% no-repeat padding-box';
|
||||
this.style.border = '1px solid #CCCCCC';
|
||||
this.style.opacity = '1';
|
||||
this.style.fontSize = '18px';
|
||||
this.style.fontFamily = '"Montserrat" sans-serif';
|
||||
this.style.fontWeight = 'normal';
|
||||
this.style.letterSpacing = '0px';
|
||||
this.style.width = '100%';
|
||||
this.style.background = '#F7F7F7 0% 0% no-repeat padding-box';
|
||||
this.style.border = '1px solid #CCCCCC';
|
||||
this.style.opacity = '1';
|
||||
this.style.fontSize = '18px';
|
||||
this.style.padding = '13px';
|
||||
this.style.boxSizing = 'border-box';
|
||||
this.updateParametrizedStyle();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
class MainWindow extends HTMLElement {
|
||||
static observedAttributes = ['width', 'height', 'gap'];
|
||||
static observedAttributes = ['width', 'gap'];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
|
@ -20,7 +20,6 @@ class MainWindow extends HTMLElement {
|
|||
<style>
|
||||
div {
|
||||
width: ${this.getAttribute('width')};
|
||||
height: ${this.getAttribute('height')};
|
||||
box-sizing: border-box;
|
||||
padding: 50px;
|
||||
background: #FFFFFF 0% 0% no-repeat padding-box;
|
||||
|
|
|
|||
|
|
@ -1,57 +0,0 @@
|
|||
import Store from '../modules/store.js';
|
||||
|
||||
class CustomModal extends HTMLElement {
|
||||
static observedAttributes = ['active', 'color', 'action'];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.publish = Store.publish;
|
||||
this.attachShadow({ mode: 'open' });
|
||||
}
|
||||
|
||||
onClick(e) {
|
||||
this.publish(this.getAttribute('action'));
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.render();
|
||||
this.shadowRoot.getElementById('button').addEventListener('click', this.onClick.bind(this));
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.shadowRoot.getElementById('button').removeEventListener('click', this.onClick);
|
||||
}
|
||||
|
||||
attributeChangedCallback() {
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
this.shadowRoot.innerHTML = `
|
||||
<style>
|
||||
button {
|
||||
border-radius: 50px;
|
||||
border-width: 1px;
|
||||
border-style: ${isOutline ? 'solid' : 'hidden'};
|
||||
border-color: ${this.getAttribute('color')};
|
||||
opacity: 1;
|
||||
width: ${this.getAttribute('width')};
|
||||
height: 49px;
|
||||
background-color: ${isOutline ? 'white' : this.getAttribute('color')};
|
||||
color: ${isOutline ? this.getAttribute('color') : 'white'};
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-family: "Montserrat", sans-serif;
|
||||
font-weight: normal
|
||||
letter-spacing: 0px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
</style>
|
||||
<main-window width="700px" height="276px" gap="25px">
|
||||
<slot></slot>
|
||||
</main-window>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('custom-modal', CustomModal);
|
||||
|
|
@ -1,6 +1 @@
|
|||
import './components/app-base.js';
|
||||
import './main-window.js';
|
||||
import './components/custom-button.js';
|
||||
import './components/item-list.js';
|
||||
import './components/custom-modal.js';
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,15 @@ export default class Store {
|
|||
REMOVE_LINE: 'REMOVE_LINE',
|
||||
UNDO: 'UNDO',
|
||||
SELECT: 'SELECT',
|
||||
OPEN_MODAL: 'OPEN_MODAL',
|
||||
CLOSE_MODAL: 'CLOSE_MODAL',
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.state = {
|
||||
records: [],
|
||||
selected: [],
|
||||
modalActive: false,
|
||||
};
|
||||
this.callbacks = [() => console.log(this.state)];
|
||||
|
||||
|
|
@ -74,6 +77,18 @@ export default class Store {
|
|||
selected: event.detail,
|
||||
}
|
||||
break;
|
||||
case this.constructor.actions.OPEN_MODAL:
|
||||
this.state = {
|
||||
...this.state,
|
||||
modalActive: true,
|
||||
}
|
||||
break;
|
||||
case this.constructor.actions.CLOSE_MODAL:
|
||||
this.state = {
|
||||
...this.state,
|
||||
modalActive: false,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.error(`Action "${event.type}" not implemented in eventHandler`);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
export default {
|
||||
title: 'This is a technical proof',
|
||||
description: 'Lorem ipsum dolor sit amet consectetur adipiscing, elit mus primis nec inceptos. Lacinia habitasse arcu molestie maecenas cursus quam nunc, hendrerit posuere augue fames dictumst placerat porttitor, dis mi pharetra vestibulum venenatis phasellus.',
|
||||
modal: {
|
||||
description: 'Add item to list',
|
||||
},
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue