From 3a4f7caf2bc187390a708221ae756bb9d75b6d38 Mon Sep 17 00:00:00 2001 From: Cory Dransfeldt Date: Mon, 30 Sep 2024 12:39:55 -0700 Subject: [PATCH] fix(rating): address inconsistent behavior in rating hover state --- .changeset/spotty-penguins-sort.md | 5 +++ components/rating/index.css | 21 ++++++----- components/rating/stories/template.js | 52 +++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 .changeset/spotty-penguins-sort.md diff --git a/.changeset/spotty-penguins-sort.md b/.changeset/spotty-penguins-sort.md new file mode 100644 index 00000000000..800349cd889 --- /dev/null +++ b/.changeset/spotty-penguins-sort.md @@ -0,0 +1,5 @@ +--- +"@spectrum-css/rating": minor +--- + +Provides more granular control over the hover behavior of child stars within the rating component to prevent hovering in space adjacent to the component from highlighting all stars. diff --git a/components/rating/index.css b/components/rating/index.css index 9d523f0ecdd..6c10a6ed007 100644 --- a/components/rating/index.css +++ b/components/rating/index.css @@ -98,17 +98,6 @@ cursor: default; pointer-events: none; } - - /* When the entire component is hovered, show all solid icons */ - &:hover { - .spectrum-Rating-starActive { - display: block; - } - - .spectrum-Rating-starInactive { - display: none; - } - } } .spectrum-Rating-input { @@ -168,6 +157,16 @@ display: block; } } + + &.is-hovered { + .spectrum-Rating-starActive { + display: block; + } + + .spectrum-Rating-starInactive { + display: none; + } + } } .spectrum-Rating-starActive, diff --git a/components/rating/stories/template.js b/components/rating/stories/template.js index 245694af8fa..d0d5ef9bf78 100644 --- a/components/rating/stories/template.js +++ b/components/rating/stories/template.js @@ -19,6 +19,58 @@ export const Template = ({ id = getRandomId("rating"), } = {}, context = {}) => { const { updateArgs } = context; + document.addEventListener("DOMContentLoaded", function() { + const rating = document.getElementById(id); + if (rating.classList.contains("is-disabled") || rating.classList.contains("is-readOnly")) return; + const icons = Array.from(rating.getElementsByClassName("spectrum-Rating-icon")); + let hoverIndex = -1; + let selectedIndex = -1; + + const updateHoverState = () => { + icons.forEach((icon, index) => { + const activeStar = icon.querySelector(".spectrum-Rating-starActive"); + const inactiveStar = icon.querySelector(".spectrum-Rating-starInactive"); + + if (index <= hoverIndex) { + icon.classList.add("is-hovered"); + activeStar.style.display = "block"; + inactiveStar.style.display = "none"; + } + else if (index <= selectedIndex && hoverIndex === -1) { + activeStar.style.display = "block"; + inactiveStar.style.display = "none"; + } + else { + icon.classList.remove("is-hovered"); + activeStar.style.display = "none"; + inactiveStar.style.display = "block"; + } + }); + }; + + icons.forEach((icon, index) => { + if (icon.classList.contains("is-selected")) selectedIndex = index; + + icon.addEventListener("mouseover", function() { + hoverIndex = index; + updateHoverState(); + }); + + icon.addEventListener("mouseleave", function(event) { + if (!rating.contains(event.relatedTarget)) { + hoverIndex = -1; + updateHoverState(); + } + }); + + icon.addEventListener("click", function() { + selectedIndex = index; + updateHoverState(); + }); + }); + + updateHoverState(); + }); return html`