Add more styling and changed undo behaviour to work correctly when multiple selection is deleted

This commit is contained in:
Alex Piqueras 2024-10-11 00:44:34 +02:00
parent 37401a85c8
commit 1749249c1c
7 changed files with 109 additions and 38 deletions

View File

@ -6,6 +6,9 @@ class AppBase extends HTMLElement {
super();
this.attachShadow({ mode: 'open' });
this.text = text;
this.properties = {
color: '#324BFF',
};
this.store = new Store();
}
@ -14,27 +17,101 @@ class AppBase extends HTMLElement {
this.render();
}
renderText() {
renderOptions() {
const textList = this.store.getRecords();
return textList.map((item) => `<option value=${item.id}>${item.text}</option>`).join('\n');
}
render(action = 'INITIAL') {
if (![Store.actions.ADD_LINE, Store.actions.REMOVE_LINE, Store.actions.UNDO, 'INITIAL'].includes(action)) {
render(action = 'INIT') {
if (![Store.actions.ADD_LINE, Store.actions.REMOVE_LINE, Store.actions.UNDO, 'INIT'].includes(action)) {
return; // Only render if content changed
}
this.shadowRoot.innerHTML = `
<main-window title="${this.text.title}" description="${this.text.description}">
<select multiple is="item-list">
${this.renderText()}
<style>
* {
margin: 0;
}
#window {
width: 800px;
height: 477px;
background: #FFFFFF 0% 0% no-repeat padding-box;
box-shadow: 0px 5px 12px #0000001F;
border-radius: 20px;
opacity: 1;
padding: 50px;
display: flex;
flex-direction: column;
row-gap: 35px;
}
#title {
height: 49px;;
margin-bottom: -12px;
text-align: center;
font-size: 40px;
font-family: "Montserrat", sans-serif;
font-weight: normal;
letter-spacing: 0px;
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%);
box-shadow: 0 0 10px 100px ${this.properties.color} inset;
color: #fff;
outline: none;
}
#button-bar {
display: flex;
column-gap: 35px
}
#button-bar > custom-button:last-child {
margin-left: auto;
}
#undo-char {
margin-top: 3px;
}
</style>
<div id="window">
<h1 id="title">${this.text.title}</h1>
<p id="description">${this.text.description}</p>
<select id="list" multiple is="item-list">
${this.renderOptions()}
</select>
<span id="button-bar">
<custom-button action="${Store.actions.REMOVE_LINE}" color="#324bff">Delete</custom-button>
<custom-button action="${Store.actions.ADD_LINE}" color="#324bff">Add</custom-button>
<custom-button action="${Store.actions.UNDO}" outline color="#324bff">Undo</custom-button>
<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"/>
<path d="m.132 1.525.437.964.964-.437" style="fill:none;stroke:${this.properties.color};stroke-width:.264583;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"/>
</svg>
</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>
</span>
</main-window>
</div>
`;
}
}

View File

@ -1,7 +1,7 @@
import Store from '../modules/store.js';
class CustomButton extends HTMLElement {
static observedAttributes = ['outline', 'color', 'action'];
static observedAttributes = ['outline', 'color', 'width', 'action'];
constructor() {
super();
@ -36,7 +36,7 @@ class CustomButton extends HTMLElement {
border-style: ${isOutline ? 'solid' : 'hidden'};
border-color: ${this.getAttribute('color')};
opacity: 1;
width: 138px;
width: ${this.getAttribute('width')};
height: 49px;
background-color: ${isOutline ? 'white' : this.getAttribute('color')};
color: ${isOutline ? this.getAttribute('color') : 'white'};

View File

@ -21,7 +21,7 @@ class ItemList extends HTMLSelectElement {
}
updateStyle() {
this.style.width = '800px';
this.style.width = '100%';
this.style.height = '227px';
this.style.background = '#F7F7F7 0% 0% no-repeat padding-box';
this.style.border = '1px solid #CCCCCC';

View File

@ -15,27 +15,23 @@ class MainWindow extends HTMLElement {
}
render() {
const title = this.getAttribute('title') || "No title";
const description = this.getAttribute('description') || "No description";
this.shadowRoot.innerHTML = `
<style>
#window {
width: 900px;
height: 577px;
width: 800px;
height: 477px;
background: #FFFFFF 0% 0% no-repeat padding-box;
box-shadow: 0px 5px 12px #0000001F;
border-radius: 20px;
opacity: 1;
}
#content {
width: 800px;
margin: 0 50px 13px 50px;
padding: 50px;
display: flex
}
h1 {
top: 221px;
margin: 50px 50px 13px 50px;
height: 49px;
margin: 0;
margin-bottom: 13px;
text-align: center;
font-size: 40px;
font-family: "Montserrat", sans-serif;
@ -45,12 +41,10 @@ class MainWindow extends HTMLElement {
opacity: 1;
}
p {
margin: 0 50px 0 50px;
text-align: center;
height: 74px;
/* UI Properties */
margin: 0;
margin-bottom: 35px;
text-align: center;
font-size: 18px;
font-family: "Montserrat", sans-serif;
@ -63,9 +57,7 @@ class MainWindow extends HTMLElement {
<div id="window">
<h1>${title}</h1>
<p>${description}</p>
<div id="content" >
<slot></slot>
<div/>
<slot></slot>
</div>
`;
}

View File

View File

@ -1,5 +1,4 @@
import './components/app-base.js';
import './components/main-window.js';
import './components/custom-button.js';
import './components/item-list.js';

View File

@ -48,14 +48,13 @@ export default class Store {
};
break;
case this.constructor.actions.REMOVE_LINE:
const linesToRemove = this.state.selected.map((id, index) => ({
id: this.state.records.length + index,
targetId: id,
action: 'remove',
}));
this.state = {
...this.state,
records: [ ...this.state.records, ...linesToRemove],
records: [ ...this.state.records, {
id: this.state.records.length,
targetIds: this.state.selected,
action: 'remove',
}],
selected: [],
};
break;
@ -85,7 +84,11 @@ export default class Store {
return acc.concat({id: current.id, text: current.text});
}
if (current.action === "remove") {
return acc.filter((item) => item.id !== current.targetId);
let temp = acc;
for (const id of current.targetIds) {
temp = temp.filter((item) => item.id !== id);
}
return temp;
}
console.error(`Action ${current.action} not valid`);
}, []);