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

fix(slider): added filled offset variant #3876

Merged
merged 28 commits into from Jan 17, 2024
Merged

fix(slider): added filled offset variant #3876

merged 28 commits into from Jan 17, 2024

Conversation

Rajdeepc
Copy link
Contributor

@Rajdeepc Rajdeepc commented Dec 15, 2023

Description

Add fill-start/fill-offset functionality to Slider

Related issue(s)

Motivation and context

How has this been tested?

  • Test case 1
    1. Go here
    2. Run this test

Screenshots (if appropriate)

fillslider.mov

With only fill-start, fill starting from center
Screenshot 2023-12-18 at 2 40 17 PM

With a fill-start value, fill starting from fill-start value
Screenshot 2024-01-08 at 10 52 54 AM

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Chore (minor updates related to the tooling or maintenance of the repository, does not impact compiled assets)

Checklist

  • I have signed the Adobe Open Source CLA.
  • My code follows the code style of this project.
  • If my change required a change to the documentation, I have updated the documentation in this pull request.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have reviewed at the Accessibility Practices for this feature, see: Aria Practices

Best practices

This repository uses conventional commit syntax for each commit message; note that the GitHub UI does not use this by default so be cautious when accepting suggested changes. Avoid the "Update branch" button on the pull request and opt instead for rebasing your branch against main.

@Rajdeepc Rajdeepc added enhancement New feature or request Component: Slider labels Dec 15, 2023
@Rajdeepc Rajdeepc changed the title chore(slider): added filled offset variant feat(slider): added filled offset variant Dec 15, 2023
@Rajdeepc Rajdeepc linked an issue Dec 15, 2023 that may be closed by this pull request
Copy link

github-actions bot commented Dec 15, 2023

Tachometer results

Chrome

slider permalink

Version Bytes Avg Time vs remote vs branch
npm latest 478 kB 125.17ms - 128.30ms - slower ❌
2% - 5%
1.97ms - 5.54ms
branch 467 kB 122.11ms - 123.84ms faster ✔
2% - 4%
1.97ms - 5.54ms
-
Firefox

slider permalink

Version Bytes Avg Time vs remote vs branch
npm latest 478 kB 231.07ms - 238.65ms - slower ❌
3% - 8%
6.82ms - 17.62ms
branch 467 kB 218.79ms - 226.49ms faster ✔
3% - 7%
6.82ms - 17.62ms
-

