Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] <sl-rating> - Add an event when hovering over a rating (or when no longer hovering over a rating) #1125

Closed
mpharoah opened this issue Jan 10, 2023 · 4 comments
Assignees
Labels
feature Feature requests.

Comments

@mpharoah
Copy link
Contributor

mpharoah commented Jan 10, 2023

What issue are you having?

I would like to be able to update text based on the rating that is currently being hovered over. This text will describe what the rating level represents. Here is an example of what I mean:
rating-preview-example

Describe the solution you'd like

I would like to see an event emitted from the component when the user either hovers over a new rating value for an editable rating, or stops hovering over a rating. The event should contain a value representing the value currently hovered (or null when the user stops hovering over it).

An example of one possible implementation of this feature (this would also fire an event when the component initializes which may or may not be desirable):

// src/components/rating/rating.ts

export type SlRatingPreviewEvent = CustomEvent<{ hoverValue: number | null }>;

...

// in the SlRating class
protected override willUpdate( changedProperties: PropertyValues ) : void {
	super.willUpdate( changedProperties );
	
	if( changedProperties.has( 'hoverValue' ) || changedProperties.has( 'isHovering' ) ) {
		this.emit( 'sl-preview', {
			detail: {
				hoverValue: this.isHovering ? this.hoverValue : null
			}
		});
	}
}

Describe alternatives you've considered

I am currently able to implement my desired behaviour with the Shoelace component; however, it requires accessing the component's internal state, and attaching to a number of event handlers. I would like a cleaner solution that doesn't rely on the component's implementation details.

My current workaround:

// Hack: un-private internal state
interface SlRatingInternal extends Omit<Omit<SlRating, 'hoverValue'>, 'isHovering'> {
	hoverValue: number;
	isHovering: boolean;
}

...

<sl-rating
	id="my-element"
	...
	@keydown=${this.#updateHover}
	@mouseenter=${this.#updateHover}
	@touchstart=${this.#updateHover}
	@mouseleave=${this.#updateHover}
	@touchend=${this.#updateHover}
	@mousemove=${this.#updateHover}
	@touchmove=${this.#updateHover}
></sl-rating>

...

#updateHover() : void {
	const ratingElement = this.shadowRoot.getElementById( 'my-element' ) as SlRatingInternal;
	this.hoverRating = ratingElement?.isHovering ? ratingElement.hoverValue : null;
}
@mpharoah mpharoah added the feature Feature requests. label Jan 10, 2023
@claviska
Copy link
Member

Good idea, since this is really hard to get otherwise. I added an sl-hover event in 0c2f43b that gives you this ability.

I didn't like the event name at first, but it makes a lot of sense considering that it does emit on hover. It also emits when you touch and drag, but one could argue that's close enough to hovering.

It's also worth noting that this works with the precision property so, if you allow half stars, you'll get the value on every .5 instead of every 1.

The event has a payload with two properties. The phase property indicates the hover phase (when it starts, when it moves to a new value, and when it ends). The value property reflects the hovered value.

// event.detail
{
  phase: 'start' | 'move' | 'end',
  value: number
}

I added this example to demonstrate usage.

This feature will be available in the next release of Shoelace.

@mpharoah
Copy link
Contributor Author

Excellent! Thanks for the swift response. I'll look forward to the update

@mpharoah
Copy link
Contributor Author

mpharoah commented Jan 10, 2023

By the way, is there a good way to get the event details type in Typescript for an event? Shoelace doesn't seem to export types for events.

@claviska
Copy link
Member

They're not currently typed, just documented. I'd love a PR from anyone who has an elegant suggestion for handling them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Feature requests.
Projects
None yet
Development

No branches or pull requests

2 participants