-
Notifications
You must be signed in to change notification settings - Fork 75
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
feat(slider): Implement vertical orientation #9953
Conversation
This PR has been automatically marked as stale because it has not had recent activity. Please close your PR if it is no longer relevant. Thank you for your contributions. |
This PR has been automatically marked as stale because it has not had recent activity. Please close your PR if it is no longer relevant. Thank you for your contributions. |
expect(button).toEqualAttribute("aria-valuemin", "0"); | ||
expect(button).toEqualAttribute("aria-valuemax", "100"); | ||
expect(button).toEqualAttribute("aria-orientation", "horizontal"); | ||
for (const l of ["horizontal", "vertical"]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of adding a for loop inside the tests, can you wrap them all in a describe.each
block. Something like this:
describe.each(["horizontal", "vertical"])("%s layout", (layout) => {
// tests here
})
NOTE: I typed that directly into the comment so the syntax may be off.
This will make it easier to determine which layout is causing issues when there are test failures. Also we have a convention not to abbreviate so I changed l
to layout
.
scale="m" | ||
></calcite-slider> | ||
`; | ||
const simple = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need separate "simple" stories for the layout
property because it can be changed via the knobs.
}; | ||
|
||
const rangeLabeledTicksEdgePositioningAtMin = {}; | ||
for (const l of ["horizontal", "vertical"]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think all of these stories need to be duplicated for vertical vs horizontal.
How about one vertical story that has a couple sliders with different configurations that might be impacted by the change in layout?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great progress, @josercarcamo! 💪
I brought up some things that need to be addressed. LMK if you have any questions.
@@ -559,8 +576,9 @@ export class Slider | |||
return; | |||
} | |||
|
|||
const x = event.clientX || event.pageX; | |||
const position = this.mapToRange(x); | |||
const v = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does v
represent? If it's value
, can you rename it to be more expressive?
@@ -938,13 +958,20 @@ export class Slider | |||
/** | |||
* Translate a pixel position to value along the range | |||
* | |||
* @param x | |||
* @param p |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you rename this to be expressive?
const { left, width } = this.trackEl.getBoundingClientRect(); | ||
const percent = (x - left) / width; | ||
let percent: number; | ||
if (this.layout === "horizontal") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a bit of duplication here. Can you DRY it up?
@@ -247,6 +249,9 @@ export class Slider | |||
} | |||
|
|||
componentDidRender(): void { | |||
if (this.layout === "vertical") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIXME: this is bypassing logic that should apply to both layouts (e.g., avoiding label overlap). You can see the difference by comparing edge/overlapping stories in both layouts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, most of this code translates the handle label in the x direction, which is not needed for vertical.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to handle vertical label overlap for both layouts. You can see this if you compare the edge/overlapping stories:
Range Labeled Ticks Edge Positioning At Max
Range Labeled Ticks Overlapping At Min
@ashetland Do we need hyphenation when vertical?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch! Yep, looks like we need this on vertical as well. While we're at it, is it possible to add a space so it would look like 99.5 - 100
instead of 99.5- 100
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we please update the design since the numbers are now one on top of the other? Or should it just display "99.5 - 100 |" where "|" is the vertical range bar whenever they overlap each other?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, when the range handles overlap, it should display "99.5 - 100" like the horizontal layout.
></calcite-slider> | ||
`; | ||
} | ||
export const simpleH = simple["horizontal"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For readability, avoid abbreviations in test names.
export const rangeH = range["horizontal"]; | ||
export const rangeV = range["vertical"]; | ||
|
||
const darkMode = {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you type this, and similar objects? May not be applicable if story functions are parameterized.
></calcite-slider> | ||
`; | ||
} | ||
export const simpleH = simple["horizontal"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIXME: can you restore the names for the previous, horizontal stories? Renamed stories will get treated as new ones and won't display a diff.
For improved organization, we could look at having separate stories for each slider layout configuration. I think we can use title
for this separation and have Storybook take care of the hierarchy (e.g., title: "Components/Controls/Slider
[default], title: "Components/Controls/Slider/Vertical"
[new]). I'm open to other ideas too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if we make it so each story has two sliders - one horizontal and one vertical? That way we don't double slider's chromatic snapshots. Specifically for simple
, we only need one slider because it can be changed via knobs like I mentioned above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dig this. Besides reducing snapshots, it also makes it easier to add coverage for both compared to handling them separately.
`; | ||
const simple = {}; | ||
for (const l of ["horizontal", "vertical"]) { | ||
simple[l] = (args: SliderStoryArgs): string => html` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Storybook allows us to pass arguments to stories, so can you update these to use args
:
const SimpleTemplate = {
render: (args: SliderStoryArgs): string => html`
<calcite-slider
min="${args.min}"
max="${args.max}"
value="${args.value}"
step="${args.step}"
min-label="${args.minLabel}"
${boolean("disabled", args.disabled)}
${boolean("label-handles", args.labelHandles)}
${boolean("label-ticks", args.labelTicks)}
ticks="${args.ticks}"
page-step="${args.pageStep}"
${boolean("precise", args.precise)}
${boolean("mirrored", args.mirrored)}
${boolean("snap", args.snap)}
scale="${args.scale}"
layout=${args.layout || "horizontal"}
style="${args.style}"
></calcite-slider>
`;
}
export const simple = {
...SimpleTemplate,
// default "horizontal" specified at [CSF (story metadata) level](https://github.com/Esri/calcite-design-system/pull/9953/files#diff-a4b7803179119e68983d2abf8a806a8e0be7c72550eee9a97a583b289c01ba0aR46)
};
export const simpleVertical = {
...SimpleTemplate,
args: {
layout: "vertical"
}
};
Generalizing the template might help simplify setup for other stories.
@@ -42,6 +43,8 @@ export default { | |||
mirrored: false, | |||
snap: true, | |||
scale: scale.defaultValue, | |||
layout: "horizontal", | |||
style: "padding-top: 200px; padding-left: 100px; height: 200px", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIXME: it looks like style
was added to work around the slider not having the proper box model. In general, we only want to provide defaults for component props.
(this.layout === "horizontal" && | ||
(minThumbTypes.includes("histogram") || minThumbTypes.includes("precise"))) || | ||
(this.layout === "vertical" && valueIsRange && this.precise && !this.mirrored) || | ||
(this.layout === "vertical" && valueIsRange && this.precise && this.mirrored) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mirrored
is canceled out in these or statements, so you could simplify this to:
thumbPlacement:
(this.layout === "horizontal" && (minThumbTypes.includes("histogram") || minThumbTypes.includes("precise"))) ||
(this.layout === "vertical" && valueIsRange && this.precise);
db157ab
to
d7c9321
Compare
Related Issue: #5522
Summary
Implemented a vertical orientation for the slider, along with label, precise, ticks.