@Rajdeepc Rajdeepc force-pushed the bug/slider-filled branch 2 times, most recently from 3b9073b to c067b70 Compare December 18, 2023 07:41
@Rajdeepc Rajdeepc linked an issue Dec 18, 2023 that may be closed by this pull request
1 task
@@ -160,6 +164,9 @@ export class Slider extends SizedMixin(ObserveSlotText(SliderHandle, ''), {
@property({ type: Boolean, reflect: true })
public override disabled = false;

@property({ type: Boolean, reflect: true, attribute: 'fill-start' })
public fillStart = false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is supposed to be a boolean. I think it is supposed to represent where the fill starts from. By default it would equal the same as min but then set it would allow for the fill to start from whereever.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, maybe be unneeded work, but should we also surface a relativeValue property that give the value relative to the start? Calculable from the outside, so maybe not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should min the start value or the initial value represented as 'value' ?
fillStart boolean creates the filled highlight on the track.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be misunderstand, so let's check with the design team, but I understand the workflow to be:

<sp-slider></sp-slider> // No fill

<sp-slider
    variant="filled"
></sp-slider> // Fill from `min`, or 0 by default

<sp-slider
    variant="filled"
    fill-start="5"
    min="0"
    max="10"
></sp-slider> // Fill from 5, or half way

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure I was wondering if fill-start="5" and value="6" then how will the slider behave? which takes precendence?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0                    20
|----==0-------------|

I think it would look like this where the fill-started at 5 and the fill went to 6 where the handle stood. More clear might be variant="filled" fill-start value="15" min="0" max="20", variant="filled" fill-start="5" value="15" min="0" max="20", and variant="filled" fill-start="5" value="0" min="0" max="20" as comparison:

0                    20
|----------====0-----|
0                    20
|----==========0-----|
0                    20
0===-----------------|

When fill-start is present, the fill starts at half the value like you've previously outlined. When fill-start is supplied a value, the fill starts from that value. The fill goes from that number to the value provided. The delta from the fill-start to the value would be the relativeValue if we chose to surface it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. For this variant variant="filled" fill-start value="15" min="0" max="20" , handle will be at 10 i.e the center.
    When user slides from 10 - 20 and 10 - 0 should the fill be visible for both or it should only be visible from 10-15?

  2. For this variant variant="filled" fill-start="5" value="15" min="0" max="20"
    the handle should start from the fill-start value of "5" or from value="15" itself? And also do we show fill from 5-15 only or from 5-0 also?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

variant="filled" fill-start value="15" min="0" max="20"
In this case the "fill" will start at half (so 10) but the value will be 15, so the "fill" will take up 1/4 of the track starting from the middle.

0                    20
|----------====0-----|

variant="filled" fill-start value="10" min="0" max="20"
Fill starting at half (10) and value at 10.

0                    20
|----------0---------|

User moves handle to 20

0                    20
|----------==========0

User moves handle to 0

0                    20
0===========---------|

variant="filled" fill-start="5" value="15" min="0" max="20"
Fill takes up half of the track starting 1/4 of the way along the track.

0                    20
|-----=========0-----|

User moves to 0, fill size is 1/4 of the track starting at the beginning of the track.

0                    20
0=====---------------|

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attached video recording for preview and review. Let me know how this solution looks now.

@Westbrook Westbrook changed the title feat(slider): added filled offset variant fix(slider): added filled offset variant Jan 5, 2024
Copy link
Collaborator

@Westbrook Westbrook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One visual outcome in the stories that seems wrong:
image

Beyond that, I think we're in alignment on how things should end up, just a couple of nips and tucks and this should be on its way!

<script type="module">
const initSlider = async () => {
const slider = document.querySelector('#fill-start-slider');
slider.fillStart = 0.3
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not apply this with the fill-start attribute?

Copy link
Contributor Author

@Rajdeepc Rajdeepc Jan 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjusted the logic to add fill-start as an empty attribute as well as with a value

Comment on lines 531 to 538
if (typeof this.fillStart === 'number') {
this.fillStartPoint = this.fillStart;
} else {
this.fillStartPoint =
(Number(this.max) - Number(this.min)) / 2 +
Number(this.min);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this just be a getter instead? That would allow us to not place fillStartPoint as a reactive property, as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now using the fillStartPoint getter

private get fillStartPoint(): number {
        if (this.fillStart) {
            return Number(this.fillStart);
        } else {
            return (Number(this.max) - Number(this.min)) / 2 + Number(this.min);
        }
    }

Comment on lines 395 to 397
class=${`fill ${
!!(this.value > this.fillStartPoint) ? 'offset' : ''
}`}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using classMap({fill: true, offset: this.value > this.fillStartPoint}) might make this easier to read.

Comment on lines 398 to 409
style=${styleMap({
[this.dir === 'rtl' ? 'right' : 'left']: `${
this.value > this.fillStartPoint
? this.getOffsetPosition(this.fillStartPoint)
: this.getOffsetPosition(this.value)
}%`,
width: `${this.getOffsetWidth(
this.fillStartPoint,
this.value,
this._cachedValue
)}%`,
})}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With a complex map like this, we may want to create it as a variable outside of the template, so that it is easier to read.

Copy link
Contributor Author

@Rajdeepc Rajdeepc Jan 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been updated to make it more modular

packages/slider/src/Slider.ts Show resolved Hide resolved
<div style="width: 500px; margin-inline: 20px;">
<sp-slider
max="1"
fill-start
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we still want variant="filled" here. I know this is less things, but it's also less clear. I could be convinced away, but it feels more expected for each of the "filled" sliders to have the same variant and for the fill-start attribute to change the way that the fill is delivered.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we cannot use variant="fiiled" when using this property fill-start becuase of this css

:host([variant='filled']) .track:first-child:before {
    background: var(
        --highcontrast-slider-track-fill-color,
        var(
            --mod-slider-track-fill-color,
            var(--spectrum-slider-track-fill-color)
        )
    );
}

If fill-start has value then the track will be filled even if it is not starting from 0

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That means we're opening a fail state in the API <sp-slider variant="filled" fill-start="15" max="20" value="5"></sp-slider>. How would you like to handle this case and support consumers to success?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this use case. This should be handled now

await nextFrame();

expect(el.value).to.equal(24);
expect(el.shadowRoot.querySelector('.fill') as HTMLDivElement).to.exist;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a good idea to assert that .fill doesn't exist to get started with?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

class fill will be there when fill-start or fill-start with value is there with width as 0% when only fill-start

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then a presence check is likely not enough to actually guarantee that the role that element is playing is complete to the situation in question.

Copy link
Collaborator

@Westbrook Westbrook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, found two quick nits.

Comment on lines 373 to 377
if (fillStartValue === cachedValue) {
distance = Math.abs(currentValue - fillStartValue);
} else {
distance = Math.abs(currentValue - fillStartValue);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like the same on both sides of the logic.

max="1"
variant="filled"
min="0"
value=".5"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, can we use a value other than the middle of the range so that this story shows the fill by default in VRT so that we can test that the output stays the same over time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2024-01-17 at 11 34 00 AM

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry, I put this comment on the wrong story. 😞 I meant for https://bug-slider-filled--spectrum-web-components.netlify.app/storybook/?path=/story/slider--fill-start for all the same reasons. I swear this is the last thing!

Copy link
Contributor Author

@Rajdeepc Rajdeepc Jan 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2024-01-17 at 6 45 46 PM
<sp-slider
      max="1"
      fill-start
      min="0"
      value=".7"
      step="0.01"
      @input=${handleEvent(args)}
      @change=${handleEvent(args)}
      .formatOptions=${{ style: 'percent' }}
      ...=${spreadProps(args)}
>
    Slider label
</sp-slider>
            

Copy link
Collaborator

@Westbrook Westbrook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM! Checking with @beeduul to confirm this covers a use case that recently came up for him and then we can merge this in. Thanks for getting this together!

@beeduul
Copy link
Collaborator

beeduul commented Jan 17, 2024

Thanks for checking @Westbrook. My use case only requires the vanilla fill-start attribute to start in the middle of the slider, so lgtm!

Copy link
Collaborator

@Westbrook Westbrook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit: 🥳

@Westbrook Westbrook merged commit 2c3e35e into main Jan 17, 2024
47 checks passed
@Westbrook Westbrook deleted the bug/slider-filled branch January 17, 2024 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Slider enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add fill-start/fill-offset functionality to Slider
3 participants