Skip to content

Instantly share code, notes, and snippets.

@chriswitko
Created September 11, 2024 02:15
Show Gist options
  • Save chriswitko/671f8dbc0d6165fc7bf6e56e314a60ee to your computer and use it in GitHub Desktop.
Save chriswitko/671f8dbc0d6165fc7bf6e56e314a60ee to your computer and use it in GitHub Desktop.
Rating Web Component
class RatingComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.code = this.getAttribute('code') || '';
this.render();
}
get open() {
return this.hasAttribute('open');
}
set open(value) {
if (value) {
this.setAttribute('open', '');
} else {
this.removeAttribute('open');
}
this.render();
}
connectedCallback() {
this.render();
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host { display: ${this.open ? 'block' : 'none'}; }
.modal {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 300px;
background-color: white;
border: 1px solid #ccc;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
padding: 16px;
z-index: 1000;
}
.stars {
display: flex;
cursor: pointer;
margin-bottom: 10px;
}
.star {
font-size: 24px;
color: #ccc;
}
.star.selected {
color: gold;
}
.comment-box {
width: 100%;
margin-bottom: 10px;
}
.modal-footer {
display: flex;
justify-content: space-between;
}
</style>
<div class="modal">
<div class="stars">
${[1, 2, 3, 4, 5].map((i) => `
<span class="star" data-value="${i}">&#9733;</span>
`).join('')}
</div>
<textarea class="comment-box" placeholder="Leave a comment..." rows="3"></textarea>
<div class="modal-footer">
<button class="close-btn">Close</button>
<button class="submit-btn">Submit</button>
</div>
</div>
`;
this.shadowRoot.querySelectorAll('.star').forEach(star => {
star.addEventListener('click', (e) => this.selectRating(e));
});
this.shadowRoot.querySelector('.close-btn').addEventListener('click', () => this.close());
this.shadowRoot.querySelector('.submit-btn').addEventListener('click', () => this.submit());
}
selectRating(e) {
const value = e.target.getAttribute('data-value');
this.selectedRating = value;
this.shadowRoot.querySelectorAll('.star').forEach(star => {
star.classList.toggle('selected', star.getAttribute('data-value') <= value);
});
}
close() {
this.open = false;
this.dispatchEvent(new CustomEvent('close'));
}
submit() {
const comment = this.shadowRoot.querySelector('.comment-box').value;
const rating = this.selectedRating;
if (rating) {
const payload = {
rating,
comment,
code: this.code
};
console.log('Submitting:', payload);
// Simulate sending data to the server
this.dispatchEvent(new CustomEvent('submit', { detail: payload }));
// Close the modal after submission
this.close();
} else {
alert('Please select a rating.');
}
}
}
customElements.define('rating-component', RatingComponent);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment