Improve performance of sl-rating by not render all icons twice

This commit is contained in:
Matt Pharoah
2023-04-20 17:01:12 -04:00
committed by konnorrogers
parent 6b51d4a8a0
commit 12e9ee836f
2 changed files with 41 additions and 35 deletions

View File

@@ -43,12 +43,19 @@ export default css`
padding: var(--symbol-spacing);
}
.rating__symbols--indicator {
position: absolute;
top: 0;
left: 0;
.rating__symbol--active,
.rating__partial--filled {
color: var(--symbol-color-active);
pointer-events: none;
}
.rating__partial-symbol-container {
position: relative;
}
.rating__partial--filled {
position: absolute;
top: var(--symbol-spacing);
left: var(--symbol-spacing);
}
.rating__symbol {
@@ -79,7 +86,7 @@ export default css`
/* Forced colors mode */
@media (forced-colors: active) {
.rating__symbols--indicator {
.rating__symbol--active {
color: SelectedItem;
}
}

View File

@@ -249,16 +249,39 @@ export default class SlRating extends ShoelaceElement {
@mousemove=${this.handleMouseMove}
@touchmove=${this.handleTouchMove}
>
<span class="rating__symbols rating__symbols--inactive">
<span class="rating__symbols">
${counter.map(index => {
// Users can click the current value to clear the rating. When this happens, we set this.isHovering to
// false to prevent the hover state from confusing them as they move the mouse out of the control. This
// extra mouseenter will reinstate it if they happen to mouse over an adjacent symbol.
if (displayValue > index && displayValue < index + 1) {
const clipLeft = styleMap({ clipPath: `inset(0 ${100 - ((displayValue - index) / 1) * 100}% 0 0)` });
const clipRight = styleMap({ clipPath: `inset(0 0 0 ${100 - ((displayValue - index) / 1) * 100}%)` });
// Users can click the current value to clear the rating. When this happens, we set this.isHovering to
// false to prevent the hover state from confusing them as they move the mouse out of the control. This
// extra mouseenter will reinstate it if they happen to mouse over an adjacent symbol.
return html`
<span
class=${classMap({
rating__symbol: true,
'rating__partial-symbol-container': true,
'rating__symbol--hover': this.isHovering && Math.ceil(displayValue) === index + 1
})}
role="presentation"
@mouseenter=${this.handleMouseEnter}
>
<div style=${isRtl ? clipLeft : clipRight}>${unsafeHTML(this.getSymbol(index + 1))}</div>
<div class="rating__partial--filled" style=${isRtl ? clipRight : clipLeft}>
${unsafeHTML(this.getSymbol(index + 1))}
</div>
</span>
`;
}
return html`
<span
class=${classMap({
rating__symbol: true,
'rating__symbol--hover': this.isHovering && Math.ceil(displayValue) === index + 1
'rating__symbol--hover': this.isHovering && Math.ceil(displayValue) === index + 1,
'rating__symbol--active': displayValue >= index + 1
})}
role="presentation"
@mouseenter=${this.handleMouseEnter}
@@ -268,30 +291,6 @@ export default class SlRating extends ShoelaceElement {
`;
})}
</span>
<span class="rating__symbols rating__symbols--indicator">
${counter.map(index => {
return html`
<span
class=${classMap({
rating__symbol: true,
'rating__symbol--hover': this.isHovering && Math.ceil(displayValue) === index + 1
})}
style=${styleMap({
clipPath:
displayValue > index + 1
? 'none'
: isRtl
? `inset(0 0 0 ${100 - ((displayValue - index) / 1) * 100}%)`
: `inset(0 ${100 - ((displayValue - index) / 1) * 100}% 0 0)`
})}
role="presentation"
>
${unsafeHTML(this.getSymbol(index + 1))}
</span>
`;
})}
</span>
</div>
`;
}