<div class="container">
<ul class="items">
<li class="item item-1">
<p>Item 1 Name</p>
<button class="delete">
<span aria-hidden="true">❌</span>
<span class="sr-only">delete</span>
</button>
</li>
<li class="item item-2">
<p>Item 2 Name</p>
<button class="delete">
<span aria-hidden="true">❌</span>
<span class="sr-only">delete</span>
</button>
</li>
<li class="item item-3">
<p>Item 3 Name</p>
<button class="delete">
<span aria-hidden="true">❌</span>
<span class="sr-only">delete</span>
</button>
</li>
<li class="item item-4">
<p>Item 4 Name</p>
<button class="delete">
<span aria-hidden="true">❌</span>
<span class="sr-only">delete</span>
</button>
</li>
</ul>
<button class="add">
<span aria-hidden="true">➕</span>
<span class="sr-only">add new item</span>
</button>
</div>
.item {
opacity: 1;
height: 3rem;
display: grid;
}
/* Put new transition name on each card to morph each */
.item-1 {
view-transition-name: item-1;
}
.item-2 {
view-transition-name: item-2;
}
.item-3 {
view-transition-name: item-3;
}
.item-4 {
view-transition-name: item-4;
}
/* ... rest set in JS */
.add {
view-transition-name: add;
}
/* etc */
@layer base {
body {
font-family: system-ui, sans-serif;
}
button {
border: none;
background: none;
}
.items {
padding: 0;
display: grid;
gap: 0.5rem;
}
.item {
display: grid;
grid-template-columns: 1fr auto;
background: aliceblue;
border: 1px solid lightblue;
padding: 0 1rem;
border-radius: 1rem;
width: 300px;
}
.sr-only {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
.container {
display: grid;
justify-content: center;
width: 300px;
margin: 0 auto;
}
.add {
font-size: 2rem;
width: 3rem;
height: 3rem;
line-height: 0;
margin: 0 auto;
}
function deleteListItem() {
const listItem = this.parentNode;
// Still need JS to animate out
// Need to inert this out
if (document.startViewTransition) {
document.startViewTransition(() => {
listItem.remove();
});
} else {
listItem.remove();
}
}
let counter = 5;
function addListItem() {
// Get the input value from the text field
const inputField = document.getElementById('newItem');
const newItemText = `New Item ${counter}`
// Create a new list item element
const newItem = document.createElement('li');
counter++;
newItem.className = `item item-${counter}`;
// Create a paragraph element with the new item text
const itemText = document.createElement('p');
itemText.textContent = newItemText;
newItem.appendChild(itemText);
// Add style for unique view transition
const vtStyle = `view-transition-name: item-${counter}`;
newItem.style.viewTransitionName = `item-${counter}`;
// Create a delete button element
const deleteButton = document.createElement('button');
deleteButton.className = 'delete';
deleteButton.addEventListener('click', deleteListItem);
// Add an X symbol to the delete button
const xSymbol = document.createElement('span');
xSymbol.setAttribute('aria-hidden', 'true');
xSymbol.textContent = '❌';
deleteButton.appendChild(xSymbol);
// Add a visually hidden label to the delete button
const srLabel = document.createElement('span');
srLabel.className = 'sr-only';
srLabel.textContent = 'delete';
deleteButton.appendChild(srLabel);
// Add the delete button to the list item element
newItem.appendChild(deleteButton);
// Add the new list item to the list
const list = document.querySelector('.items');
if (document.startViewTransition) {
document.startViewTransition(() => {
list.appendChild(newItem);
})} else {
list.appendChild(newItem);
}
}
const addButton = document.querySelector('.add');
const deleteButtons = document.querySelectorAll('.delete');
addButton.addEventListener('click', addListItem);
deleteButtons.forEach(button => {
button.addEventListener('click', deleteListItem);
});