Created
September 11, 2024 02:15
-
-
Save chriswitko/671f8dbc0d6165fc7bf6e56e314a60ee to your computer and use it in GitHub Desktop.
Rating Web Component
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}">★</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