mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
fix(slider): calculate the correct value on mark click (#3017)
* fix(slider): calculate the correct value on mark click * refactor(slider): remove the tests inside describe block * feat(slider): add tests for thumb move on mark click * refactor(slider): use val instead of pos
This commit is contained in:
parent
9d63259eea
commit
5329de42d2
5
.changeset/olive-kids-hide.md
Normal file
5
.changeset/olive-kids-hide.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"@nextui-org/slider": patch
|
||||
---
|
||||
|
||||
calculate the correct value on mark click (#2980)
|
||||
@ -213,78 +213,161 @@ describe("Slider", () => {
|
||||
|
||||
expect(setValues).toStrictEqual([[15, 25]]);
|
||||
});
|
||||
});
|
||||
|
||||
it("should supports hideThumb", async function () {
|
||||
const {container} = render(<Slider hideThumb defaultValue={20} label="The Label" />);
|
||||
|
||||
const track = container.querySelector("[data-slot='track']");
|
||||
|
||||
expect(track).toHaveAttribute("data-thumb-hidden", "true");
|
||||
});
|
||||
|
||||
it("should supports marks", async function () {
|
||||
const {container} = render(
|
||||
<Slider
|
||||
hideThumb
|
||||
defaultValue={20}
|
||||
label="The Label"
|
||||
marks={[
|
||||
{
|
||||
value: 0.2,
|
||||
label: "20%",
|
||||
},
|
||||
{
|
||||
value: 0.5,
|
||||
label: "50%",
|
||||
},
|
||||
{
|
||||
value: 0.8,
|
||||
label: "80%",
|
||||
},
|
||||
]}
|
||||
maxValue={1}
|
||||
minValue={0}
|
||||
step={0.1}
|
||||
/>,
|
||||
);
|
||||
|
||||
const marks = container.querySelectorAll("[data-slot='mark']");
|
||||
|
||||
expect(marks).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("should supports marks with hideThumb", async function () {
|
||||
const {container} = render(
|
||||
<Slider
|
||||
hideThumb
|
||||
defaultValue={20}
|
||||
label="The Label"
|
||||
marks={[
|
||||
{
|
||||
value: 0.2,
|
||||
label: "20%",
|
||||
},
|
||||
{
|
||||
value: 0.5,
|
||||
label: "50%",
|
||||
},
|
||||
{
|
||||
value: 0.8,
|
||||
label: "80%",
|
||||
},
|
||||
]}
|
||||
maxValue={1}
|
||||
minValue={0}
|
||||
step={0.1}
|
||||
/>,
|
||||
);
|
||||
|
||||
const track = container.querySelector("[data-slot='track']");
|
||||
|
||||
expect(track).toHaveAttribute("data-thumb-hidden", "true");
|
||||
|
||||
const marks = container.querySelectorAll("[data-slot='mark']");
|
||||
|
||||
expect(marks).toHaveLength(3);
|
||||
|
||||
it("should supports hideThumb", async function () {
|
||||
const {container} = render(<Slider hideThumb defaultValue={20} label="The Label" />);
|
||||
|
||||
const track = container.querySelector("[data-slot='track']");
|
||||
|
||||
expect(track).toHaveAttribute("data-thumb-hidden", "true");
|
||||
});
|
||||
|
||||
it("should supports marks", async function () {
|
||||
const {container} = render(
|
||||
<Slider
|
||||
hideThumb
|
||||
defaultValue={20}
|
||||
label="The Label"
|
||||
marks={[
|
||||
{
|
||||
value: 0.2,
|
||||
label: "20%",
|
||||
},
|
||||
{
|
||||
value: 0.5,
|
||||
label: "50%",
|
||||
},
|
||||
{
|
||||
value: 0.8,
|
||||
label: "80%",
|
||||
},
|
||||
]}
|
||||
maxValue={1}
|
||||
minValue={0}
|
||||
step={0.1}
|
||||
/>,
|
||||
);
|
||||
|
||||
const marks = container.querySelectorAll("[data-slot='mark']");
|
||||
|
||||
expect(marks).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("should supports marks with hideThumb", async function () {
|
||||
const {container} = render(
|
||||
<Slider
|
||||
hideThumb
|
||||
defaultValue={20}
|
||||
label="The Label"
|
||||
marks={[
|
||||
{
|
||||
value: 0.2,
|
||||
label: "20%",
|
||||
},
|
||||
{
|
||||
value: 0.5,
|
||||
label: "50%",
|
||||
},
|
||||
{
|
||||
value: 0.8,
|
||||
label: "80%",
|
||||
},
|
||||
]}
|
||||
maxValue={1}
|
||||
minValue={0}
|
||||
step={0.1}
|
||||
/>,
|
||||
);
|
||||
|
||||
const track = container.querySelector("[data-slot='track']");
|
||||
|
||||
expect(track).toHaveAttribute("data-thumb-hidden", "true");
|
||||
|
||||
const marks = container.querySelectorAll("[data-slot='mark']");
|
||||
|
||||
expect(marks).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("should move thumb after clicking mark (single thumb)", async function () {
|
||||
const {getByRole, container} = render(
|
||||
<Slider
|
||||
hideThumb
|
||||
defaultValue={0.2}
|
||||
label="The Label"
|
||||
marks={[
|
||||
{
|
||||
value: 0.2,
|
||||
label: "20%",
|
||||
},
|
||||
{
|
||||
value: 0.5,
|
||||
label: "50%",
|
||||
},
|
||||
{
|
||||
value: 0.8,
|
||||
label: "80%",
|
||||
},
|
||||
]}
|
||||
maxValue={1}
|
||||
minValue={0}
|
||||
step={0.1}
|
||||
/>,
|
||||
);
|
||||
|
||||
const marks = container.querySelectorAll("[data-slot='mark']");
|
||||
|
||||
expect(marks).toHaveLength(3);
|
||||
|
||||
await act(async () => {
|
||||
await userEvent.click(marks[1]);
|
||||
});
|
||||
|
||||
const slider = getByRole("slider");
|
||||
|
||||
expect(slider).toHaveProperty("value", "0.5");
|
||||
expect(slider).toHaveAttribute("aria-valuetext", "0.5");
|
||||
});
|
||||
|
||||
it("should move thumb after clicking mark (left and right thumbs)", async function () {
|
||||
const {getAllByRole, container} = render(
|
||||
<Slider
|
||||
hideThumb
|
||||
defaultValue={[0.2, 0.8]}
|
||||
label="The Label"
|
||||
marks={[
|
||||
{
|
||||
value: 0.2,
|
||||
label: "20%",
|
||||
},
|
||||
{
|
||||
value: 0.5,
|
||||
label: "50%",
|
||||
},
|
||||
{
|
||||
value: 0.8,
|
||||
label: "80%",
|
||||
},
|
||||
]}
|
||||
maxValue={1}
|
||||
minValue={0}
|
||||
step={0.1}
|
||||
/>,
|
||||
);
|
||||
|
||||
const marks = container.querySelectorAll("[data-slot='mark']");
|
||||
|
||||
expect(marks).toHaveLength(3);
|
||||
|
||||
await act(async () => {
|
||||
await userEvent.click(marks[1]);
|
||||
});
|
||||
|
||||
const [leftSlider, rightSlider] = getAllByRole("slider");
|
||||
|
||||
expect(leftSlider).toHaveProperty("value", "0.5");
|
||||
expect(leftSlider).toHaveAttribute("aria-valuetext", "0.5");
|
||||
|
||||
expect(rightSlider).toHaveProperty("value", "0.8");
|
||||
expect(rightSlider).toHaveAttribute("aria-valuetext", "0.8");
|
||||
});
|
||||
});
|
||||
|
||||
@ -389,6 +389,30 @@ export function useSlider(originalProps: UseSliderProps) {
|
||||
style: {
|
||||
[isVertical ? "bottom" : direction === "rtl" ? "right" : "left"]: `${percent * 100}%`,
|
||||
},
|
||||
// avoid `onDownTrack` is being called since when you click the mark,
|
||||
// `onDownTrack` will calculate the percent based on the position you click
|
||||
// the calculated value will be set instead of the actual value defined in `marks`
|
||||
onMouseDown: (e: React.MouseEvent) => e.stopPropagation(),
|
||||
onPointerDown: (e: React.PointerEvent) => e.stopPropagation(),
|
||||
onClick: (e: any) => {
|
||||
e.stopPropagation();
|
||||
if (state.values.length === 1) {
|
||||
state.setThumbPercent(0, percent);
|
||||
} else {
|
||||
const leftThumbVal = state.values[0];
|
||||
const rightThumbVal = state.values[1];
|
||||
|
||||
if (mark.value < leftThumbVal) {
|
||||
state.setThumbPercent(0, percent);
|
||||
} else if (mark.value > rightThumbVal) {
|
||||
state.setThumbPercent(1, percent);
|
||||
} else if (Math.abs(mark.value - leftThumbVal) < Math.abs(mark.value - rightThumbVal)) {
|
||||
state.setThumbPercent(0, percent);
|
||||
} else {
|
||||
state.setThumbPercent(1, percent);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user