diff --git a/packages/main/cypress/specs/RangeSlider.cy.tsx b/packages/main/cypress/specs/RangeSlider.cy.tsx index f26350b96863..0ea5dbd2963e 100755 --- a/packages/main/cypress/specs/RangeSlider.cy.tsx +++ b/packages/main/cypress/specs/RangeSlider.cy.tsx @@ -1,1815 +1,1839 @@ -import RangeSlider from "../../src/RangeSlider.js"; - -describe("Testing Range Slider interactions", () => { - it("Changing the current startValue is reflected", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle-container") - .first() - .as("startHandle"); - - // Initially if no value is set, the Range Slider start-handle is at the beginning - cy.get("@startHandle").should("have.attr", "style").and("include", "left: 0%"); - - // Set startValue to 5 - cy.get("@rangeSlider").invoke("attr", "start-value", "5"); - cy.get("@startHandle").should("have.attr", "style").and("include", "left: 12.5%"); - - // Test programmatic value change and verify handle position updates - cy.get("@rangeSlider").invoke("attr", "start-value", "8"); - cy.get("@startHandle").should("have.attr", "style").and("include", "left: 20%"); - - // Test clicking on the slider to change value - cy.get("@rangeSlider").realClick({ x: 100 }); - - // The value should change after clicking - cy.get("@rangeSlider").should("have.attr", "start-value").and("not.eq", "5"); - }); - - it("Changing the endValue is reflected", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-inner .ui5-slider-handle-container") - .eq(1) - .as("endHandle"); - - // Check initial endValue (default should be 100, but with max=40, it should be 40) - cy.get("@rangeSlider").should("have.attr", "end-value", "40"); - cy.get("@endHandle").should("have.attr", "style").and("include", "left: 100%"); - - // Set endValue to 10 - cy.get("@rangeSlider").invoke("attr", "end-value", "10"); - cy.get("@endHandle").should("have.attr", "style").and("include", "left: 25%"); - - // Set endValue to 20 (middle) - cy.get("@rangeSlider").invoke("attr", "end-value", "20"); - cy.get("@endHandle").should("have.attr", "style").and("include", "left: 50%"); - - // Set endValue to 30 to verify another position - cy.get("@rangeSlider").invoke("attr", "end-value", "30"); - cy.get("@endHandle").should("have.attr", "style").and("include", "left: 75%"); - }); - - it("Click within the selected range should not change any value", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-progress") - .as("selectedRange"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "5"); - cy.get("@rangeSlider").should("have.attr", "end-value", "30"); - - // Click within the selected range (on the progress bar) - cy.get("@selectedRange").realClick(); - - cy.get("@rangeSlider").should("have.attr", "start-value", "5"); - cy.get("@rangeSlider").should("have.attr", "end-value", "30"); - }); - - it("Dragging the selected range should change both values and handles", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-progress") - .as("selectedRange"); - - // Get initial values - cy.get("@rangeSlider").should("have.attr", "start-value", "5"); - cy.get("@rangeSlider").should("have.attr", "end-value", "30"); - - // Drag the selected range to the right - cy.get("@selectedRange") - .realMouseDown() - .realMouseMove(50, 0) - .realMouseUp(); - - // Both values should change after dragging the range - cy.get("@rangeSlider").should("have.attr", "start-value").and("not.eq", "5"); - cy.get("@rangeSlider").should("have.attr", "end-value").and("not.eq", "30"); - - // The range size should remain the same (25 units) - cy.get("@rangeSlider").then(($slider) => { - const startValue = parseInt($slider.attr("start-value")); - const endValue = parseInt($slider.attr("end-value")); - expect(endValue - startValue).to.equal(25); - }); - }); - - it("Dragging the start-handle past the end-handle should swap the values", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("startHandle"); - - // Get initial values - cy.get("@rangeSlider").should("have.attr", "start-value", "8"); - cy.get("@rangeSlider").should("have.attr", "end-value", "9"); - - // Drag the start handle past the end handle - cy.get("@startHandle") - .realMouseDown() - .realMouseMove(100, 0) - .realMouseUp(); - - // Values should be swapped after dragging - cy.get("@rangeSlider").then(($el) => { - const rangeSlider = $el[0] as RangeSlider; - expect(rangeSlider.startValue).to.equal(9); - expect(rangeSlider.endValue).to.be.greaterThan(9); - }); - }); - - it("Dragging the whole range selection should always keep the initially selected range and be within min/max values", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-progress") - .as("selectedRange"); - - // Drag the selected range to the left (towards minimum) - cy.get("@selectedRange") - .realMouseDown() - .realMouseMove(-100, 0) - .realMouseUp(); - - // startValue should be 0 as the selected range has reached the start of the Range Slider - cy.get("@rangeSlider").should("have.attr", "start-value", "0"); - // endValue should be 21 and no less, the initially selected range should be preserved - cy.get("@rangeSlider").should("have.attr", "end-value", "21"); - - // Drag the selected range to the right (towards maximum) - cy.get("@selectedRange") - .realMouseDown() - .realMouseMove(600, 0) - .realMouseUp(); - - // startValue should be 7 and no more, the initially selected range should be preserved - cy.get("@rangeSlider").should("have.attr", "start-value", "7"); - // endValue should be 28 as the selected range has reached the end of the Range Slider - cy.get("@rangeSlider").should("have.attr", "end-value", "28"); - }); - - it("Range Slider should not be interactive if the step property is 0", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.get("@rangeSlider").realClick(); - - // endValue should remain the same - cy.get("@rangeSlider").should("have.attr", "end-value", "100"); - }); - - it("Disabled Range Slider is not interactive", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Range Slider should be disabled - cy.get("@rangeSlider").should("have.attr", "disabled"); - }); -}); - -describe("Range Slider elements - tooltip, step, tickmarks, labels", () => { - it("Range Slider have correct number of labels and tickmarks based on the defined step and labelInterval properties", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-labels") - .as("labelsContainer"); - - // With min=0, max=44, step=1, labelInterval=2: - // Total steps = (44-0)/1 = 44 steps - // Labels should appear every 2 steps: 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44 - // That's 23 labels total - cy.get("@labelsContainer").find("li").should("have.length", 23); - - // Check tickmarks - should have one for each step plus start and end - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-tickmark") - .should("have.length", 45); // 0 to 44 inclusive = 45 tickmarks - }); - it("Range Slider tooltips are displayed showing the current value", () => { - cy.get('[data-cy-root]') - .invoke('css', 'padding', '100px') - - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.get("@rangeSlider").realClick(); - - cy.get('@rangeSlider') - .shadow() - .find('[data-sap-ui-start-value]') - .as('startTooltip'); - - cy.get('@rangeSlider') - .shadow() - .find('[data-sap-ui-end-value]') - .as('endTooltip'); - - - cy.get("@rangeSlider").invoke("attr", "start-value", 65); - cy.get("@startTooltip").shadow().find(".ui5-slider-tooltip-value").should("have.text", "65"); - - cy.get("@rangeSlider").invoke("attr", "end-value", 115); - cy.get("@endTooltip").shadow().find(".ui5-slider-tooltip-value").should("have.text", "115"); - }); - - it("Tooltip input is displayed showing the current value", () => { - cy.mount( - - ); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.get("@rangeSlider").realClick(); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-start-value]') - .shadow() - .find("ui5-input") - .as("startTooltipInput"); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-end-value]') - .shadow() - .find("ui5-input") - .as("endTooltipInput"); - - cy.get("@startTooltipInput") - .should("have.attr", "value", "8"); - - cy.get("@endTooltipInput") - .should("have.attr", "value", "12"); - }); - - it("Input tooltips value change should change the range slider's value", () => { - cy.mount( - - ); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.get("@rangeSlider").realClick(); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-start-value]') - .shadow() - .find("ui5-input") - .as("startTooltipInput"); - - cy.get("@startTooltipInput") - .realClick() - .clear() - .realType("8"); - - cy.get("@startTooltipInput").realPress("Enter"); - - cy.get("@rangeSlider").invoke("attr", "start-value").should("eq", "8"); - }); - - it("Input tooltip value change should fire change event", () => { - cy.mount( - - ); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.get("@rangeSlider") - .invoke('on', 'ui5-change', cy.spy().as('changeEventSpy')); - - cy.get("@rangeSlider").realClick(); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-start-value]') - .shadow() - .find("ui5-input") - .as("startTooltipInput"); - - cy.get("@startTooltipInput") - .realClick() - .clear() - .realType("4"); - - cy.get("@startTooltipInput").realPress("Enter"); - - cy.get("@changeEventSpy").should('have.been.calledOnce'); - }); - - it("Input tooltips value state should change to 'Negative' if value is invalid", () => { - cy.mount( - - ); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.get("@rangeSlider").realClick(); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-start-value]') - .shadow() - .find("ui5-input") - .as("startTooltipInput"); - - cy.get("@startTooltipInput") - .realClick() - .clear() - .realType("23"); - - cy.get("@startTooltipInput").realPress("Enter"); - - cy.get("@startTooltipInput") - .should("have.attr", "value-state", "Negative"); - }); - - it("Input tooltip should become hidden when input loses focus", () => { - cy.mount( - <> - - - - ); - - cy.get("#range-slider-tickmarks-labels").as("rangeSlider"); - cy.get("#basic-range-slider").as("anotherSlider"); - - cy.get("@rangeSlider").realClick(); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-start-value]') - .as("startTooltip"); - - cy.get("@startTooltip").should("have.prop", "open", true); - - cy.get("@anotherSlider").realClick(); - - cy.get("@startTooltip").should("have.prop", "open", false); - }); - - it("F2 should switch the focus between the handle and the tooltip input", () => { - cy.mount( - - ); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("rangeSliderHandle"); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-start-value]') - .shadow() - .find("ui5-input") - .as("rangeSliderStartTooltipInput"); - - cy.get("@rangeSliderHandle").realClick(); - cy.realPress("F2"); - - cy.get("@rangeSliderStartTooltipInput").should("have.focus"); - - cy.realPress("F2"); - - cy.get("@rangeSliderHandle").should("have.focus"); - }); - - it("Arrow up/down should not increase/decrease the value of the input", () => { - cy.mount( - - ); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-start-value]') - .shadow() - .find("ui5-input") - .as("startTooltipInput"); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-end-value]') - .shadow() - .find("ui5-input") - .as("endTooltipInput"); - - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("startHandle"); - - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--end") - .as("endHandle"); - - cy.get("@startHandle").realClick(); - cy.get("@startTooltipInput").realClick(); - cy.realPress("ArrowUp"); - - cy.get("@rangeSlider").invoke("attr", "start-value").should("eq", "1"); - - cy.realPress("ArrowDown"); - - cy.get("@rangeSlider").invoke("attr", "start-value").should("eq", "1"); - - cy.get("@endHandle").realClick(); - cy.get("@endTooltipInput").realClick(); - cy.realPress("ArrowUp"); - - cy.get("@rangeSlider").invoke("attr", "end-value").should("eq", "10"); - - cy.realPress("ArrowDown"); - - cy.get("@rangeSlider").invoke("attr", "end-value").should("eq", "10"); - }); - - it("Tab on slider handle should not move the focus to the tooltip input", () => { - cy.mount( - <> - - - ); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Start value handle and input - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("startHandle"); - - // End value handle and input - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--end") - .as("endHandle"); - - cy.get("@startHandle").realClick(); - - cy.realPress("Tab"); - - cy.get("@endHandle").should("be.focused"); - }); - - it("Focus out with invalid value should reset it", () => { - cy.mount( - - ); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-start-value]') - .shadow() - .find("ui5-input") - .as("startTooltipInput"); - - cy.get("@rangeSlider").realClick(); - - cy.get("@startTooltipInput").realClick().realType("23"); - - cy.realPress("Tab"); - - cy.get("@startTooltipInput").should("have.attr", "value", "2"); - }); - - it("Input values should be swapped if the start value is bigger than the end value", () => { - cy.mount( - - ); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Start value handle and input - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("startHandle"); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-start-value]') - .shadow() - .find("ui5-input") - .as("startTooltipInput"); - - // End value handle and input - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--end") - .as("endHandle"); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-end-value]') - .shadow() - .find("ui5-input") - .as("endTooltipInput"); - - // Set start value to 20 - cy.get("@startHandle").realClick(); - cy.get("@startTooltipInput").realClick().clear().realType("20"); - cy.get("@startTooltipInput").realPress("Enter"); - - // Assert that start and end values are swapped - cy.get("@rangeSlider").invoke("attr", "end-value").should("eq", "20"); - cy.get("@endTooltipInput").should("have.attr", "value", "20"); - }); - - it("Input values should be swapped if the end value is lower than the start value", () => { - cy.mount( - - ); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Start value input - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-start-value]') - .shadow() - .find("ui5-input") - .as("startTooltipInput"); - - // End value input - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-end-value]') - .shadow() - .find("ui5-input") - .as("endTooltipInput"); - - // End value handle - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--end") - .as("endHandle"); - - // Set end value to 1 - cy.get("@endHandle").realClick(); - cy.get("@endTooltipInput").realClick().clear().realType("1"); - cy.get("@endTooltipInput").realPress("Enter"); - - // Assert that start and end values are swapped - cy.get("@rangeSlider").invoke("attr", "start-value").should("eq", "1"); - cy.get("@startTooltipInput").should("have.attr", "value", "1"); - }); - - it("Invalid tooltip value should not be changed on 'Enter'", () => { - cy.mount( - - ); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-end-value]') - .shadow() - .find("ui5-input") - .as("endTooltipInput"); - - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--end") - .as("endHandle"); - - cy.get("@endHandle").realClick(); - cy.get("@endTooltipInput").realClick().clear().realType("60"); - cy.get("@endTooltipInput").realPress("Enter"); - - cy.get("@rangeSlider").invoke("attr", "end-value").should("eq", "12"); - - cy.get("@endTooltipInput").should("have.attr", "value-state", "Negative"); - - cy.get("@endTooltipInput").should("have.attr", "value", "60"); - - cy.get("@endTooltipInput").realPress("Tab"); - - cy.get("@endTooltipInput").should("have.attr", "value", "12"); - - }); - - it("Range Slider tooltips should become hidden if the range slider loses focus", () => { - cy.mount( - <> - - - - ); - - cy.get("#basic-range-slider-with-tooltip").as("rangeSlider"); - cy.get("#basic-range-slider").as("anotherSlider"); - - cy.get("@rangeSlider").realClick(); - - cy.get("@rangeSlider") - .shadow() - .find('[data-sap-ui-start-value]') - .as("startTooltip"); - - cy.get("@startTooltip").should("have.prop", "open", true); - - cy.get("@anotherSlider").realClick(); - - cy.get("@startTooltip").should("have.prop", "open", false); - }); -}); - -describe("Properties synchronization and normalization", () => { - it("If a negative number is set to the step property its positive equivalent should be used as effective value", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--end") - .as("endHandle"); - - cy.get("@rangeSlider").should("have.attr", "step", "-7"); - - // Test keyboard navigation which should use the positive step value (7) - cy.get("@endHandle").realClick(); - cy.get("@endHandle").realPress("Home"); // Move to start (0) - cy.get("@endHandle").realPress("ArrowRight"); // Move by step (should be 7) - cy.get("@endHandle").realPress("ArrowRight"); // Move by step again (should be 14) - cy.get("@endHandle").realPress("ArrowRight"); // Move by step again (should be 21) - - // The current value should be 'stepified' by 7 (positive equivalent) - cy.get("@rangeSlider").should("have.attr", "end-value", "21"); - }); - - it("If min property is set to a greater number than the max property their effective values should be swapped, their real ones - not", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Properties themselves should not be normalized - cy.get("@rangeSlider").should("have.attr", "min", "100"); - cy.get("@rangeSlider").should("have.attr", "max", "10"); - - // startValue should be within the boundaries of the effective (swapped) min and max props - cy.get("@rangeSlider").should("have.attr", "start-value", "10"); - }); - - it("Should keep the current values between the boundaries of min and max properties", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Set endValue to 300 (above max) - cy.get("@rangeSlider").invoke("attr", "end-value", "300"); - cy.get("@rangeSlider").should("have.attr", "end-value", "200"); - - // Set startValue to 99 (below min) - cy.get("@rangeSlider").invoke("attr", "start-value", "99"); - cy.get("@rangeSlider").should("have.attr", "start-value", "100"); - }); - - it("Should not 'stepify' current value if it is not in result of user interaction", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Set values programmatically - cy.get("@rangeSlider").invoke("attr", "start-value", "14"); - cy.get("@rangeSlider").invoke("attr", "end-value", "24"); - - // Values should not be stepped to the next step - cy.get("@rangeSlider").should("have.attr", "start-value", "14"); - cy.get("@rangeSlider").should("have.attr", "end-value", "24"); - }); - - it("If the step property or the labelInterval are changed, the tickmarks and labels must be updated also", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Change step to 2 - cy.get("@rangeSlider").invoke("attr", "step", "2"); - - // Change labelInterval to 4 - cy.get("@rangeSlider").invoke("attr", "label-interval", "4"); - - // Labels should be updated accordingly - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-labels li") - .should("have.length.lessThan", 21); // Should have fewer labels now - }); -}); - -describe("Testing events", () => { - it("Should fire input event on user interaction and change event after user interaction finish", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.get("@rangeSlider") - .invoke('on', 'ui5-input', cy.spy().as('inputEventSpy')) - .invoke('on', 'ui5-change', cy.spy().as('changeEventSpy')); - - // Start value handle and input - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("startHandle"); - - cy.get("@startHandle") - .realMouseDown() - .realMouseMove(100, 0) - .realMouseUp(); - - // Click on the slider to trigger both events - cy.get("@rangeSlider").realClick(); - - // Both input event and change event should be fired after user interaction - cy.get("@inputEventSpy").should('have.been.called'); - cy.get("@changeEventSpy").should('have.been.called'); - }); - - it("Should not fire change event if the values are the same after interaction", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("firstHandle"); - - cy.get("@rangeSlider") - .invoke('on', 'ui5-change', cy.spy().as('changeEventSpy')); - - cy.get("@firstHandle").realClick(); - cy.get("@firstHandle").realPress("Home"); - - cy.get("@changeEventSpy").should('not.have.been.called'); - }); - - it("Should fire input event with correctly swapped values", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-progress") - .as("rangeSliderProgressBar"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("firstHandle"); - - cy.get("@rangeSlider") - .invoke('on', 'ui5-input', cy.spy().as('inputEventSpy')); - - // Use keyboard navigation to move start handle past end handle - cy.get("@firstHandle").realClick(); - cy.get("@firstHandle").realPress("ArrowRight"); - cy.get("@firstHandle").realPress("ArrowRight"); - cy.get("@firstHandle").realPress("ArrowRight"); - - cy.get("@rangeSliderProgressBar").should("have.attr", "aria-valuenow", "2"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "2"); - cy.get("@rangeSlider").should("have.attr", "end-value", "4"); - cy.get("@inputEventSpy").should('have.been.called'); - }); - - it("Should not fire change event after user interaction is finished if the current value is the same as the one at the start of the action", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.get("@rangeSlider") - .invoke('on', 'ui5-change', cy.spy().as('changeEventSpy')); - - // Click on the same position (should not change value) - cy.get("@rangeSlider").realClick(); - - cy.get("@changeEventSpy").should('not.have.been.called'); - }); - - it("Should fire change event after swapping the values", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("startHandle"); - - cy.get("@rangeSlider") - .invoke('on', 'ui5-change', cy.spy().as('changeEventSpy')); - - // Drag start handle past end handle to swap values - cy.get("@startHandle") - .realMouseDown() - .realMouseMove(100, 0) - .realMouseUp(); - - cy.get("@rangeSlider").should("have.attr", "start-value", "2"); - cy.get("@rangeSlider").invoke("attr", "end-value").then((endValue: string) => { - expect(parseInt(endValue)).to.be.greaterThan(2); - }); - cy.get("@changeEventSpy").should('have.been.called'); - }); - - it("Aria attributes of the start handle are set correctly", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("startHandle"); - - cy.get("@rangeSlider").then(($el) => { - const rangeSlider = $el[0] as RangeSlider; - const minValue = rangeSlider.min; - const maxValue = rangeSlider.max; - const startValue = rangeSlider.startValue; - - cy.get("@startHandle") - .should("have.attr", "aria-labelledby", "ui5-slider-startHandleDesc"); - - cy.get("@startHandle") - .should("have.attr", "aria-valuemin", `${minValue}`); - - cy.get("@startHandle") - .should("have.attr", "aria-valuemax", `${maxValue}`); - - cy.get("@startHandle") - .should("have.attr", "aria-valuenow", `${startValue}`); - }); - }); - - it("Aria attributes of the end handle are set correctly", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--end") - .as("endHandle"); - - cy.get("@rangeSlider").then(($el) => { - const rangeSlider = $el[0] as RangeSlider; - const minValue = rangeSlider.min; - const maxValue = rangeSlider.max; - const endValue = rangeSlider.endValue; - - cy.get("@endHandle") - .should("have.attr", "aria-labelledby", "ui5-slider-endHandleDesc"); - - cy.get("@endHandle") - .should("have.attr", "aria-valuemin", `${minValue}`); - - cy.get("@endHandle") - .should("have.attr", "aria-valuemax", `${maxValue}`); - - cy.get("@endHandle") - .should("have.attr", "aria-valuenow", `${endValue}`); - }); - }); - - it("Aria-labelledby text is mapped correctly when values are swapped", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("startHandle"); - cy.get("@rangeSlider") - .shadow() - .find("#ui5-slider-startHandleDesc") - .as("rangeSliderStartHandleSpan"); - cy.get("@rangeSlider") - .shadow() - .find("#ui5-slider-endHandleDesc") - .as("rangeSliderEndHandleSpan"); - - // Drag start handle past end handle to swap values using real events - cy.get("@startHandle") - .realMouseDown() - .realMouseMove(100, 0) - .realMouseUp(); - - cy.get("@rangeSliderStartHandleSpan").should("contain.text", "Left handle"); - cy.get("@rangeSliderEndHandleSpan").should("contain.text", "Right handle"); - }); - - it("Click anywhere in the Range Slider should focus the closest handle", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Test that clicking on the slider focuses some element (either handle or progress bar) - cy.get("@rangeSlider").realClick(); - - // Verify that the slider component itself is focused - cy.get("@rangeSlider").should("have.focus"); - - // Test that handles can be focused when clicked directly - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .realClick() - .should("have.focus"); - - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--end") - .realClick() - .should("have.focus"); - }); - - it("Click currently selected range should focus it", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-progress") - .as("rangeSliderSelection"); - - cy.get("@rangeSlider").realClick(); - - // Should focus the progress bar - cy.get("@rangeSliderSelection").should("have.focus"); - }); - - it("When not yet focused, 'Tab' should focus the Range Slider and move the focus to the progress bar", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-progress") - .as("rangeSliderSelection"); - - cy.realPress("Tab"); - - cy.get("@rangeSlider").should("have.focus"); - cy.get("@rangeSliderSelection").should("have.focus"); - }); - - it("When progress bar has the focus, 'Tab' should move the focus to the first handle", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("rangeSliderStartHandle"); - - // Focus the progress bar first - cy.realPress("Tab"); - cy.realPress("Tab"); - - cy.get("@rangeSliderStartHandle").should("have.focus"); - }); - - it("When the first handle has the focus, 'Tab' should focus the second handle", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--end") - .as("rangeSliderEndHandle"); - - // Focus the first handle first - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("Tab"); - - cy.get("@rangeSliderEndHandle").should("have.focus"); - }); - - it("When the second handle has the focus, 'Tab' should move the focus away from the Range Slider", () => { - cy.mount( - <> - - - - ); - - cy.get("#basic-range-slider").as("currentRangeSlider"); - cy.get("#basic-range-slider-with-tooltip").as("nextRangeSlider"); - cy.get("@nextRangeSlider") - .shadow() - .find(".ui5-slider-progress") - .as("rangeSliderSelection"); - - // Focus through the first slider - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("Tab"); - - cy.get("@currentRangeSlider").should("not.have.focus"); - cy.get("@nextRangeSlider").should("have.focus"); - cy.get("@rangeSliderSelection").should("have.focus"); - }); - - it("Shift+Tab should focus the previous Range Slider and move the focus to its second handle", () => { - cy.mount( - <> - - - - ); - - cy.get("#basic-range-slider-with-tooltip").as("currentRangeSlider"); - cy.get("#basic-range-slider").as("previousRangeSlider"); - cy.get("@previousRangeSlider") - .shadow() - .find(".ui5-slider-handle--end") - .as("previousRangeSliderEndHandle"); - - // Focus the second slider first - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("Tab"); - - cy.realPress(["Shift", "Tab"]); - - cy.get("@currentRangeSlider").should("not.have.focus"); - cy.get("@previousRangeSlider").should("have.focus"); - cy.get("@previousRangeSliderEndHandle").should("have.focus"); - }); - - it("When the second handle has the focus, 'Shift' + 'Tab' should move the focus to the first handle", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("rangeSliderStartHandle"); - - // Focus the second handle first - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("Tab"); - - cy.realPress(["Shift", "Tab"]); - - cy.get("@rangeSliderStartHandle").should("have.focus"); - }); - - it("When the first handle has the focus, 'Shift' + 'Tab' should move the focus to the progress bar", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-progress") - .as("rangeSliderSelection"); - - // Focus the first handle first - cy.realPress("Tab"); - cy.realPress("Tab"); - - cy.realPress(["Shift", "Tab"]); - - cy.get("@rangeSliderSelection").should("have.focus"); - }); - - it("When the progress bar has the focus, 'Shift' + 'Tab' should move the focus away from the Range Slider", () => { - cy.mount( - <> - - - - ); - - cy.get("#basic-range-slider").as("rangeSlider"); - cy.get("#previous-range-slider").as("previousRangeSlider"); - - // Focus the current slider's progress bar first - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("Tab"); - - cy.realPress(["Shift", "Tab"]); - - cy.get("@rangeSlider").should("not.have.focus"); - cy.get("@previousRangeSlider").should("have.focus"); - }); - - it("When one handle comes across the other and the values are swapped the focus must be switched between the handles", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--start") - .as("startHandle"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle--end") - .as("endHandle"); - - // Focus the start handle and move it past the end handle using keyboard - cy.get("@startHandle").realClick(); - - // Move start handle to the right multiple times to pass the end handle - for (let i = 0; i < 15; i++) { - cy.get("@startHandle").realPress("ArrowRight"); - } - - // After swapping, the original start handle should now be the end handle - // and should have focus - cy.get("@endHandle").should("have.focus"); - - // Verify values were swapped - cy.get("@rangeSlider").should("have.attr", "start-value", "20"); - cy.get("@rangeSlider").should("have.attr", "end-value", "25"); - }); -}); - -describe("Accessibility: Testing keyboard handling", () => { - it("When progress bar is focused 'Right Arrow' key should increase both values of the Range Slider with a small increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-progress") - .as("progressBar"); - - // Click on the progress bar to focus it - cy.get("@progressBar").realClick(); - cy.get("@progressBar").should("have.focus"); - - // Press arrow right - cy.get("@progressBar").realPress("ArrowRight"); - - // Verify that both values increased by 1 - cy.get("@rangeSlider").should("have.attr", "start-value", "11"); - cy.get("@rangeSlider").should("have.attr", "end-value", "31"); - }); - - it("When progress bar is focused 'Left Arrow' key should decrease both values of the Range Slider with a small increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress("ArrowLeft"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "9"); - cy.get("@rangeSlider").should("have.attr", "end-value", "29"); - }); - - it("When progress bar is focused 'Up Arrow' key should increase both values of the Range Slider with a small increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress("ArrowUp"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "11"); - cy.get("@rangeSlider").should("have.attr", "end-value", "31"); - }); - - it("When progress bar is focused 'Down' key should decrease both values of the Range Slider with a small increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress("ArrowDown"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "9"); - cy.get("@rangeSlider").should("have.attr", "end-value", "29"); - }); - - it("When progress bar is focused 'Control' + 'Right Arrow' key should increase both values of the Range Slider with a big increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress(["Control", "ArrowRight"]); - - cy.get("@rangeSlider").should("have.attr", "start-value", "20"); - cy.get("@rangeSlider").should("have.attr", "end-value", "40"); - }); - - it("When progress bar is focused 'Control' + 'Left Arrow' key should decrease both values of the Range Slider with a big increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress(["Control", "ArrowLeft"]); - - cy.get("@rangeSlider").should("have.attr", "start-value", "10"); - cy.get("@rangeSlider").should("have.attr", "end-value", "30"); - }); - - it("When progress bar is focused 'Control' + 'Up Arrow' key should increase both values of the Range Slider with a big increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress(["Control", "ArrowUp"]); - - cy.get("@rangeSlider").should("have.attr", "start-value", "20"); - cy.get("@rangeSlider").should("have.attr", "end-value", "40"); - }); - - it("When progress bar is focused 'Control' + 'Down' key should decrease both values of the Range Slider with a big increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress(["Control", "ArrowDown"]); - - cy.get("@rangeSlider").should("have.attr", "start-value", "10"); - cy.get("@rangeSlider").should("have.attr", "end-value", "30"); - }); - - it("When progress bar is focused 'Page Up' key should increase both values of the Range Slider with a big increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress("PageUp"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "20"); - cy.get("@rangeSlider").should("have.attr", "end-value", "40"); - }); - - it("When progress bar is focused 'Page Down' key should decrease both values of the Range Slider with a big increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress("PageDown"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "10"); - cy.get("@rangeSlider").should("have.attr", "end-value", "30"); - }); - - it("When progress bar is focused the '+' key should increase both values of the Range Slider with a small increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress("+"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "11"); - cy.get("@rangeSlider").should("have.attr", "end-value", "31"); - - // Test numpad add - cy.realPress("NumpadAdd"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "12"); - cy.get("@rangeSlider").should("have.attr", "end-value", "32"); - }); - - it("When progress bar is focused the '-' key should decrease both values of the Range Slider with a small increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress("-"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "11"); - cy.get("@rangeSlider").should("have.attr", "end-value", "31"); - - // Test numpad subtract - cy.realPress("NumpadSubtract"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "10"); - cy.get("@rangeSlider").should("have.attr", "end-value", "30"); - }); - - it("When progress bar is focused an 'End' key press should offset the selected range to the end of the Range Slider", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress("End"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "80"); - cy.get("@rangeSlider").should("have.attr", "end-value", "100"); - }); - - it("When progress bar is focused a 'Home' key press should offset the selected range to the start of the Range Slider", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress("Home"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "0"); - cy.get("@rangeSlider").should("have.attr", "end-value", "20"); - }); - - it("A 'Esc' key press should return the values of the Range Slider at their initial point at the time of its focusing", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - cy.realPress("Tab"); - cy.realPress("Escape"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "24"); - cy.get("@rangeSlider").should("have.attr", "end-value", "42"); - }); - - it("When a handle is focused 'Right Arrow' key should increase its value with a small increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus start handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("ArrowRight"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "11"); - - // Focus end handle - cy.realPress("Tab"); - cy.realPress("ArrowRight"); - - cy.get("@rangeSlider").should("have.attr", "end-value", "31"); - }); - - it("When a handle is focused 'Left Arrow' key should decrease its value with a small increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus end handle first - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("ArrowLeft"); - - cy.get("@rangeSlider").should("have.attr", "end-value", "29"); - - // Focus start handle - cy.realPress(["Shift", "Tab"]); - cy.realPress("ArrowLeft"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "9"); - }); - - it("When a handle is focused 'Up Arrow' key should increase its value with a small increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus start handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("ArrowUp"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "11"); - - // Focus end handle - cy.realPress("Tab"); - cy.realPress("ArrowUp"); - - cy.get("@rangeSlider").should("have.attr", "end-value", "31"); - }); - - it("When a handle is focused 'Down' key should decrease its value with a small increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus start handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("ArrowDown"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "9"); - - // Focus end handle - cy.realPress("Tab"); - cy.realPress("ArrowDown"); - - cy.get("@rangeSlider").should("have.attr", "end-value", "29"); - }); - - it("When a handle is focused 'Control' + 'Right Arrow' key should increase its value with a big increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus start handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress(["Control", "ArrowRight"]); - - cy.get("@rangeSlider").should("have.attr", "start-value", "20"); - - // Focus end handle - cy.realPress("Tab"); - cy.realPress(["Control", "ArrowRight"]); - - cy.get("@rangeSlider").should("have.attr", "end-value", "40"); - }); - - it("When a handle is focused 'Control' + 'Left Arrow' key should decrease its value with a big increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus start handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress(["Control", "ArrowLeft"]); - - cy.get("@rangeSlider").should("have.attr", "start-value", "10"); - - // Focus end handle - cy.realPress("Tab"); - cy.realPress(["Control", "ArrowLeft"]); - - cy.get("@rangeSlider").should("have.attr", "end-value", "30"); - }); - - it("When a handle is focused 'Control' + 'Up Arrow' key should increase its value with a big increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus start handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress(["Control", "ArrowUp"]); - - cy.get("@rangeSlider").should("have.attr", "start-value", "20"); - - // Focus end handle - cy.realPress("Tab"); - cy.realPress(["Control", "ArrowUp"]); - - cy.get("@rangeSlider").should("have.attr", "end-value", "40"); - }); - - it("When handle is focused 'Control' + 'Down' key should decrease its value with a big increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus start handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress(["Control", "ArrowDown"]); - - cy.get("@rangeSlider").should("have.attr", "start-value", "10"); - - // Focus end handle - cy.realPress("Tab"); - cy.realPress(["Control", "ArrowDown"]); - - cy.get("@rangeSlider").should("have.attr", "end-value", "30"); - }); - - it("When a handle is focused 'Page Down' key should decrease its value with a big increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus start handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("PageDown"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "10"); - - // Focus end handle - cy.realPress("Tab"); - cy.realPress("PageDown"); - - cy.get("@rangeSlider").should("have.attr", "end-value", "30"); - }); - - it("When a handle focused the '+' key should increase its value with a small increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus start handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("+"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "11"); - - // Test numpad add on start handle - cy.realPress("NumpadAdd"); - cy.get("@rangeSlider").should("have.attr", "start-value", "12"); - - // Focus end handle - cy.realPress("Tab"); - cy.realPress("+"); - - cy.get("@rangeSlider").should("have.attr", "end-value", "31"); - - // Test numpad add on end handle - cy.realPress("NumpadAdd"); - cy.get("@rangeSlider").should("have.attr", "end-value", "32"); - }); - - it("When a handle focused the '-' key should decrease its value with a small increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus start handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("-"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "11"); - - // Test numpad subtract on start handle - cy.realPress("NumpadSubtract"); - cy.get("@rangeSlider").should("have.attr", "start-value", "10"); - - // Focus end handle - cy.realPress("Tab"); - cy.realPress("-"); - - cy.get("@rangeSlider").should("have.attr", "end-value", "31"); - - // Test numpad subtract on end handle - cy.realPress("NumpadSubtract"); - cy.get("@rangeSlider").should("have.attr", "end-value", "30"); - }); - - it("When a handle is focused 'Page Up' key should increase its value with a big increment step", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus start handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("PageUp"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "20"); - - // Focus end handle - cy.realPress("Tab"); - cy.realPress("PageUp"); - - cy.get("@rangeSlider").should("have.attr", "end-value", "40"); - }); - - it("When a handle is focused an 'End' key press should set its value to the maximum allowed", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus end handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("End"); - - cy.get("@rangeSlider").should("have.attr", "end-value", "100"); - }); - - it("When a handle is focused a 'Home' key press should set its value to the start of the Range Slider", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Focus start handle - cy.realPress("Tab"); - cy.realPress("Tab"); - cy.realPress("Home"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "0"); - }); -}); - -describe("Testing resize handling and RTL support", () => { - it("Testing RTL support", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle-container") - .first() - .as("startHandle"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-inner .ui5-slider-handle-container") - .eq(1) - .as("endHandle"); - - // Initially start-handle should be 0% from the right side - cy.get("@startHandle").should("have.attr", "style").and("include", "right: 0%"); - // End-handle should be 40% from the right side - cy.get("@endHandle").should("have.attr", "style").and("include", "right: 40%"); - - // Set startValue to 3 - cy.get("@rangeSlider").invoke("attr", "start-value", "3"); - cy.get("@startHandle").should("have.attr", "style").and("include", "right: 30%"); - - // Click on slider - cy.get("@rangeSlider").realClick(); - cy.get("@rangeSlider").should("have.attr", "end-value", "5"); - cy.get("@endHandle").should("have.attr", "style").and("include", "right: 50%"); - }); - - it("Testing RTL KBH support", () => { - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-handle-container") - .first() - .as("startHandle"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-inner .ui5-slider-handle-container") - .eq(1) - .as("endHandle"); - cy.get("@rangeSlider") - .shadow() - .find(".ui5-slider-progress") - .as("rangeSliderSelection"); - - // Initially start-handle should be 30% from the right side - cy.get("@startHandle").should("have.attr", "style").and("include", "right: 30%"); - // End-handle should be 70% from the right side - cy.get("@endHandle").should("have.attr", "style").and("include", "right: 70%"); - - // Test selection range keyboard navigation - cy.get("@rangeSliderSelection").realClick(); - cy.get("@rangeSliderSelection").realPress("ArrowLeft"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "4"); - cy.get("@rangeSlider").should("have.attr", "end-value", "8"); - - cy.get("@rangeSliderSelection").realPress("ArrowRight"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "3"); - cy.get("@rangeSlider").should("have.attr", "end-value", "7"); - - // Test start handle - cy.get("@startHandle").realClick(); - cy.get("@startHandle").realPress("ArrowLeft"); - cy.get("@startHandle").realPress("ArrowLeft"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "5"); - - cy.get("@startHandle").realPress("ArrowRight"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "4"); - - cy.get("@startHandle").realPress("Home"); - - cy.get("@rangeSlider").should("have.attr", "start-value", "0"); - - // Test end handle - cy.get("@endHandle").realClick(); - cy.get("@endHandle").realPress("ArrowLeft"); - cy.get("@endHandle").realPress("ArrowLeft"); - - cy.get("@rangeSlider").should("have.attr", "end-value", "9"); - - cy.get("@endHandle").realPress("ArrowRight"); - - cy.get("@rangeSlider").should("have.attr", "end-value", "8"); - - cy.get("@endHandle").realPress("End"); - - cy.get("@rangeSlider").should("have.attr", "end-value", "10"); - }); - - it("Should hide all labels except the first and the last one, if there is not enough space for all of them", () => { - // Set small viewport first - cy.viewport(400, 600); - - cy.mount(); - - cy.get("[ui5-range-slider]").as("rangeSlider"); - - // Wait for the component to render and calculate overlapping - cy.get("@rangeSlider").should(($el) => { - const rangeSlider = $el[0] as RangeSlider; - expect(rangeSlider._labelsOverlapping || rangeSlider._hiddenTickmarks).to.be.true; - }); - - // Trigger a resize event to force recalculation - cy.window().trigger('resize'); - - // Wait for the resize handling to complete - cy.get("@rangeSlider").should(($el) => { - const rangeSlider = $el[0] as RangeSlider; - expect(rangeSlider._labelsOverlapping || rangeSlider._hiddenTickmarks).to.be.true; - }); - }); -}); - -describe("Accessibility", () => { - it("should apply associated label text as aria-label on the slider element", () => { - const labelText = "basic range slider"; - cy.mount( - <> - - - - ); - - cy.get("[ui5-range-slider]") - .shadow() - .find(".ui5-slider-progress") - .should("have.attr", "aria-label", `${labelText} Range`); - }); - - it("Aria attributes of the progress bar are set correctly", () => { - cy.mount( - - ); - - cy.get("[ui5-range-slider]") - .shadow() - .find(".ui5-slider-progress") - .as("sliderProgress"); - - cy.get("[ui5-range-slider]").then(($el) => { - const rangeSlider = $el[0] as RangeSlider; - const minValue = rangeSlider.min; - const maxValue = rangeSlider.max; - const startValue = rangeSlider.startValue; - const endValue = rangeSlider.endValue; - - cy.get("@sliderProgress") - .should("have.attr", "aria-label", "Range"); - - cy.get("@sliderProgress") - .should("have.attr", "aria-valuemin", `${minValue}`); - - cy.get("@sliderProgress") - .should("have.attr", "aria-valuemax", `${maxValue}`); - - cy.get("@sliderProgress") - .should("have.attr", "aria-valuetext", `From ${startValue} to ${endValue}`); - - cy.get("@sliderProgress") - .should("have.attr", "aria-valuenow", `${endValue}`); - - }); - }); -}); +import RangeSlider from "../../src/RangeSlider.js"; + +describe("Testing Range Slider interactions", () => { + it("Changing the current startValue is reflected", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("startHandle"); + + // Initially if no value is set, the Range Slider start-handle is at the beginning + cy.get("@startHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 0%, 100%);"); + + // Set startValue to 5 + cy.get("@rangeSlider").invoke("attr", "start-value", "5"); + cy.get("@startHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 12.5%, 100%);"); + + // Test programmatic value change and verify handle position updates + cy.get("@rangeSlider").invoke("attr", "start-value", "8"); + cy.get("@startHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 20%, 100%);"); + + // Test clicking on the slider to change value + cy.get("@rangeSlider").realClick({ x: 100 }); + + // The value should change after clicking + cy.get("@rangeSlider").should("have.attr", "start-value").and("not.eq", "5"); + }); + + it("Changing the endValue is reflected", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("endHandle"); + + // Check initial endValue (default should be 100, but with max=40, it should be 40) + cy.get("@rangeSlider").should("have.attr", "end-value", "40"); + cy.get("@endHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 100%, 100%);"); + + // Set endValue to 10 + cy.get("@rangeSlider").invoke("attr", "end-value", "10"); + cy.get("@endHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 25%, 100%);"); + + // Set endValue to 20 (middle) + cy.get("@rangeSlider").invoke("attr", "end-value", "20"); + cy.get("@endHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 50%, 100%);"); + + // Set endValue to 30 to verify another position + cy.get("@rangeSlider").invoke("attr", "end-value", "30"); + cy.get("@endHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 75%, 100%);"); + }); + + it("Click within the selected range should not change any value", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-progress") + .as("selectedRange"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "5"); + cy.get("@rangeSlider").should("have.attr", "end-value", "30"); + + // Click within the selected range (on the progress bar) + cy.get("@selectedRange").realClick(); + + cy.get("@rangeSlider").should("have.attr", "start-value", "5"); + cy.get("@rangeSlider").should("have.attr", "end-value", "30"); + }); + + it("Dragging the selected range should change both values and handles", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-progress") + .as("selectedRange"); + + // Get initial values + cy.get("@rangeSlider").should("have.attr", "start-value", "5"); + cy.get("@rangeSlider").should("have.attr", "end-value", "30"); + + // Drag the selected range to the right + cy.get("@selectedRange") + .realMouseDown() + .realMouseMove(50, 0) + .realMouseUp(); + + // Both values should change after dragging the range + cy.get("@rangeSlider").should("have.attr", "start-value").and("not.eq", "5"); + cy.get("@rangeSlider").should("have.attr", "end-value").and("not.eq", "30"); + + // The range size should remain the same (25 units) + cy.get("@rangeSlider").then(($slider) => { + const startValue = parseInt($slider.attr("start-value")); + const endValue = parseInt($slider.attr("end-value")); + expect(endValue - startValue).to.equal(25); + }); + }); + + it("Dragging the start-handle past the end-handle should swap the values", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("startHandle"); + + // Get initial values + cy.get("@rangeSlider").should("have.attr", "start-value", "8"); + cy.get("@rangeSlider").should("have.attr", "end-value", "9"); + + // Drag the start handle past the end handle + cy.get("@startHandle") + .realMouseDown() + .realMouseMove(100, 0) + .realMouseUp(); + + // Values should be swapped after dragging + cy.get("@rangeSlider").then(($el) => { + const rangeSlider = $el[0] as RangeSlider; + expect(rangeSlider.startValue).to.equal(9); + expect(rangeSlider.endValue).to.be.greaterThan(9); + }); + }); + + it("Dragging the whole range selection should always keep the initially selected range and be within min/max values", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-progress") + .as("selectedRange"); + + // Drag the selected range to the left (towards minimum) + cy.get("@selectedRange") + .realMouseDown() + .realMouseMove(-100, 0) + .realMouseUp(); + + // startValue should be 0 as the selected range has reached the start of the Range Slider + cy.get("@rangeSlider").should("have.attr", "start-value", "0"); + // endValue should be 21 and no less, the initially selected range should be preserved + cy.get("@rangeSlider").should("have.attr", "end-value", "21"); + + // Drag the selected range to the right (towards maximum) + cy.get("@selectedRange") + .realMouseDown() + .realMouseMove(600, 0) + .realMouseUp(); + + // startValue should be 7 and no more, the initially selected range should be preserved + cy.get("@rangeSlider").should("have.attr", "start-value", "7"); + // endValue should be 28 as the selected range has reached the end of the Range Slider + cy.get("@rangeSlider").should("have.attr", "end-value", "28"); + }); + + it("Range Slider should not be interactive if the step property is 0", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.get("@rangeSlider").realClick(); + + // endValue should remain the same + cy.get("@rangeSlider").should("have.attr", "end-value", "100"); + }); + + it("Disabled Range Slider is not interactive", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Range Slider should be disabled + cy.get("@rangeSlider").should("have.attr", "disabled"); + }); +}); + +describe("Range Slider elements - tooltip, step, tickmarks, labels", () => { + it("Range Slider have correct number of labels and tickmarks based on the defined step and labelInterval properties", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-scale-tickmark-label") + .as("labels"); + + // With min=0, max=44, step=1, labelInterval=2: + // Total steps = (44-0)/1 = 44 steps + // Labels should appear every 2 steps: 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44 + // That's 23 labels total + cy.get("@labels").should("have.length", 23); + + // Check tickmarks - should have one for each step plus start and end + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-scale-tickmark") + .should("have.length", 45); // 0 to 44 inclusive = 45 tickmarks + }); + it("Range Slider tooltips are displayed showing the current value", () => { + cy.get('[data-cy-root]') + .invoke('css', 'padding', '100px') + + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.get("@rangeSlider").realClick(); + + cy.get('@rangeSlider') + .shadow() + .find('[data-sap-ui-start-value]') + .as('startTooltip'); + + cy.get('@rangeSlider') + .shadow() + .find('[data-sap-ui-end-value]') + .as('endTooltip'); + + + cy.get("@rangeSlider").invoke("attr", "start-value", 65); + cy.get("@startTooltip").shadow().find(".ui5-slider-tooltip-value").should("have.text", "65"); + + cy.get("@rangeSlider").invoke("attr", "end-value", 115); + cy.get("@endTooltip").shadow().find(".ui5-slider-tooltip-value").should("have.text", "115"); + }); + + it("Tooltip input is displayed showing the current value", () => { + cy.mount( + + ); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.get("@rangeSlider").realClick(); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-start-value]') + .shadow() + .find("ui5-input") + .as("startTooltipInput"); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-end-value]') + .shadow() + .find("ui5-input") + .as("endTooltipInput"); + + cy.get("@startTooltipInput") + .should("have.attr", "value", "8"); + + cy.get("@endTooltipInput") + .should("have.attr", "value", "12"); + }); + + it("Input tooltips value change should change the range slider's value", () => { + cy.mount( + + ); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.get("@rangeSlider").realClick(); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-start-value]') + .shadow() + .find("ui5-input") + .as("startTooltipInput"); + + cy.get("@startTooltipInput") + .realClick() + .clear() + .realType("8"); + + cy.get("@startTooltipInput").realPress("Enter"); + + cy.get("@rangeSlider").invoke("attr", "start-value").should("eq", "8"); + }); + + it("Input tooltip value change should fire change event", () => { + cy.mount( + + ); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.get("@rangeSlider") + .invoke('on', 'ui5-change', cy.spy().as('changeEventSpy')); + + cy.get("@rangeSlider").realClick(); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-start-value]') + .shadow() + .find("ui5-input") + .as("startTooltipInput"); + + cy.get("@startTooltipInput") + .realClick() + .clear() + .realType("4"); + + cy.get("@startTooltipInput").realPress("Enter"); + + cy.get("@changeEventSpy").should('have.been.called'); + }); + + it("Input tooltips value state should change to 'Negative' if value is invalid", () => { + cy.mount( + + ); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.get("@rangeSlider").realClick(); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-start-value]') + .shadow() + .find("ui5-input") + .as("startTooltipInput"); + + cy.get("@startTooltipInput") + .realClick() + .clear() + .realType("23"); + + cy.get("@startTooltipInput").realPress("Enter"); + + cy.get("@startTooltipInput") + .should("have.attr", "value-state", "Negative"); + }); + + it("Input tooltip should become hidden when input loses focus", () => { + cy.mount( + <> + + + + ); + + cy.get("#range-slider-tickmarks-labels").as("rangeSlider"); + cy.get("#basic-range-slider").as("anotherSlider"); + + cy.get("@rangeSlider").realClick(); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-start-value]') + .as("startTooltip"); + + cy.get("@startTooltip").should("have.prop", "open", true); + + cy.get("@anotherSlider").realClick(); + + cy.get("@startTooltip").should("have.prop", "open", false); + }); + + it("F2 should switch the focus between the handle and the tooltip input", () => { + cy.mount( + + ); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("rangeSliderHandle"); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-start-value]') + .shadow() + .find("ui5-input") + .as("rangeSliderStartTooltipInput"); + + cy.get("@rangeSliderHandle").realClick(); + cy.realPress("F2"); + + cy.get("@rangeSliderStartTooltipInput").should("have.focus"); + + cy.realPress("F2"); + + cy.get("@rangeSliderHandle").should("have.focus"); + }); + + it("Arrow up/down should not increase/decrease the value of the input", () => { + cy.mount( + + ); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-start-value]') + .shadow() + .find("ui5-input") + .as("startTooltipInput"); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-end-value]') + .shadow() + .find("ui5-input") + .as("endTooltipInput"); + + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("startHandle"); + + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("endHandle"); + + cy.get("@startHandle").realClick(); + cy.get("@startTooltipInput").realClick(); + cy.realPress("ArrowUp"); + + cy.get("@rangeSlider").invoke("attr", "start-value").should("eq", "1"); + + cy.realPress("ArrowDown"); + + cy.get("@rangeSlider").invoke("attr", "start-value").should("eq", "1"); + + cy.get("@endHandle").realClick(); + cy.get("@endTooltipInput").realClick(); + cy.realPress("ArrowUp"); + + cy.get("@rangeSlider").invoke("attr", "end-value").should("eq", "10"); + + cy.realPress("ArrowDown"); + + cy.get("@rangeSlider").invoke("attr", "end-value").should("eq", "10"); + }); + + it("Tab on slider handle should not move the focus to the tooltip input", () => { + cy.mount( + <> + + + ); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Start value handle and input + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("startHandle"); + + // End value handle and input + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("endHandle"); + + cy.get("@startHandle").realClick(); + + cy.realPress("Tab"); + + cy.get("@endHandle").should("be.focused"); + }); + + it("Focus out with invalid value should reset it", () => { + cy.mount( + + ); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-start-value]') + .shadow() + .find("ui5-input") + .as("startTooltipInput"); + + cy.get("@rangeSlider").realClick(); + + cy.get("@startTooltipInput").realClick().realType("23"); + + cy.realPress("Tab"); + + cy.get("@startTooltipInput").should("have.attr", "value", "2"); + }); + + it("Input values should be swapped if the start value is bigger than the end value", () => { + cy.mount( + + ); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Start value handle and input + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("startHandle"); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-start-value]') + .shadow() + .find("ui5-input") + .as("startTooltipInput"); + + // End value handle and input + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("endHandle"); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-end-value]') + .shadow() + .find("ui5-input") + .as("endTooltipInput"); + + // Set start value to 20 + cy.get("@startHandle").realClick(); + cy.get("@startTooltipInput").realClick().clear().realType("20"); + cy.get("@startTooltipInput").realPress("Enter"); + + // Assert that start and end values are swapped + cy.get("@rangeSlider").invoke("attr", "end-value").should("eq", "20"); + cy.get("@endTooltipInput").should("have.attr", "value", "20"); + }); + + it("Input values should be swapped if the end value is lower than the start value", () => { + cy.mount( + + ); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Start value input + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-start-value]') + .shadow() + .find("ui5-input") + .as("startTooltipInput"); + + // End value input + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-end-value]') + .shadow() + .find("ui5-input") + .as("endTooltipInput"); + + // End value handle + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("endHandle"); + + // Set end value to 1 + cy.get("@endHandle").realClick(); + cy.get("@endTooltipInput").realClick().clear().realType("1"); + cy.get("@endTooltipInput").realPress("Enter"); + + // Assert that start and end values are swapped + cy.get("@rangeSlider").invoke("attr", "start-value").should("eq", "1"); + cy.get("@startTooltipInput").should("have.attr", "value", "1"); + }); + + it("Invalid tooltip value should not be changed on 'Enter'", () => { + cy.mount( + + ); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-end-value]') + .shadow() + .find("ui5-input") + .as("endTooltipInput"); + + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("endHandle"); + + cy.get("@endHandle").realClick(); + cy.get("@endTooltipInput").realClick().clear().realType("60"); + cy.get("@endTooltipInput").realPress("Enter"); + + cy.get("@rangeSlider").invoke("attr", "end-value").should("eq", "12"); + + cy.get("@endTooltipInput").should("have.attr", "value-state", "Negative"); + + cy.get("@endTooltipInput").should("have.attr", "value", "60"); + + cy.get("@endTooltipInput").realPress("Tab"); + + cy.get("@endTooltipInput").should("have.attr", "value", "12"); + + }); + + it("Range Slider tooltips should become hidden if the range slider loses focus", () => { + cy.mount( + <> + + + + ); + + cy.get("#basic-range-slider-with-tooltip").as("rangeSlider"); + cy.get("#basic-range-slider").as("anotherSlider"); + + cy.get("@rangeSlider").realClick(); + + cy.get("@rangeSlider") + .shadow() + .find('[data-sap-ui-start-value]') + .as("startTooltip"); + + cy.get("@startTooltip").should("have.prop", "open", true); + + cy.get("@anotherSlider").realClick(); + + cy.get("@startTooltip").should("have.prop", "open", false); + }); +}); + +describe("Properties synchronization and normalization", () => { + it("If a negative number is set to the step property its positive equivalent should be used as effective value", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("endHandle"); + + cy.get("@rangeSlider").should("have.attr", "step", "-7"); + + // Test keyboard navigation which should use the positive step value (7) + cy.get("@endHandle").realClick(); + cy.get("@endHandle").realPress("Home"); // Move to start (0) + cy.get("@endHandle").realPress("ArrowRight"); // Move by step (should be 7) + cy.get("@endHandle").realPress("ArrowRight"); // Move by step again (should be 14) + cy.get("@endHandle").realPress("ArrowRight"); // Move by step again (should be 21) + + // The current value should be 'stepified' by 7 (positive equivalent) + cy.get("@rangeSlider").should("have.attr", "end-value", "21"); + }); + + it("If min property is set to a greater number than the max property their effective values should be swapped, their real ones - not", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Properties themselves should not be normalized + cy.get("@rangeSlider").should("have.attr", "min", "100"); + cy.get("@rangeSlider").should("have.attr", "max", "10"); + + // startValue should be within the boundaries of the effective (swapped) min and max props + cy.get("@rangeSlider").should("have.attr", "start-value", "10"); + }); + + it("Should keep the current values between the boundaries of min and max properties", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Set endValue to 300 (above max) + cy.get("@rangeSlider").invoke("attr", "end-value", "300"); + cy.get("@rangeSlider").should("have.attr", "end-value", "200"); + + // Set startValue to 99 (below min) + cy.get("@rangeSlider").invoke("attr", "start-value", "99"); + cy.get("@rangeSlider").should("have.attr", "start-value", "100"); + }); + + it("Should not 'stepify' current value if it is not in result of user interaction", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Set values programmatically + cy.get("@rangeSlider").invoke("attr", "start-value", "14"); + cy.get("@rangeSlider").invoke("attr", "end-value", "24"); + + // Values should not be stepped to the next step + cy.get("@rangeSlider").should("have.attr", "start-value", "14"); + cy.get("@rangeSlider").should("have.attr", "end-value", "24"); + }); + + it("If the step property or the labelInterval are changed, the tickmarks and labels must be updated also", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Change step to 2 + cy.get("@rangeSlider").invoke("attr", "step", "2"); + + // Change labelInterval to 4 + cy.get("@rangeSlider").invoke("attr", "label-interval", "4"); + + // Labels should be updated accordingly + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-scale-tickmark-label") + .should("have.length.lessThan", 21); // Should have fewer labels now + }); +}); + +describe("Testing events", () => { + it("Should fire input event on user interaction and change event after user interaction finish", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.get("@rangeSlider") + .invoke('on', 'ui5-input', cy.spy().as('inputEventSpy')) + .invoke('on', 'ui5-change', cy.spy().as('changeEventSpy')); + + // Start value handle and input + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("startHandle"); + + cy.get("@startHandle") + .realMouseDown() + .realMouseMove(100, 0) + .realMouseUp(); + + // Click on the slider to trigger both events + cy.get("@rangeSlider").realClick(); + + // Both input event and change event should be fired after user interaction + cy.get("@inputEventSpy").should('have.been.called'); + cy.get("@changeEventSpy").should('have.been.called'); + }); + + it("Should not fire change event if the values are the same after interaction", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("firstHandle"); + + cy.get("@rangeSlider") + .invoke('on', 'ui5-change', cy.spy().as('changeEventSpy')); + + cy.get("@firstHandle").realClick(); + cy.get("@firstHandle").realPress("Home"); + + cy.get("@changeEventSpy").should('not.have.been.called'); + }); + + it("Should fire input event with correctly swapped values", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-progress") + .as("rangeSliderProgressBar"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("firstHandle"); + + cy.get("@rangeSlider") + .invoke('on', 'ui5-input', cy.spy().as('inputEventSpy')); + + // Use keyboard navigation to move start handle past end handle + cy.get("@firstHandle").realClick(); + cy.get("@firstHandle").realPress("ArrowRight"); + cy.get("@firstHandle").realPress("ArrowRight"); + cy.get("@firstHandle").realPress("ArrowRight"); + + cy.get("@rangeSliderProgressBar").should("have.attr", "aria-valuenow", "2"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "2"); + cy.get("@rangeSlider").should("have.attr", "end-value", "4"); + cy.get("@inputEventSpy").should('have.been.called'); + }); + + it("Should not fire change event after user interaction is finished if the current value is the same as the one at the start of the action", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.get("@rangeSlider") + .invoke('on', 'ui5-change', cy.spy().as('changeEventSpy')); + + // Click on the same position (should not change value) + cy.get("@rangeSlider").realClick(); + + cy.get("@changeEventSpy").should('not.have.been.called'); + }); + + it("Should fire change event after swapping the values", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("startHandle"); + + cy.get("@rangeSlider") + .invoke('on', 'ui5-change', cy.spy().as('changeEventSpy')); + + // Drag start handle past end handle to swap values + cy.get("@startHandle") + .realMouseDown() + .realMouseMove(100, 0) + .realMouseUp(); + + cy.get("@rangeSlider").should("have.attr", "start-value", "2"); + cy.get("@rangeSlider").invoke("attr", "end-value").then((endValue: string) => { + expect(parseInt(endValue)).to.be.greaterThan(2); + }); + cy.get("@changeEventSpy").should('have.been.called'); + }); + + it("Aria attributes of the start handle are set correctly", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("startHandle"); + + cy.get("@rangeSlider").then(($el) => { + const rangeSlider = $el[0] as RangeSlider; + const minValue = rangeSlider.min; + const maxValue = rangeSlider.max; + const startValue = rangeSlider.startValue; + + cy.get("@startHandle") + .should("have.attr", "aria-labelledby", "ui5-slider-startHandleDesc"); + + cy.get("@startHandle") + .should("have.attr", "aria-valuemin", `${minValue}`); + + cy.get("@startHandle") + .should("have.attr", "aria-valuemax", `${maxValue}`); + + cy.get("@startHandle") + .should("have.attr", "aria-valuenow", `${startValue}`); + }); + }); + + it("Aria attributes of the end handle are set correctly", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("endHandle"); + + cy.get("@rangeSlider").then(($el) => { + const rangeSlider = $el[0] as RangeSlider; + const minValue = rangeSlider.min; + const maxValue = rangeSlider.max; + const endValue = rangeSlider.endValue; + + cy.get("@endHandle") + .should("have.attr", "aria-labelledby", "ui5-slider-endHandleDesc"); + + cy.get("@endHandle") + .should("have.attr", "aria-valuemin", `${minValue}`); + + cy.get("@endHandle") + .should("have.attr", "aria-valuemax", `${maxValue}`); + + cy.get("@endHandle") + .should("have.attr", "aria-valuenow", `${endValue}`); + }); + }); + + it("Aria-labelledby text is mapped correctly when values are swapped", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("startHandle"); + cy.get("@rangeSlider") + .shadow() + .find("#ui5-slider-startHandleDesc") + .as("rangeSliderStartHandleSpan"); + cy.get("@rangeSlider") + .shadow() + .find("#ui5-slider-endHandleDesc") + .as("rangeSliderEndHandleSpan"); + + // Drag start handle past end handle to swap values using real events + cy.get("@startHandle") + .realMouseDown() + .realMouseMove(100, 0) + .realMouseUp(); + + cy.get("@rangeSliderStartHandleSpan").should("contain.text", "Left handle"); + cy.get("@rangeSliderEndHandleSpan").should("contain.text", "Right handle"); + }); + + it("Click anywhere in the Range Slider should focus the closest handle", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Test that clicking on the slider focuses some element (either handle or progress bar) + cy.get("@rangeSlider").realClick(); + + // Verify that the slider component itself is focused + cy.get("@rangeSlider").should("have.focus"); + + // Test that handles can be focused when clicked directly + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .realClick() + .should("have.focus"); + + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .realClick() + .should("have.focus"); + }); + + it("Click currently selected range should focus it", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-progress") + .as("rangeSliderSelection"); + + cy.get("@rangeSlider").realClick(); + + // Should focus the progress bar + cy.get("@rangeSliderSelection").should("have.focus"); + }); + + it("When not yet focused, 'Tab' should focus the Range Slider and move the focus to the progress bar", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-progress") + .as("rangeSliderSelection"); + + cy.realPress("Tab"); + + cy.get("@rangeSlider").should("have.focus"); + cy.get("@rangeSliderSelection").should("have.focus"); + }); + + it("When progress bar has the focus, 'Tab' should move the focus to the first handle", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("rangeSliderStartHandle"); + + // Focus the progress bar first + cy.realPress("Tab"); + cy.realPress("Tab"); + + cy.get("@rangeSliderStartHandle").should("have.focus"); + }); + + it("When the first handle has the focus, 'Tab' should focus the second handle", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("rangeSliderEndHandle"); + + // Focus the first handle first + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("Tab"); + + cy.get("@rangeSliderEndHandle").should("have.focus"); + }); + + it("When the second handle has the focus, 'Tab' should move the focus away from the Range Slider", () => { + cy.mount( + <> + + + + ); + + cy.get("#basic-range-slider").as("currentRangeSlider"); + cy.get("#basic-range-slider-with-tooltip").as("nextRangeSlider"); + cy.get("@nextRangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-progress") + .as("rangeSliderSelection"); + + // Focus through the first slider + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("Tab"); + + cy.get("@currentRangeSlider").should("not.have.focus"); + cy.get("@nextRangeSlider").should("have.focus"); + cy.get("@rangeSliderSelection").should("have.focus"); + }); + + it("Shift+Tab should focus the previous Range Slider and move the focus to its second handle", () => { + cy.mount( + <> + + + + ); + + cy.get("#basic-range-slider-with-tooltip").as("currentRangeSlider"); + cy.get("#basic-range-slider").as("previousRangeSlider"); + cy.get("@previousRangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("previousRangeSliderEndHandle"); + + // Focus the second slider first + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("Tab"); + + cy.realPress(["Shift", "Tab"]); + + cy.get("@currentRangeSlider").should("not.have.focus"); + cy.get("@previousRangeSlider").should("have.focus"); + cy.get("@previousRangeSliderEndHandle").should("have.focus"); + }); + + it("When the second handle has the focus, 'Shift' + 'Tab' should move the focus to the first handle", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("rangeSliderStartHandle"); + + // Focus the second handle first + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("Tab"); + + cy.realPress(["Shift", "Tab"]); + + cy.get("@rangeSliderStartHandle").should("have.focus"); + }); + + it("When the first handle has the focus, 'Shift' + 'Tab' should move the focus to the progress bar", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-progress") + .as("rangeSliderSelection"); + + // Focus the first handle first + cy.realPress("Tab"); + cy.realPress("Tab"); + + cy.realPress(["Shift", "Tab"]); + + cy.get("@rangeSliderSelection").should("have.focus"); + }); + + it("When the progress bar has the focus, 'Shift' + 'Tab' should move the focus away from the Range Slider", () => { + cy.mount( + <> + + + + ); + + cy.get("#basic-range-slider").as("rangeSlider"); + cy.get("#previous-range-slider").as("previousRangeSlider"); + + // Focus the current slider's progress bar first + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("Tab"); + + cy.realPress(["Shift", "Tab"]); + + cy.get("@rangeSlider").should("not.have.focus"); + cy.get("@previousRangeSlider").should("have.focus"); + }); + + it("When one handle comes across the other and the values are swapped the focus must be switched between the handles", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("startHandle"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("endHandle"); + + // Focus the start handle and move it past the end handle using keyboard + cy.get("@startHandle").realClick(); + + // Move start handle to the right multiple times to pass the end handle + for (let i = 0; i < 15; i++) { + cy.get("@startHandle").realPress("ArrowRight"); + } + + // After swapping, the original start handle should now be the end handle + // and should have focus + cy.get("@endHandle").should("have.focus"); + + // Verify values were swapped + cy.get("@rangeSlider").should("have.attr", "start-value", "20"); + cy.get("@rangeSlider").should("have.attr", "end-value", "25"); + }); +}); + +describe("Accessibility: Testing keyboard handling", () => { + it("When progress bar is focused 'Right Arrow' key should increase both values of the Range Slider with a small increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-progress") + .as("progressBar"); + + // Click on the progress bar to focus it + cy.get("@progressBar").realClick(); + cy.get("@progressBar").should("have.focus"); + + // Press arrow right + cy.get("@progressBar").realPress("ArrowRight"); + + // Verify that both values increased by 1 + cy.get("@rangeSlider").should("have.attr", "start-value", "11"); + cy.get("@rangeSlider").should("have.attr", "end-value", "31"); + }); + + it("When progress bar is focused 'Left Arrow' key should decrease both values of the Range Slider with a small increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress("ArrowLeft"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "9"); + cy.get("@rangeSlider").should("have.attr", "end-value", "29"); + }); + + it("When progress bar is focused 'Up Arrow' key should increase both values of the Range Slider with a small increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress("ArrowUp"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "11"); + cy.get("@rangeSlider").should("have.attr", "end-value", "31"); + }); + + it("When progress bar is focused 'Down' key should decrease both values of the Range Slider with a small increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress("ArrowDown"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "9"); + cy.get("@rangeSlider").should("have.attr", "end-value", "29"); + }); + + it("When progress bar is focused 'Control' + 'Right Arrow' key should increase both values of the Range Slider with a big increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress(["Control", "ArrowRight"]); + + cy.get("@rangeSlider").should("have.attr", "start-value", "20"); + cy.get("@rangeSlider").should("have.attr", "end-value", "40"); + }); + + it("When progress bar is focused 'Control' + 'Left Arrow' key should decrease both values of the Range Slider with a big increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress(["Control", "ArrowLeft"]); + + cy.get("@rangeSlider").should("have.attr", "start-value", "10"); + cy.get("@rangeSlider").should("have.attr", "end-value", "30"); + }); + + it("When progress bar is focused 'Control' + 'Up Arrow' key should increase both values of the Range Slider with a big increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress(["Control", "ArrowUp"]); + + cy.get("@rangeSlider").should("have.attr", "start-value", "20"); + cy.get("@rangeSlider").should("have.attr", "end-value", "40"); + }); + + it("When progress bar is focused 'Control' + 'Down' key should decrease both values of the Range Slider with a big increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress(["Control", "ArrowDown"]); + + cy.get("@rangeSlider").should("have.attr", "start-value", "10"); + cy.get("@rangeSlider").should("have.attr", "end-value", "30"); + }); + + it("When progress bar is focused 'Page Up' key should increase both values of the Range Slider with a big increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress("PageUp"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "20"); + cy.get("@rangeSlider").should("have.attr", "end-value", "40"); + }); + + it("When progress bar is focused 'Page Down' key should decrease both values of the Range Slider with a big increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress("PageDown"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "10"); + cy.get("@rangeSlider").should("have.attr", "end-value", "30"); + }); + + it("When progress bar is focused the '+' key should increase both values of the Range Slider with a small increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress("+"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "11"); + cy.get("@rangeSlider").should("have.attr", "end-value", "31"); + + // Test numpad add + cy.realPress("NumpadAdd"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "12"); + cy.get("@rangeSlider").should("have.attr", "end-value", "32"); + }); + + it("When progress bar is focused the '-' key should decrease both values of the Range Slider with a small increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress("-"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "11"); + cy.get("@rangeSlider").should("have.attr", "end-value", "31"); + + // Test numpad subtract + cy.realPress("NumpadSubtract"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "10"); + cy.get("@rangeSlider").should("have.attr", "end-value", "30"); + }); + + it("When progress bar is focused an 'End' key press should offset the selected range to the end of the Range Slider", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress("End"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "80"); + cy.get("@rangeSlider").should("have.attr", "end-value", "100"); + }); + + it("When progress bar is focused a 'Home' key press should offset the selected range to the start of the Range Slider", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress("Home"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "0"); + cy.get("@rangeSlider").should("have.attr", "end-value", "20"); + }); + + it("A 'Esc' key press should return the values of the Range Slider at their initial point at the time of its focusing", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + cy.realPress("Tab"); + cy.realPress("Escape"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "24"); + cy.get("@rangeSlider").should("have.attr", "end-value", "42"); + }); + + it("When a handle is focused 'Right Arrow' key should increase its value with a small increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus start handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("ArrowRight"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "11"); + + // Focus end handle + cy.realPress("Tab"); + cy.realPress("ArrowRight"); + + cy.get("@rangeSlider").should("have.attr", "end-value", "31"); + }); + + it("When a handle is focused 'Left Arrow' key should decrease its value with a small increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus end handle first + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("ArrowLeft"); + + cy.get("@rangeSlider").should("have.attr", "end-value", "29"); + + // Focus start handle + cy.realPress(["Shift", "Tab"]); + cy.realPress("ArrowLeft"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "9"); + }); + + it("When a handle is focused 'Up Arrow' key should increase its value with a small increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus start handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("ArrowUp"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "11"); + + // Focus end handle + cy.realPress("Tab"); + cy.realPress("ArrowUp"); + + cy.get("@rangeSlider").should("have.attr", "end-value", "31"); + }); + + it("When a handle is focused 'Down' key should decrease its value with a small increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus start handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("ArrowDown"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "9"); + + // Focus end handle + cy.realPress("Tab"); + cy.realPress("ArrowDown"); + + cy.get("@rangeSlider").should("have.attr", "end-value", "29"); + }); + + it("When a handle is focused 'Control' + 'Right Arrow' key should increase its value with a big increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus start handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress(["Control", "ArrowRight"]); + + cy.get("@rangeSlider").should("have.attr", "start-value", "20"); + + // Focus end handle + cy.realPress("Tab"); + cy.realPress(["Control", "ArrowRight"]); + + cy.get("@rangeSlider").should("have.attr", "end-value", "40"); + }); + + it("When a handle is focused 'Control' + 'Left Arrow' key should decrease its value with a big increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus start handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress(["Control", "ArrowLeft"]); + + cy.get("@rangeSlider").should("have.attr", "start-value", "10"); + + // Focus end handle + cy.realPress("Tab"); + cy.realPress(["Control", "ArrowLeft"]); + + cy.get("@rangeSlider").should("have.attr", "end-value", "30"); + }); + + it("When a handle is focused 'Control' + 'Up Arrow' key should increase its value with a big increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus start handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress(["Control", "ArrowUp"]); + + cy.get("@rangeSlider").should("have.attr", "start-value", "20"); + + // Focus end handle + cy.realPress("Tab"); + cy.realPress(["Control", "ArrowUp"]); + + cy.get("@rangeSlider").should("have.attr", "end-value", "40"); + }); + + it("When handle is focused 'Control' + 'Down' key should decrease its value with a big increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus start handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress(["Control", "ArrowDown"]); + + cy.get("@rangeSlider").should("have.attr", "start-value", "10"); + + // Focus end handle + cy.realPress("Tab"); + cy.realPress(["Control", "ArrowDown"]); + + cy.get("@rangeSlider").should("have.attr", "end-value", "30"); + }); + + it("When a handle is focused 'Page Down' key should decrease its value with a big increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus start handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("PageDown"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "10"); + + // Focus end handle + cy.realPress("Tab"); + cy.realPress("PageDown"); + + cy.get("@rangeSlider").should("have.attr", "end-value", "30"); + }); + + it("When a handle focused the '+' key should increase its value with a small increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus start handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("+"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "11"); + + // Test numpad add on start handle + cy.realPress("NumpadAdd"); + cy.get("@rangeSlider").should("have.attr", "start-value", "12"); + + // Focus end handle + cy.realPress("Tab"); + cy.realPress("+"); + + cy.get("@rangeSlider").should("have.attr", "end-value", "31"); + + // Test numpad add on end handle + cy.realPress("NumpadAdd"); + cy.get("@rangeSlider").should("have.attr", "end-value", "32"); + }); + + it("When a handle focused the '-' key should decrease its value with a small increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus start handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("-"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "11"); + + // Test numpad subtract on start handle + cy.realPress("NumpadSubtract"); + cy.get("@rangeSlider").should("have.attr", "start-value", "10"); + + // Focus end handle + cy.realPress("Tab"); + cy.realPress("-"); + + cy.get("@rangeSlider").should("have.attr", "end-value", "31"); + + // Test numpad subtract on end handle + cy.realPress("NumpadSubtract"); + cy.get("@rangeSlider").should("have.attr", "end-value", "30"); + }); + + it("When a handle is focused 'Page Up' key should increase its value with a big increment step", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus start handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("PageUp"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "20"); + + // Focus end handle + cy.realPress("Tab"); + cy.realPress("PageUp"); + + cy.get("@rangeSlider").should("have.attr", "end-value", "40"); + }); + + it("When a handle is focused an 'End' key press should set its value to the maximum allowed", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus end handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("End"); + + cy.get("@rangeSlider").should("have.attr", "end-value", "100"); + }); + + it("When a handle is focused a 'Home' key press should set its value to the start of the Range Slider", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Focus start handle + cy.realPress("Tab"); + cy.realPress("Tab"); + cy.realPress("Home"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "0"); + }); +}); + +describe("Testing resize handling and RTL support", () => { + it("Testing RTL support", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("startHandle"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("endHandle"); + + // Initially start-handle should be 0% from the start side (inset-inline-start) + cy.get("@startHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 0%, 100%);"); + // End-handle should be 40% from the start side + cy.get("@endHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 40%, 100%);"); + + // Set startValue to 3 + cy.get("@rangeSlider").invoke("attr", "start-value", "3"); + cy.get("@startHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 30%, 100%);"); + + // Click on slider + cy.get("@rangeSlider").realClick(); + cy.get("@rangeSlider").should("have.attr", "end-value", "5"); + cy.get("@endHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 50%, 100%);"); + }); + + it("Testing RTL KBH support", () => { + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='start']") + .as("startHandle"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-handle][handle-type='end']") + .as("endHandle"); + cy.get("@rangeSlider") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-progress") + .as("rangeSliderSelection"); + + // Initially start-handle should be 30% from the start side (inset-inline-start) + cy.get("@startHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 30%, 100%);"); + // End-handle should be 70% from the start side + cy.get("@endHandle").should("have.attr", "style", "inset-inline-start: clamp(0%, 70%, 100%);"); + + // Test selection range keyboard navigation + cy.get("@rangeSliderSelection").realClick(); + cy.get("@rangeSliderSelection").realPress("ArrowLeft"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "4"); + cy.get("@rangeSlider").should("have.attr", "end-value", "8"); + + cy.get("@rangeSliderSelection").realPress("ArrowRight"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "3"); + cy.get("@rangeSlider").should("have.attr", "end-value", "7"); + + // Test start handle + cy.get("@startHandle").realClick(); + cy.get("@startHandle").realPress("ArrowLeft"); + cy.get("@startHandle").realPress("ArrowLeft"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "5"); + + cy.get("@startHandle").realPress("ArrowRight"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "4"); + + cy.get("@startHandle").realPress("Home"); + + cy.get("@rangeSlider").should("have.attr", "start-value", "0"); + + // Test end handle + cy.get("@endHandle").realClick(); + cy.get("@endHandle").realPress("ArrowLeft"); + cy.get("@endHandle").realPress("ArrowLeft"); + + cy.get("@rangeSlider").should("have.attr", "end-value", "9"); + + cy.get("@endHandle").realPress("ArrowRight"); + + cy.get("@rangeSlider").should("have.attr", "end-value", "8"); + + cy.get("@endHandle").realPress("End"); + + cy.get("@rangeSlider").should("have.attr", "end-value", "10"); + }); + + it("Should hide all labels except the first and the last one, if there is not enough space for all of them", () => { + // Set small viewport first + cy.viewport(400, 600); + + cy.mount(); + + cy.get("[ui5-range-slider]").as("rangeSlider"); + + // Wait for the component to render and calculate overlapping + cy.get("@rangeSlider").should(($el) => { + const rangeSlider = $el[0] as RangeSlider; + expect(rangeSlider._labelsOverlapping || rangeSlider._hiddenTickmarks).to.be.true; + }); + + // Trigger a resize event to force recalculation + cy.window().trigger('resize'); + + // Wait for the resize handling to complete + cy.get("@rangeSlider").should(($el) => { + const rangeSlider = $el[0] as RangeSlider; + expect(rangeSlider._labelsOverlapping || rangeSlider._hiddenTickmarks).to.be.true; + }); + }); +}); + +describe("Accessibility", () => { + it("should apply associated label text as aria-label on the slider element", () => { + const labelText = "basic range slider"; + cy.mount( + <> + + + + ); + + cy.get("[ui5-range-slider]") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-progress") + .should("have.attr", "aria-label", `${labelText} Range`); + }); + + it("Aria attributes of the progress bar are set correctly", () => { + cy.mount( + + ); + + cy.get("[ui5-range-slider]") + .shadow() + .find("[ui5-slider-scale]") + .shadow() + .find(".ui5-slider-progress") + .as("sliderProgress"); + + cy.get("[ui5-range-slider]").then(($el) => { + const rangeSlider = $el[0] as RangeSlider; + const minValue = rangeSlider.min; + const maxValue = rangeSlider.max; + const startValue = rangeSlider.startValue; + const endValue = rangeSlider.endValue; + + cy.get("@sliderProgress") + .should("have.attr", "aria-label", "Range"); + + cy.get("@sliderProgress") + .should("have.attr", "aria-valuemin", `${minValue}`); + + cy.get("@sliderProgress") + .should("have.attr", "aria-valuemax", `${maxValue}`); + + cy.get("@sliderProgress") + .should("have.attr", "aria-valuetext", `From ${startValue} to ${endValue}`); + + cy.get("@sliderProgress") + .should("have.attr", "aria-valuenow", `${endValue}`); + + }); + }); +}); diff --git a/packages/main/src/RangeSlider.ts b/packages/main/src/RangeSlider.ts index c45dfd6ec810..19012eed69cc 100644 --- a/packages/main/src/RangeSlider.ts +++ b/packages/main/src/RangeSlider.ts @@ -93,7 +93,7 @@ type AffectedValue = "startValue" | "endValue"; languageAware: true, formAssociated: true, template: RangeSliderTemplate, - styles: [SliderBase.styles, rangeSliderStyles], + styles: [rangeSliderStyles], }) class RangeSlider extends SliderBase implements IFormInputElement { /** @@ -106,7 +106,7 @@ class RangeSlider extends SliderBase implements IFormInputElement { @property({ type: Number }) set startValue(value: number) { this._startValue = value; - this.tooltipStartValue = value.toString(); + this.tooltipStartValue = value?.toString() ?? ""; } get startValue(): number { @@ -123,7 +123,7 @@ class RangeSlider extends SliderBase implements IFormInputElement { @property({ type: Number }) set endValue(value: number) { this._endValue = value; - this.tooltipEndValue = value.toString(); + this.tooltipEndValue = value?.toString() ?? ""; } get endValue(): number { @@ -145,6 +145,9 @@ class RangeSlider extends SliderBase implements IFormInputElement { @property({ type: Boolean }) rangePressed = false; + @property({ type: Boolean }) + _progressFocused = false; + @property({ type: Boolean }) _isStartValueValid = false; @@ -192,6 +195,33 @@ class RangeSlider extends SliderBase implements IFormInputElement { this._stateStorage.endValue = undefined; this._lastValidStartValue = this.min.toString(); this._lastValidEndValue = this.max.toString(); + this._onDocumentClick = this._onDocumentClick.bind(this); + } + + onEnterDOM() { + document.addEventListener("mousedown", this._onDocumentClick, true); + } + + onExitDOM() { + document.removeEventListener("mousedown", this._onDocumentClick, true); + } + + /** + * Handles document-level clicks to clear progress focus when clicking outside. + * @private + */ + _onDocumentClick(e: MouseEvent) { + const target = e.target as HTMLElement; + const clickedInside = e.composedPath().includes(this); + + if (!clickedInside) { + if (this._progressFocused) { + this._progressFocused = false; + } + if (this._tooltipsOpen) { + this._tooltipsOpen = false; + } + } } get _ariaDisabled() { @@ -326,6 +356,7 @@ class RangeSlider extends SliderBase implements IFormInputElement { this._setAffectedValue(undefined); this._startValueInitial = undefined; this._endValueInitial = undefined; + this._progressFocused = false; if (this.showTooltip && !(e.relatedTarget as HTMLInputElement)?.hasAttribute("ui5-slider-tooltip")) { this._tooltipsOpen = false; @@ -358,7 +389,9 @@ class RangeSlider extends SliderBase implements IFormInputElement { this._endValueAtBeginningOfAction = this.endValue; if (isEscape(e)) { - this.update(undefined, this._startValueInitial, this._endValueInitial); + if (this._startValueInitial !== undefined && this._endValueInitial !== undefined) { + this.update(undefined, this._startValueInitial, this._endValueInitial); + } return; } @@ -481,15 +514,30 @@ class RangeSlider extends SliderBase implements IFormInputElement { return; } - // Calculate the new value from the press position of the event + // Pre-calculate whether the press is in the current range before handleDownBase + // This is needed so focusInnerElement() knows where to focus + const ctor = this.constructor as typeof RangeSlider; + const pageX = ctor.getPageXValueFromEvent(e); + const tempValue = ctor.getValueFromInteraction(e, this._effectiveStep, this._effectiveMin, this._effectiveMax, this.getBoundingClientRect(), this.directionStart); + const isInRange = tempValue >= this.startValue && tempValue <= this.endValue; + const startHandle = this.shadowRoot!.querySelector("[ui5-slider-handle][handle-type='start']"); + const endHandle = this.shadowRoot!.querySelector("[ui5-slider-handle][handle-type='end']"); + const inStartHandle = startHandle && pageX >= startHandle.getBoundingClientRect().left && pageX <= startHandle.getBoundingClientRect().right; + const inEndHandle = endHandle && pageX >= endHandle.getBoundingClientRect().left && pageX <= endHandle.getBoundingClientRect().right; + + if (isInRange && !inStartHandle && !inEndHandle) { + this._setIsPressInCurrentRange(true); + this._progressFocused = true; + this.rangePressed = true; + } else { + this._progressFocused = false; + this.rangePressed = false; + } + const newValue = this.handleDownBase(e); - // Determine the rest of the needed details from the start of the interaction. this._saveInteractionStartData(e, newValue); - this.rangePressed = this._isPressInCurrentRange; - - // Do not yet update the RangeSlider if press is in range or over a handle. if (this._isPressInCurrentRange || this._handeIsPressed) { this._handeIsPressed = false; return; @@ -509,7 +557,7 @@ class RangeSlider extends SliderBase implements IFormInputElement { * @private */ _saveInteractionStartData(e: TouchEvent | MouseEvent, newValue: number) { - const progressBarDom = this.shadowRoot!.querySelector(".ui5-slider-progress")!.getBoundingClientRect(); + const progressBarDom = this._progressBar?.getBoundingClientRect(); // Save the state of the value properties on the start of the interaction this._startValueAtBeginningOfAction = this.startValue; @@ -521,7 +569,9 @@ class RangeSlider extends SliderBase implements IFormInputElement { // Which element of the Range Slider is pressed and which value property to be modified on further interaction this._pressTargetAndAffectedValue(this._initialPageXPosition, newValue); // Use the progress bar to save the initial coordinates of the start-handle when the interaction begins. - this._initialStartHandlePageX = this.directionStart === "left" ? progressBarDom.left : progressBarDom.right; + if (progressBarDom) { + this._initialStartHandlePageX = this.directionStart === "left" ? progressBarDom.left : progressBarDom.right; + } } /** @@ -606,8 +656,8 @@ class RangeSlider extends SliderBase implements IFormInputElement { * @private */ _pressTargetAndAffectedValue(clientX: number, value: number) { - const startHandle = this.shadowRoot!.querySelector(".ui5-slider-handle--start")!; - const endHandle = this.shadowRoot!.querySelector(".ui5-slider-handle--end")!; + const startHandle = this.shadowRoot!.querySelector("[ui5-slider-handle][handle-type='start']")!; + const endHandle = this.shadowRoot!.querySelector("[ui5-slider-handle][handle-type='end']")!; // Check if the press point is in the bounds of any of the Range Slider handles const handleStartDomRect = startHandle.getBoundingClientRect(); @@ -690,16 +740,16 @@ class RangeSlider extends SliderBase implements IFormInputElement { const affectedValue = this._valueAffected; if (this._isPressInCurrentRange || !affectedValue) { - this._progressBar.focus(); + this._progressBar?.focus(); } if ((affectedValue === "startValue" && !isReversed) || (affectedValue === "endValue" && isReversed)) { - this._startHandle.focus(); + this._startHandle?.focus(); this.bringToFrontTooltip("start"); } if ((affectedValue === "endValue" && !isReversed) || (affectedValue === "startValue" && isReversed)) { - this._endHandle.focus(); + this._endHandle?.focus(); this.bringToFrontTooltip("end"); } } @@ -1004,15 +1054,16 @@ class RangeSlider extends SliderBase implements IFormInputElement { } get _startHandle() { - return this.shadowRoot!.querySelector(".ui5-slider-handle--start")!; + return this.shadowRoot!.querySelector("[ui5-slider-handle][handle-type='start']")!; } get _endHandle() { - return this.shadowRoot!.querySelector(".ui5-slider-handle--end")!; + return this.shadowRoot!.querySelector("[ui5-slider-handle][handle-type='end']")!; } get _progressBar() { - return this.shadowRoot!.querySelector(".ui5-slider-progress")!; + const sliderScale = this.shadowRoot!.querySelector("[ui5-slider-scale]"); + return sliderScale?.shadowRoot?.querySelector(".ui5-slider-progress") ?? null; } get _ariaLabelledByStartHandleText() { diff --git a/packages/main/src/RangeSliderTemplate.tsx b/packages/main/src/RangeSliderTemplate.tsx index 54377bb87ce5..d07bc9427154 100644 --- a/packages/main/src/RangeSliderTemplate.tsx +++ b/packages/main/src/RangeSliderTemplate.tsx @@ -1,128 +1,172 @@ -import directionArrows from "@ui5/webcomponents-icons/dist/direction-arrows.js"; import type RangeSlider from "./RangeSlider.js"; -import Icon from "./Icon.js"; -import SliderBaseTemplate from "./SliderBaseTemplate.js"; import SliderTooltip from "./SliderTooltip.js"; +import SliderHandle from "./SliderHandle.js"; +import SliderScale from "./SliderScale.js"; -export default function RangeSliderTemplate(this: RangeSlider) { - return SliderBaseTemplate.call(this, { - handlesAriaText, - progressBar, - handles, - }); -} +const _handlePosition = (min: number, max: number, value: number) => { + const range = max - min; + const position = ((value - min) / range) * 100; + return position; +}; -export function handlesAriaText(this: RangeSlider) { - return (<> - {this._ariaHandlesText.startHandleText} - {this._ariaHandlesText.endHandleText} - ); -} +const startHandle = (slider: RangeSlider) => { + const position = _handlePosition(slider.min, slider.max, slider.startValue); -export function progressBar(this: RangeSlider) { return ( -
-
+
-
- ); -} - -export function handles(this: RangeSlider) { - return (<> -
-
- -
+ aria-valuemin={slider.min} + aria-valuemax={slider.max} + aria-valuenow={slider.startValue} + aria-labelledby={slider._ariaLabelledByStartHandleText} + aria-disabled={slider._ariaDisabled} + aria-describedby={slider._ariaDescribedByHandleText} + aria-keyshortcuts={slider._ariaKeyshortcuts} + onFocusIn={slider._onfocusin} + onFocusOut={slider._onfocusout} + style={{ + "inset-inline-start": `clamp(0%, ${position}%, 100%)`, + }} + > - - -
-
-
+ ); +}; + +const endHandle = (slider: RangeSlider) => { + const position = _handlePosition(slider.min, slider.max, slider.endValue); + + return ( + <> + - -
+ onFocusIn={slider._onfocusin} + onFocusOut={slider._onfocusout} + style={{ + "inset-inline-start": `clamp(0%, ${position}%, 100%)`, + }} + > + + {endTooltip(slider)} + + ); +}; + +const startTooltip = (slider: RangeSlider) => ( + + +); - ( + + +); + +export default function RangeSliderTemplate(this: RangeSlider) { + return ( + <> +
- -
- ); + {/* Hidden accessibility text for handle descriptions */} + {this._ariaHandlesText.startHandleText} + {this._ariaHandlesText.endHandleText} + {this.accessibleName && {this.accessibleName}} + + + {startHandle(this)} + {endHandle(this)} + + {this.editableTooltip && <> + {this._ariaDescribedByInputText} + } + +
+ + ); } diff --git a/packages/main/src/SliderBase.ts b/packages/main/src/SliderBase.ts index 5ba3b8227155..5cfbebd3e287 100644 --- a/packages/main/src/SliderBase.ts +++ b/packages/main/src/SliderBase.ts @@ -296,12 +296,17 @@ abstract class SliderBase extends UI5Element { _onkeydown(e: KeyboardEvent) { const target = e.target as HTMLElement; + const isHandleFocused = target.hasAttribute("ui5-slider-handle"); - if (isF2(e) && target.classList.contains("ui5-slider-handle")) { - (target.parentNode!.querySelector("[ui5-slider-tooltip]") as HTMLElement).focus(); + if (isF2(e) && isHandleFocused) { + const handleType = target.getAttribute("handle-type"); + const tooltipSelector = handleType === "start" ? "[data-sap-ui-start-value]" : handleType === "end" ? "[data-sap-ui-end-value]" : "[ui5-slider-tooltip]"; + const tooltip = this.shadowRoot!.querySelector(tooltipSelector); + tooltip?.focus(); + return; } - if (this.disabled || this._effectiveStep === 0 || target.hasAttribute("ui5-slider-handle")) { + if (this.disabled || this._effectiveStep === 0) { return; } @@ -391,7 +396,7 @@ abstract class SliderBase extends UI5Element { const labelItemsParent = this.shadowRoot!.querySelector(".ui5-slider-labels") as HTMLElement; const labelItemsSumWidth = this._labels.length * childWidthPx; // all labels width - const labelItemsParentWidth = labelItemsParent.clientWidth; // label parent width + const labelItemsParentWidth = labelItemsParent && labelItemsParent.clientWidth; // label parent width this._labelsOverlapping = labelItemsParentWidth < labelItemsSumWidth; } diff --git a/packages/main/src/SliderHandle.ts b/packages/main/src/SliderHandle.ts index 9568c5305555..b1ee9a552543 100644 --- a/packages/main/src/SliderHandle.ts +++ b/packages/main/src/SliderHandle.ts @@ -80,6 +80,15 @@ class SliderHandle extends UI5Element { @property() orientation: `${SliderScaleOrientation}` = "Horizontal"; + /** + * Defines the type of handle for styling purposes. + * Used by RangeSlider to differentiate between start and end handles. + * + * @private + */ + @property() + handleType: "start" | "end" | "single" = "single"; + getFocusDomRef(): HTMLElement | undefined { return this; } diff --git a/packages/main/src/SliderHandleTemplate.tsx b/packages/main/src/SliderHandleTemplate.tsx index 165baac862e2..a27b243b07fd 100644 --- a/packages/main/src/SliderHandleTemplate.tsx +++ b/packages/main/src/SliderHandleTemplate.tsx @@ -4,7 +4,12 @@ import type SliderHandle from "./SliderHandle.js"; export default function SliderHandleTemplate(this: SliderHandle) { return ( -
+
void; + + /** + * Event handler for focusout on the progress bar. + * @private + */ + onProgressFocusOut?: (e: FocusEvent) => void; + /** * @private */ diff --git a/packages/main/src/SliderScaleTemplate.tsx b/packages/main/src/SliderScaleTemplate.tsx index d77efe915746..28ae29fbb043 100644 --- a/packages/main/src/SliderScaleTemplate.tsx +++ b/packages/main/src/SliderScaleTemplate.tsx @@ -1,4 +1,5 @@ import type SliderScale from "./SliderScale.js"; +import type { AriaRole } from "@ui5/webcomponents-base/dist/types.js"; export default function SliderScaleTemplate(this: SliderScale) { return ( @@ -25,7 +26,26 @@ export default function SliderScaleTemplate(this: SliderScale) { ))}
)} -
+
); diff --git a/packages/main/src/themes/RangeSlider.css b/packages/main/src/themes/RangeSlider.css index f9d9892697b4..b50a8192a5cb 100644 --- a/packages/main/src/themes/RangeSlider.css +++ b/packages/main/src/themes/RangeSlider.css @@ -1,77 +1,53 @@ -:host([ui5-range-slider]) .ui5-slider-progress-container::before { - background-color: var(--_ui5_slider_progress_container_dot_background); -} - -/* Range Slider handles (Horizon implementatioon) */ - -.ui5-slider-root:hover:active .ui5-slider-handle:not(:focus) { - background: var(--sapSlider_RangeHandleBackground); -} - -:host([range-pressed]) .ui5-slider-root:active .ui5-slider-handle:not(:focus) { - background: var(--_ui5_range_slider_handle_active_background); - border: var(--_ui5_slider_handle_focus_border); - box-shadow: none; -} +@import "./InvisibleTextStyles.css"; +@import "./FormComponents.css"; -:host([range-pressed]) .ui5-slider-handle [slider-icon] { - display: var(--_ui5_range_slider_active_handle_icon_display); +:host { + display: inline-block; + height: var(--_slider_height, 2.75rem); + width: 100%; } -.ui5-slider-root:not(.ui5-slider-root-phone):focus .ui5-slider-inner .ui5-slider-handle, -.ui5-slider-root:not(.ui5-slider-root-phone) .ui5-slider-inner .ui5-slider-handle:focus { - background: var(--_ui5_range_slider_handle_background_focus); +:host([label-interval]:not([label-interval="0"])) { + height: 3.75rem; + align-items: flex-start; } -.ui5-slider-root:not(.ui5-slider-root-phone) .ui5-slider-inner .ui5-slider-handle:focus [slider-icon] { - display: none; -} - -.ui5-slider-root:not(.ui5-slider-root-phone) .ui5-slider-progress:focus::before { - display: var(--_ui5_range_slider_legacy_progress_focus_display); - content: ''; - position: absolute; - width: var(--_ui5_range_slider_focus_outline_width); - border: var(--_ui5_slider_progress_outline); - border-radius: var(--_ui5_range_slider_focus_outline_radius); - top: var(--_ui5_slider_progress_outline_offset); - height: var(--_ui5_slider_outer_height); +.ui5-slider-evo-root { + width: 100%; + height: 100%; + display: flex; + align-items: center; + padding: var(--_slider_root_side_padding); box-sizing: border-box; - left: var(--_ui5_slider_progress_outline_offset_left); } -.ui5-slider-progress { - position: relative; - inset-inline-start: 0; +:host([disabled]) { + opacity: var(--_ui5_slider_disabled_opacity); + cursor: default; + pointer-events: none; } -.ui5-slider-progress:focus::after { - border: 0.125rem solid var(--sapContent_FocusColor); - border-radius: 0.5rem; - content: ""; - display: var(--_ui5_range_slider_progress_focus_display); - position: absolute; - top: var(--_ui5_range_slider_progress_focus_top); - left: var(--_ui5_range_slider_progress_focus_left); - right: var(--_ui5_range_slider_progress_focus_right); - padding: var(--_ui5_range_slider_progress_focus_padding); - height: var(--_ui5_range_slider_progress_focus_height); - box-sizing: border-box; +[ui5-slider-handle] { + z-index: 5; } -.ui5-slider-handle { +/* Range Slider specific styles */ + +/* Handle background styling - these work because we're styling the custom element host, not its shadow DOM */ +[ui5-slider-handle] { background: var(--_ui5_range_slider_handle_background); } -.ui5-slider-progress-container:hover ~ .ui5-slider-handle:not(:focus), -.ui5-slider-handle:hover { +[ui5-slider-handle]:hover { background: var(--_ui5_range_slider_root_hover_handle_bg); } -.ui5-slider-root:hover .ui5-slider-handle:not(:focus) [slider-icon] { - display: var(--_ui5_range_slider_root_hover_handle_icon_display); +[ui5-slider-handle]:focus { + background: var(--_ui5_range_slider_handle_background_focus); } -:host([range-pressed]) .ui5-slider-root:active .ui5-slider-handle:not(:focus) [slider-icon] { - display: var(--_ui5_range_slider_root_active_handle_icon_display); -} \ No newline at end of file +:host([range-pressed]) [ui5-slider-handle]:not(:focus) { + background: var(--_ui5_range_slider_handle_active_background); + border: var(--_ui5_slider_handle_focus_border); + box-shadow: none; +} diff --git a/packages/main/src/themes/SliderBase.css b/packages/main/src/themes/SliderBase.css index a0fa98f168a5..93e78b29394f 100644 --- a/packages/main/src/themes/SliderBase.css +++ b/packages/main/src/themes/SliderBase.css @@ -1,270 +1,2 @@ @import "./InvisibleTextStyles.css"; -@import "./FormComponents.css"; - -:host([disabled]) { - opacity: var(--_ui5_slider_disabled_opacity); - cursor: default; - pointer-events: none; -} - -:host { - box-sizing: border-box; - cursor: pointer; - width: 100%; -} - -:host(:not([hidden])) { - display: inline-block; -} - -.ui5-slider-root { - box-sizing: border-box; - height: var(--_ui5_slider_root_height); - outline: none; - padding: var(--_ui5_slider_padding); - touch-action: none; -} - -.ui5-slider-inner { - background-repeat: no-repeat; - position: relative; - min-width: var(--_ui5_slider_inner_min_width); - height: 100%; -} - -.ui5-slider-progress-container { - width: 100%; - background: var(--_ui5_slider_progress_container_background); - border: var(--_ui5_slider_progress_border); - border-radius: var(--_ui5_slider_progress_border_radius); - height: var(--_ui5_slider_inner_height); - position: relative; - box-sizing: var(--_ui5_slider_progress_box_sizing); - top: var(--_ui5_slider_progress_container_top); -} - -.ui5-slider-progress-container::before, -.ui5-slider-progress-container::after { - display: var(--_ui5_slider_progress_container_dot_display); - content: ""; - position: absolute; - box-sizing: border-box; - border-radius: 50%; - width: var(--_ui5_slider_start_end_point_size); - height: var(--_ui5_slider_start_end_point_size); - top: var(--_ui5_slider_start_end_point_top); -} - -.ui5-slider-progress-container::before { - inset-inline-start: var(--_ui5_slider_start_end_point_left); - background-color: var(--_ui5_slider_progress_before_background); - border: var(--_ui5_slider_progress_before_border); -} - -.ui5-slider-progress-container::after { - inset-inline-end: var(--_ui5_slider_start_end_point_left); - background-color: var(--_ui5_slider_progress_after_background); - border: var(--_ui5_slider_progress_after_border); -} - -.ui5-slider-progress { - background: var(--_ui5_slider_progress_background); - border-radius: var(--_ui5_slider_active_progress_border_radius); - height: var(--_ui5_slider_active_progress_height); - position: absolute; - outline: none; - box-sizing: content-box; - border: var(--_ui5_slider_active_progress_border); - inset-inline-start: var(--_ui5_slider_active_progress_left); - top: var(--_ui5_slider_active_progress_top); -} - -.ui5-slider-tickmarks { - list-style: none; - padding: 0; - margin: 0; - top: var(--_ui5_slider_tickmark_top); - display: flex; - box-sizing: border-box; - width: 100%; - justify-content: space-between; - position: absolute; - z-index: 1; -} - -.ui5-slider-tickmarks li { - height: var(--_ui5_slider_tickmark_height); - border-inline-start: 0.0625rem solid var(--_ui5_slider_tickmark_bg); -} - -.ui5-slider-handle { - background: var(--_ui5_slider_handle_background); - border: var(--_ui5_slider_handle_border); - border-radius: var(--_ui5_slider_handle_border_radius); - position: relative; - outline: none; - height: var(--_ui5_slider_handle_height); - width: var(--_ui5_slider_handle_width); - box-sizing: var(--_ui5_slider_handle_box_sizing); - display: flex; - justify-content: center; - align-items: center; - z-index: 2; -} - -[slider-icon] { - display: var(--_ui5_slider_handle_icon_display); - color: var(--sapContent_Selected_ForegroundColor); - width: var(--_ui5_slider_handle_icon_size); - height: var(--_ui5_slider_handle_icon_size); -} - -.ui5-slider-root .ui5-slider-handle:focus [slider-icon] { - display: var(--_ui5_range_slider_active_handle_icon_display); -} - -.ui5-slider-progress-container:hover ~ .ui5-slider-handle:not(:focus), -.ui5-slider-handle:hover { - background: var(--_ui5_slider_handle_hover_background); - border: var(--_ui5_slider_handle_hover_border); -} - -.ui5-slider-root:focus .ui5-slider-inner .ui5-slider-handle, -.ui5-slider-handle:focus { - outline: var(--_ui5_slider_handle_outline); - outline-offset: var(--_ui5_slider_handle_outline_offset); - border: var(--_ui5_slider_handle_focus_border); - background: var(--_ui5_slider_handle_background_focus); -} - -.ui5-slider-handle.ui5-slider-handle--start:focus, -.ui5-slider-handle--end:focus { - border: var(--_ui5_slider_handle_focus_border); -} - -.ui5-slider-root:focus:hover .ui5-slider-handle, -.ui5-slider-handle:focus:hover { - border: var(--_ui5_slider_handle_focus_border); -} - -.ui5-slider-handle-container { - position: absolute; - margin-inline-start: calc(-1 * var(--_ui5_slider_handle_width) / 2); - top: var(--_ui5_slider_handle_top); -} - -:host(:not([hidden])) .ui5-slider-handle-container .ui5-slider-tooltip { - display: flex; - font-family: var(--sapFontFamily); - justify-content: center; - align-items: center; - visibility: hidden; - position: absolute; - left: 50%; - transform: translate(-50%); - bottom: var(--_ui5_slider_tooltip_bottom); - background: var(--_ui5_slider_tooltip_background); - border: var(--_ui5_slider_tooltip_border); - border-radius: var(--_ui5_slider_tooltip_border_radius); - box-shadow: var(--_ui5_slider_tooltip_box_shadow); - font-size: var(--_ui5_slider_tooltip_fontsize); - color: var(--_ui5_slider_tooltip_color); - height: var(--_ui5_slider_tooltip_height); - min-width: var(--_ui5_slider_tooltip_min_width); - padding: var(--_ui5_slider_tooltip_padding); - box-sizing: var(--_ui5_slider_tooltip_border_box); -} - -:host(:not([hidden])):host([editable-tooltip]) .ui5-slider-handle-container .ui5-slider-tooltip { - border: none; - background: none; - box-shadow: none; -} - -:host([editable-tooltip]) .ui5-slider-tooltip { - padding: 0; - box-shadow: none; -} - -.ui5-slider-tooltip [ui5-input] { - width: 100%; - text-align: center; -} - -.ui5-slider-tooltip-value { - position: relative; - display: flex; - justify-content: center; - align-items: center; -} - -.ui5-slider-labels { - position: absolute; - top: 1.25rem; - margin: 0; - padding: 0; - white-space: nowrap; - height: 1rem; - width: 100%; - display: flex; - justify-content: space-between; -} - -.ui5-slider-labels li { - position: relative; - list-style: none; - margin: 0; - text-align: center; - display: inline-block; - font-family: var(--sapFontFamily); - font-size: var(--_ui5_slider_label_fontsize); - padding-top: 0; - box-sizing: border-box; - width: 0.0625rem; - visibility: hidden; -} - -.ui5-slider-labels li::after { - content: attr(data-counter); - position: absolute; - top: 0; - visibility: visible; - display: inline-block; - width: 2rem; - color: var(--_ui5_slider_label_color); - transform: translateX(-50%); -} - -.ui5-slider-hidden-labels li:not(:first-child):not(:last-child)::after { - visibility: hidden; -} - -.ui5-slider-handle:focus .ui5-slider-tooltip { - bottom: var(--_ui5_slider_handle_focused_tooltip_distance); -} - -.ui5-slider-tickmarks li.ui5-slider-tickmark-in-range { - border-inline-start: 1px solid var(--_ui5_slider_tickmark_in_range_bg); -} - -:host([show-tickmarks]) .ui5-slider-progress { - height: var(--_ui5_slider_no_tickmarks_active_progress_height); - border: var(--_ui5_slider_no_tickmarks_active_progress_border); - inset-inline-start: var(--_ui5_slider_no_tickmarks_active_progress_left); - top: var(--_ui5_slider_no_tickmarks_active_progress_top); -} - -:host([show-tickmarks]) .ui5-slider-progress-container { - top: var(--_ui5_slider_no_tickmarks_progress_container_top); -} - -.ui5-slider-handle:focus:after { - content: ""; - display: var(--_ui5_slider_handle_focus_visibility); - width: calc(100% + (var(--sapContent_FocusWidth) * 2) + 2px); - height: calc(100% + (var(--sapContent_FocusWidth) * 2) + 2px); - border: var(--sapContent_FocusWidth) dotted var(--sapContent_FocusColor); - position: absolute; - border-radius: var(--_ui5_slider_handle_border_radius); - pointer-events: none; -} \ No newline at end of file +@import "./FormComponents.css"; \ No newline at end of file diff --git a/packages/main/src/themes/SliderScale.css b/packages/main/src/themes/SliderScale.css index 512563f6a8ba..0b6b0faae225 100644 --- a/packages/main/src/themes/SliderScale.css +++ b/packages/main/src/themes/SliderScale.css @@ -11,9 +11,6 @@ height: .25rem; top: 50%; transform: translateY(-50%); -} - -.ui5-slider-scale-root { box-sizing: var(--_ui5_slider_scale_root_box_sizing); border-radius: 0.25rem; width: 100%; @@ -66,6 +63,41 @@ border-radius: .25rem; } +/* Progress bar focus styling - used by RangeSlider for selected range */ +.ui5-slider-scale-progress:focus { + outline: none; +} + +.ui5-slider-scale-progress:focus::after, +.ui5-slider-scale-progress.ui5-slider-progress--focused::after { + border: 0.125rem solid var(--sapContent_FocusColor); + border-radius: 0.5rem; + content: ""; + display: var(--_ui5_range_slider_progress_focus_display); + position: absolute; + top: var(--_ui5_range_slider_progress_focus_top); + left: var(--_ui5_range_slider_progress_focus_left); + right: var(--_ui5_range_slider_progress_focus_right); + padding: var(--_ui5_range_slider_progress_focus_padding); + height: var(--_ui5_range_slider_progress_focus_height); + box-sizing: border-box; +} + +/* Legacy progress focus styling (for backward compatibility) */ +.ui5-slider-scale-progress:focus::before, +.ui5-slider-scale-progress.ui5-slider-progress--focused::before { + display: var(--_ui5_range_slider_legacy_progress_focus_display); + content: ''; + position: absolute; + width: var(--_ui5_range_slider_focus_outline_width); + border: var(--_ui5_slider_progress_outline); + border-radius: var(--_ui5_range_slider_focus_outline_radius); + top: var(--_ui5_slider_progress_outline_offset); + height: var(--_ui5_slider_outer_height); + box-sizing: border-box; + left: var(--_ui5_slider_progress_outline_offset_left); +} + .ui5-slider-scale-root::before { content: ""; position: absolute; diff --git a/packages/main/src/themes/base/SliderBase-parameters.css b/packages/main/src/themes/base/SliderBase-parameters.css index 8a39b0bce328..2a5834f561c6 100644 --- a/packages/main/src/themes/base/SliderBase-parameters.css +++ b/packages/main/src/themes/base/SliderBase-parameters.css @@ -1,106 +1,17 @@ :host { - --_ui5_slider_progress_container_background: var(--sapField_BorderColor); - --_ui5_slider_progress_container_dot_display: none; - --_ui5_slider_progress_container_dot_background: var(--sapField_BorderColor); - --_ui5_slider_progress_border_width: 0.0625rem; - --_ui5_slider_progress_border: solid var(--_ui5_slider_progress_border_width) var(--sapSlider_BorderColor); - --_ui5_slider_progress_before_background: transparent; - --_ui5_slider_progress_after_background: transparent; - --_ui5_slider_progress_before_border: none; - --_ui5_slider_progress_after_border: none; - --_ui5_slider_padding: 1.406rem 1.0625rem; - --_ui5_slider_root_height: 3.3125rem; - --_ui5_slider_inner_height: 0.25rem; - --_ui5_slider_inner_min_width: 4rem; - --_ui5_slider_outer_height: 1.6875rem; - --_ui5_slider_progress_border_radius: 0.25rem; - --_ui5_slider_progress_background: var(--sapActiveColor); - --_ui5_slider_handle_icon_display: none; - --_ui5_range_slider_root_hover_handle_icon_display: none; --_ui5_slider_handle_height: 1.5rem; --_ui5_slider_handle_width: 2rem; - --_ui5_slider_handle_border: 0.0625rem solid var(--sapField_BorderColor); - --_ui5_slider_handle_border_radius: 0.5rem; - --_ui5_slider_handle_background: var(--sapButton_Background); - --_ui5_range_slider_handle_background: #FFF; - --_ui5_slider_track_total_height: calc(var(--_ui5_slider_inner_height) + (2 * var(--_ui5_slider_progress_border_width))); - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2 - var(--_ui5_slider_progress_border_width)); - --_ui5_slider_tickmark_bg: var(--sapField_BorderColor); - --_ui5_slider_tickmark_in_range_bg: var(--sapButton_Active_Background); - --_ui5_slider_handle_hover_background: var(--sapButton_Hover_Background); - --_ui5_slider_handle_hover_border: 0.125rem solid var(--sapButton_Hover_BorderColor); - --_ui5_slider_handle_outline: 0.0625rem dotted var(--sapContent_FocusColor); - --_ui5_slider_handle_focus_border: var(--_ui5_slider_handle_hover_border); - --_ui5_slider_handle_outline_offset: 0.075rem; - --_ui5_slider_progress_outline: 0.0625rem dotted var(--sapContent_FocusColor); - --_ui5_slider_progress_outline_offset: -0.8125rem; - --_ui5_slider_tickmark_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_tickmark_height)) / 2 - var(--_ui5_slider_progress_border_width)); + --_ui5_slider_handle_focus_border: 0.125rem solid var(--sapButton_Hover_BorderColor); + --_ui5_slider_progress_border_width: 0.0625rem; --_ui5_slider_disabled_opacity: 0.4; - --_ui5_slider_tooltip_fontsize: var(--sapFontSmallSize); - --_ui5_slider_tooltip_color: var(--sapContent_LabelColor); - --_ui5_slider_tooltip_background: var(--sapField_Background); - --_ui5_slider_tooltip_border_radius: var(--sapElement_BorderCornerRadius); - --_ui5_slider_tooltip_border_color: var(--sapField_BorderColor); - --_ui5_slider_tooltip_border: 0.0625rem solid var(--_ui5_slider_tooltip_border_color); - --_ui5_slider_tooltip_box_shadow: none; - --_ui5_slider_tooltip_padding: 0.4125rem; - --_ui5_slider_tooltip_height: 1rem; - --_ui5_slider_tooltip_min_width: 2rem; - --_ui5_slider_tooltip_bottom: 2rem; - --_ui5_slider_label_fontsize: var(--sapFontSmallSize); - --_ui5_slider_label_color: var(--sapContent_LabelColor); - --_ui5_range_slider_progress_focus_display: none; - --_ui5_range_slider_progress_focus_top: -1.063rem; - --_ui5_range_slider_progress_focus_left: -1.438rem; - --_ui5_range_slider_progress_focus_padding: 0 1.375rem 0 1.438rem; - --_ui5_range_slider_progress_focus_height: 2rem; - --_ui5_range_slider_legacy_progress_focus_display: block; - --_ui5_slider_handle_focus_width: 0; - --_ui5_slider_start_end_point_size: 0.5rem; - --_ui5_slider_start_end_point_left: -.95rem; - --_ui5_slider_start_end_point_top: -0.1875rem; - --_ui5_slider_handle_background_focus: var(--sapButton_Active_Background); - --_ui5_slider_handle_focused_tooltip_distance: var(--_ui5_slider_tooltip_bottom); - --_ui5_slider_handle_box_sizing: content-box; - --_ui5_slider_tooltip_border_box: content-box; + --_ui5_range_slider_handle_background: #FFF; + --_ui5_range_slider_root_hover_handle_bg: var(--sapButton_Hover_Background); --_ui5_range_slider_handle_active_background: var(--_ui5_range_slider_handle_background); - --_ui5_range_slider_active_handle_icon_display: none; - --_ui5_range_slider_handle_background_focus: transparent; - --_ui5_range_slider_progress_focus_width: 100%; - --_ui5_range_slider_root_active_handle_icon_display: none; - --_ui5_slider_tickmark_height: 0.5rem; - --_ui5_slider_progress_box_sizing: border-box; - --_ui5_slider_active_progress_box_sizing: content-box; - --_ui5_range_slider_focus_outline_width: 100%; - --_ui5_slider_progress_outline_offset_left: 0; - --_ui5_range_slider_focus_outline_radius: 0; - - --_ui5_slider_progress_container_top: 0; - --_ui5_slider_progress_height: 0.25rem; - --_ui5_slider_active_progress_border: solid 0.0625rem var(--sapSlider_Selected_BorderColor); - --_ui5_slider_active_progress_border_radius: 0.25rem; - --_ui5_slider_active_progress_left: -0.0625rem; - --_ui5_slider_active_progress_top: -0.0625rem; - --_ui5_slider_active_progress_padding: 0.125rem; - --_ui5_slider_active_progress_height: calc(var(--_ui5_slider_progress_height) - 0.125rem); - - --_ui5_slider_no_tickmarks_progress_container_top: var(--_ui5_slider_progress_container_top); - --_ui5_slider_no_tickmarks_progress_height: var(--_ui5_slider_progress_height); - --_ui5_slider_no_tickmarks_active_progress_border: var(--_ui5_slider_active_progress_border); - --_ui5_slider_no_tickmarks_active_progress_left: -0.0625rem; - --_ui5_slider_no_tickmarks_active_progress_top: -0.0625rem; - --_ui5_slider_no_tickmarks_active_progress_height: calc(var(--_ui5_slider_no_tickmarks_progress_height) - 0.125rem); - --_ui5_slider_handle_focus_visibility: none; - --_ui5_slider_handle_icon_size: 0.875rem; } @container style(--ui5_content_density: compact) { :host { - --_ui5_slider_start_end_point_left: -0.75rem; - --_ui5_slider_handle_icon_size: 0.875rem; - --_ui5_slider_padding: 1rem 1.0625rem; --_ui5_slider_handle_height: 1.25rem; --_ui5_slider_handle_width: 1.5rem; - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2 - var(--_ui5_slider_progress_border_width)); } -} \ No newline at end of file +} diff --git a/packages/main/src/themes/base/SliderHandle-parameters.css b/packages/main/src/themes/base/SliderHandle-parameters.css index 01db4f5ed0d6..bb67ef849be1 100644 --- a/packages/main/src/themes/base/SliderHandle-parameters.css +++ b/packages/main/src/themes/base/SliderHandle-parameters.css @@ -1,3 +1,19 @@ :host { --ui5_slider_handle_outline: var(--sapContent_FocusWidth) dotted var(--sapContent_FocusColor); -} \ No newline at end of file + --ui5_slider_handle_outline_offset: 0.075rem; + --_ui5_slider_handle_background: var(--sapButton_Background); + --_ui5_slider_handle_border: 0.0625rem solid var(--sapField_BorderColor); + --_ui5_slider_handle_border_radius: 0.5rem; + --_ui5_slider_handle_box_sizing: content-box; + --_ui5_slider_handle_hover_background: var(--sapButton_Hover_Background); + --_ui5_slider_handle_hover_border: 0.125rem solid var(--sapButton_Hover_BorderColor); + --_ui5_slider_handle_background_focus: var(--sapButton_Active_Background); + --_ui5_slider_handle_icon_display: none; + --_ui5_slider_handle_icon_size: 0.875rem; +} + +@container style(--ui5_content_density: compact) { + :host { + --_ui5_slider_handle_icon_size: 0.875rem; + } +} diff --git a/packages/main/src/themes/base/SliderScale-parameters.css b/packages/main/src/themes/base/SliderScale-parameters.css index 8b6c21a396c3..279282229df9 100644 --- a/packages/main/src/themes/base/SliderScale-parameters.css +++ b/packages/main/src/themes/base/SliderScale-parameters.css @@ -1,9 +1,26 @@ :host { --ui5_slider_scale_background: var(--sapSlider_Background); --_ui5_slider_scale_border: var(--sapSlider_Background); - --_ui5_slider_scale_dots_distance: -1rem; + --_ui5_slider_scale_dots_display: none; --_ui5_slider_scale_tickmark_height: .5rem; + --_ui5_slider_scale_root_box_sizing: border-box; + --_ui5_slider_scale_progress_top: 0; + --_ui5_slider_scale_progress_height: 100%; + --_ui5_slider_scale_progress_border: none; + --_ui5_range_slider_progress_focus_display: none; + --_ui5_range_slider_progress_focus_top: -1.063rem; + --_ui5_range_slider_progress_focus_left: -1.438rem; + --_ui5_range_slider_progress_focus_right: -1.438rem; + --_ui5_range_slider_progress_focus_padding: 0 1.375rem 0 1.438rem; + --_ui5_range_slider_progress_focus_height: 2rem; + --_ui5_range_slider_legacy_progress_focus_display: block; + --_ui5_range_slider_focus_outline_width: 100%; + --_ui5_slider_progress_outline: 0.0625rem dotted var(--sapContent_FocusColor); + --_ui5_range_slider_focus_outline_radius: 0; + --_ui5_slider_progress_outline_offset: -0.8125rem; + --_ui5_slider_outer_height: 1.6875rem; + --_ui5_slider_progress_outline_offset_left: 0; } @container style(--ui5_content_density: compact) { diff --git a/packages/main/src/themes/sap_fiori_3/SliderBase-parameters.css b/packages/main/src/themes/sap_fiori_3/SliderBase-parameters.css index 2b6f414c777d..c94ae36143d1 100644 --- a/packages/main/src/themes/sap_fiori_3/SliderBase-parameters.css +++ b/packages/main/src/themes/sap_fiori_3/SliderBase-parameters.css @@ -1,31 +1,16 @@ @import "../base/SliderBase-parameters.css"; :host { - --_ui5_slider_inner_min_width: 4rem; - --_ui5_range_slider_handle_background_focus: transparent; - --_ui5_slider_track_total_height: var(--_ui5_slider_inner_height); - --_ui5_range_slider_handle_background: transparent; - --_ui5_range_slider_handle_active_background: transparent; - --_ui5_slider_handle_background: var(--sapButton_Background); - --_ui5_slider_handle_hover_background: var(--sapButton_Hover_Background); - --_ui5_range_slider_root_hover_handle_bg: transparent; - --_ui5_range_slider_root_active_handle_icon_display: none; --_ui5_slider_handle_width: 1.875rem; --_ui5_slider_handle_height: 1.875rem; - --_ui5_slider_handle_border: 0.125rem solid var(--sapField_BorderColor); - --_ui5_slider_handle_border_radius: 1rem; - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2); - --_ui5_slider_handle_box_sizing: border-box; - --_ui5_slider_tickmark_height: 1rem; - --_ui5_slider_tickmark_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_tickmark_height)) / 2); + --_ui5_range_slider_handle_background: transparent; + --_ui5_range_slider_root_hover_handle_bg: transparent; + --_ui5_range_slider_handle_active_background: transparent; } @container style(--ui5_content_density: compact) { :host { --_ui5_slider_handle_width: 1.5rem; --_ui5_slider_handle_height: 1.5rem; - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2); - --_ui5_slider_tickmark_height: 0.75rem; - --_ui5_slider_tickmark_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_tickmark_height)) / 2); } } \ No newline at end of file diff --git a/packages/main/src/themes/sap_fiori_3/SliderHandle-parameters.css b/packages/main/src/themes/sap_fiori_3/SliderHandle-parameters.css index 56f9dcbcbc4b..90aff73df3c4 100644 --- a/packages/main/src/themes/sap_fiori_3/SliderHandle-parameters.css +++ b/packages/main/src/themes/sap_fiori_3/SliderHandle-parameters.css @@ -2,4 +2,9 @@ :host { --ui5_slider_handle_outline_offset: 1px; -} \ No newline at end of file + --_ui5_slider_handle_background: var(--sapButton_Background); + --_ui5_slider_handle_border: 0.125rem solid var(--sapField_BorderColor); + --_ui5_slider_handle_border_radius: 1rem; + --_ui5_slider_handle_box_sizing: border-box; + --_ui5_slider_handle_hover_background: var(--sapButton_Hover_Background); +} diff --git a/packages/main/src/themes/sap_fiori_3/SliderScale-parameters.css b/packages/main/src/themes/sap_fiori_3/SliderScale-parameters.css index e85661513ba8..58a9549b244d 100644 --- a/packages/main/src/themes/sap_fiori_3/SliderScale-parameters.css +++ b/packages/main/src/themes/sap_fiori_3/SliderScale-parameters.css @@ -10,4 +10,15 @@ /* Fiori 3 specific */ --_ui5_slider_scale_dots_display: none; --_ui5_slider_scale_tickmark_height: 1rem; + + /* Handle dimensions for focus calculations */ + --_ui5_slider_handle_width: 1.875rem; + --_ui5_slider_handle_height: 1.875rem; +} + +@container style(--ui5_content_density: compact) { + :host { + --_ui5_slider_handle_width: 1.5rem; + --_ui5_slider_handle_height: 1.5rem; + } } \ No newline at end of file diff --git a/packages/main/src/themes/sap_fiori_3_dark/SliderBase-parameters.css b/packages/main/src/themes/sap_fiori_3_dark/SliderBase-parameters.css index aff8d3347e6b..0debb89439c5 100644 --- a/packages/main/src/themes/sap_fiori_3_dark/SliderBase-parameters.css +++ b/packages/main/src/themes/sap_fiori_3_dark/SliderBase-parameters.css @@ -1,26 +1,15 @@ @import "../base/SliderBase-parameters.css"; :host { - --_ui5_slider_inner_min_width: 4rem; - --_ui5_slider_track_total_height: var(--_ui5_slider_inner_height); - --_ui5_range_slider_handle_background: transparent; - --_ui5_range_slider_root_hover_handle_bg: transparent; --_ui5_slider_handle_width: 1.875rem; --_ui5_slider_handle_height: 1.875rem; - --_ui5_slider_handle_border: 0.125rem solid var(--sapField_BorderColor); - --_ui5_slider_handle_border_radius: 1rem; - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2); - --_ui5_slider_handle_box_sizing: border-box; - --_ui5_slider_tickmark_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_tickmark_height)) / 2); - --_ui5_slider_tickmark_height: 1rem; + --_ui5_range_slider_handle_background: transparent; + --_ui5_range_slider_root_hover_handle_bg: transparent; } @container style(--ui5_content_density: compact) { :host { --_ui5_slider_handle_width: 1.5rem; --_ui5_slider_handle_height: 1.5rem; - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2); - --_ui5_slider_tickmark_height: 0.75rem; - --_ui5_slider_tickmark_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_tickmark_height)) / 2); } } \ No newline at end of file diff --git a/packages/main/src/themes/sap_fiori_3_dark/SliderHandle-parameters.css b/packages/main/src/themes/sap_fiori_3_dark/SliderHandle-parameters.css index 56f9dcbcbc4b..1686933fe8fb 100644 --- a/packages/main/src/themes/sap_fiori_3_dark/SliderHandle-parameters.css +++ b/packages/main/src/themes/sap_fiori_3_dark/SliderHandle-parameters.css @@ -2,4 +2,7 @@ :host { --ui5_slider_handle_outline_offset: 1px; -} \ No newline at end of file + --_ui5_slider_handle_border: 0.125rem solid var(--sapField_BorderColor); + --_ui5_slider_handle_border_radius: 1rem; + --_ui5_slider_handle_box_sizing: border-box; +} diff --git a/packages/main/src/themes/sap_fiori_3_dark/SliderScale-parameters.css b/packages/main/src/themes/sap_fiori_3_dark/SliderScale-parameters.css index e85661513ba8..58a9549b244d 100644 --- a/packages/main/src/themes/sap_fiori_3_dark/SliderScale-parameters.css +++ b/packages/main/src/themes/sap_fiori_3_dark/SliderScale-parameters.css @@ -10,4 +10,15 @@ /* Fiori 3 specific */ --_ui5_slider_scale_dots_display: none; --_ui5_slider_scale_tickmark_height: 1rem; + + /* Handle dimensions for focus calculations */ + --_ui5_slider_handle_width: 1.875rem; + --_ui5_slider_handle_height: 1.875rem; +} + +@container style(--ui5_content_density: compact) { + :host { + --_ui5_slider_handle_width: 1.5rem; + --_ui5_slider_handle_height: 1.5rem; + } } \ No newline at end of file diff --git a/packages/main/src/themes/sap_fiori_3_hcb/SliderBase-parameters.css b/packages/main/src/themes/sap_fiori_3_hcb/SliderBase-parameters.css index bcd7923ee89d..c00d66aed473 100644 --- a/packages/main/src/themes/sap_fiori_3_hcb/SliderBase-parameters.css +++ b/packages/main/src/themes/sap_fiori_3_hcb/SliderBase-parameters.css @@ -1,39 +1,14 @@ @import "../base/SliderBase-parameters.css"; :host { - --_ui5_slider_inner_height: 0.375rem; /* Total height including border */ - --_ui5_slider_track_total_height: var(--_ui5_slider_inner_height); - --_ui5_slider_progress_box_sizing: border-box; - --_ui5_slider_progress_border: solid 0.0625rem var(--sapField_BorderColor); - --_ui5_slider_progress_border_radius: 0.375rem; - --_ui5_range_slider_handle_background: transparent; - --_ui5_slider_handle_hover_background: var(--sapButton_Hover_Background); --_ui5_slider_handle_width: 1.875rem; --_ui5_slider_handle_height: 1.875rem; - --_ui5_slider_handle_border: 0.125rem solid var(--sapField_BorderColor); - --_ui5_slider_handle_border_radius: 1rem; - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2); - --_ui5_slider_handle_box_sizing: border-box; - --_ui5_slider_progress_background: var(--sapSelectedColor); - --_ui5_slider_tickmark_height: 1rem; - --_ui5_slider_tickmark_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_tickmark_height)) / 2); - --_ui5_slider_active_progress_border: none; - --_ui5_slider_active_progress_left: 0rem; - --_ui5_slider_active_progress_top: 0; - --_ui5_slider_active_progress_height: var(--_ui5_slider_progress_height); - --_ui5_slider_no_tickmarks_active_progress_border: none; - --_ui5_slider_no_tickmarks_active_progress_left: 0; - --_ui5_slider_no_tickmarks_active_progress_top: 0; - --_ui5_slider_no_tickmarks_active_progress_height: var(--_ui5_slider_no_tickmarks_progress_height); + --_ui5_range_slider_handle_background: transparent; } @container style(--ui5_content_density: compact) { :host { --_ui5_slider_handle_width: 1.5rem; --_ui5_slider_handle_height: 1.5rem; - --_ui5_slider_handle_border_radius: 1rem; - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2); - --_ui5_slider_tickmark_height: 0.75rem; - --_ui5_slider_tickmark_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_tickmark_height)) / 2); } } \ No newline at end of file diff --git a/packages/main/src/themes/sap_fiori_3_hcb/SliderHandle-parameters.css b/packages/main/src/themes/sap_fiori_3_hcb/SliderHandle-parameters.css index 56f9dcbcbc4b..6d0a434fce7e 100644 --- a/packages/main/src/themes/sap_fiori_3_hcb/SliderHandle-parameters.css +++ b/packages/main/src/themes/sap_fiori_3_hcb/SliderHandle-parameters.css @@ -2,4 +2,8 @@ :host { --ui5_slider_handle_outline_offset: 1px; -} \ No newline at end of file + --_ui5_slider_handle_border: 0.125rem solid var(--sapField_BorderColor); + --_ui5_slider_handle_border_radius: 1rem; + --_ui5_slider_handle_box_sizing: border-box; + --_ui5_slider_handle_hover_background: var(--sapButton_Hover_Background); +} diff --git a/packages/main/src/themes/sap_fiori_3_hcb/SliderScale-parameters.css b/packages/main/src/themes/sap_fiori_3_hcb/SliderScale-parameters.css index 334bac136b1d..fb8ffe623b62 100644 --- a/packages/main/src/themes/sap_fiori_3_hcb/SliderScale-parameters.css +++ b/packages/main/src/themes/sap_fiori_3_hcb/SliderScale-parameters.css @@ -11,4 +11,15 @@ /* Fiori 3 specific */ --_ui5_slider_scale_dots_display: none; --_ui5_slider_scale_tickmark_height: 1rem; + + /* Handle dimensions for focus calculations */ + --_ui5_slider_handle_width: 1.875rem; + --_ui5_slider_handle_height: 1.875rem; +} + +@container style(--ui5_content_density: compact) { + :host { + --_ui5_slider_handle_width: 1.5rem; + --_ui5_slider_handle_height: 1.5rem; + } } \ No newline at end of file diff --git a/packages/main/src/themes/sap_fiori_3_hcw/SliderBase-parameters.css b/packages/main/src/themes/sap_fiori_3_hcw/SliderBase-parameters.css index ea2b0f11ee6b..c00d66aed473 100644 --- a/packages/main/src/themes/sap_fiori_3_hcw/SliderBase-parameters.css +++ b/packages/main/src/themes/sap_fiori_3_hcw/SliderBase-parameters.css @@ -1,37 +1,14 @@ @import "../base/SliderBase-parameters.css"; :host { - --_ui5_slider_inner_height: 0.375rem; /* Total height including border */ - --_ui5_slider_track_total_height: var(--_ui5_slider_inner_height); - --_ui5_slider_progress_box_sizing: border-box; - --_ui5_slider_progress_border: solid 0.0625rem var(--sapField_BorderColor); - --_ui5_slider_progress_border_radius: 0.375rem; - --_ui5_range_slider_handle_background: transparent; --_ui5_slider_handle_width: 1.875rem; --_ui5_slider_handle_height: 1.875rem; - --_ui5_slider_handle_border: 0.125rem solid var(--sapField_BorderColor); - --_ui5_slider_handle_border_radius: 1rem; - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2); - --_ui5_slider_handle_box_sizing: border-box; - --_ui5_slider_progress_background: var(--sapSelectedColor); - --_ui5_slider_tickmark_height: 1rem; - --_ui5_slider_tickmark_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_tickmark_height)) / 2); - --_ui5_slider_active_progress_border: none; - --_ui5_slider_active_progress_left: 0rem; - --_ui5_slider_active_progress_top: 0; - --_ui5_slider_active_progress_height: var(--_ui5_slider_progress_height); - --_ui5_slider_no_tickmarks_active_progress_border: none; - --_ui5_slider_no_tickmarks_active_progress_left: 0; - --_ui5_slider_no_tickmarks_active_progress_top: 0; - --_ui5_slider_no_tickmarks_active_progress_height: var(--_ui5_slider_no_tickmarks_progress_height); + --_ui5_range_slider_handle_background: transparent; } @container style(--ui5_content_density: compact) { :host { --_ui5_slider_handle_width: 1.5rem; --_ui5_slider_handle_height: 1.5rem; - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2); - --_ui5_slider_tickmark_height: 0.75rem; - --_ui5_slider_tickmark_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_tickmark_height)) / 2); } } \ No newline at end of file diff --git a/packages/main/src/themes/sap_fiori_3_hcw/SliderHandle-parameters.css b/packages/main/src/themes/sap_fiori_3_hcw/SliderHandle-parameters.css index 56f9dcbcbc4b..1686933fe8fb 100644 --- a/packages/main/src/themes/sap_fiori_3_hcw/SliderHandle-parameters.css +++ b/packages/main/src/themes/sap_fiori_3_hcw/SliderHandle-parameters.css @@ -2,4 +2,7 @@ :host { --ui5_slider_handle_outline_offset: 1px; -} \ No newline at end of file + --_ui5_slider_handle_border: 0.125rem solid var(--sapField_BorderColor); + --_ui5_slider_handle_border_radius: 1rem; + --_ui5_slider_handle_box_sizing: border-box; +} diff --git a/packages/main/src/themes/sap_fiori_3_hcw/SliderScale-parameters.css b/packages/main/src/themes/sap_fiori_3_hcw/SliderScale-parameters.css index 334bac136b1d..fb8ffe623b62 100644 --- a/packages/main/src/themes/sap_fiori_3_hcw/SliderScale-parameters.css +++ b/packages/main/src/themes/sap_fiori_3_hcw/SliderScale-parameters.css @@ -11,4 +11,15 @@ /* Fiori 3 specific */ --_ui5_slider_scale_dots_display: none; --_ui5_slider_scale_tickmark_height: 1rem; + + /* Handle dimensions for focus calculations */ + --_ui5_slider_handle_width: 1.875rem; + --_ui5_slider_handle_height: 1.875rem; +} + +@container style(--ui5_content_density: compact) { + :host { + --_ui5_slider_handle_width: 1.5rem; + --_ui5_slider_handle_height: 1.5rem; + } } \ No newline at end of file diff --git a/packages/main/src/themes/sap_horizon/SliderBase-parameters.css b/packages/main/src/themes/sap_horizon/SliderBase-parameters.css index 777d1a94eddc..e48fe76d4dd1 100644 --- a/packages/main/src/themes/sap_horizon/SliderBase-parameters.css +++ b/packages/main/src/themes/sap_horizon/SliderBase-parameters.css @@ -1,50 +1,8 @@ @import "../base/SliderBase-parameters.css"; :host { - --_ui5_slider_progress_container_background: var(--sapSlider_Background); - --_ui5_slider_progress_container_dot_display: block; - --_ui5_slider_progress_background: var(--sapSlider_Selected_Background); - --_ui5_slider_progress_before_background: var(--sapSlider_Selected_Background); - --_ui5_slider_progress_after_background: var(--sapContent_MeasureIndicatorColor); - --_ui5_slider_handle_background: var(--sapSlider_HandleBackground); - --_ui5_slider_handle_icon_display: inline-block; - --_ui5_slider_handle_border: 0.0625rem solid var(--sapSlider_HandleBorderColor); - --_ui5_slider_handle_border_radius: 0.5rem; - --_ui5_slider_handle_font_family: "SAP-icons"; - --_ui5_slider_handle_hover_border: 0.0625rem solid var(--sapSlider_Hover_HandleBorderColor); --_ui5_slider_handle_focus_border: 0.125rem solid var(--sapContent_FocusColor); - --_ui5_slider_handle_background_focus: var(--sapSlider_Active_RangeHandleBackground); - --_ui5_slider_handle_outline: none; - --_ui5_slider_handle_hover_background: var(--sapSlider_Hover_HandleBackground); - --_ui5_slider_tooltip_background: var(--sapField_Focus_Background); - --_ui5_slider_tooltip_border: none; - --_ui5_slider_tooltip_border_radius: 0.5rem; - --_ui5_slider_tooltip_box_shadow: var(--sapContent_Shadow1); - --_ui5_range_slider_legacy_progress_focus_display: none; - --_ui5_range_slider_progress_focus_display: block; - --_ui5_slider_tickmark_in_range_bg: var(--sapSlider_Selected_BorderColor); - --_ui5_slider_tooltip_padding: 0.25rem; - --_ui5_slider_tooltip_height: 1.375rem; - --_ui5_slider_handle_focus_width: 1px; - --_ui5_slider_handle_focused_tooltip_distance: calc(var(--_ui5_slider_tooltip_bottom) - var(--_ui5_slider_handle_focus_width)); - --_ui5_slider_tooltip_border_box: border-box; - --_ui5_range_slider_handle_active_background: var(--sapSlider_Active_RangeHandleBackground); - --_ui5_range_slider_active_handle_icon_display: none; - --_ui5_range_slider_progress_focus_height: calc(var(--_ui5_slider_handle_height) + 0.375rem); - --_ui5_range_slider_progress_focus_top: calc(-1 * ((var(--_ui5_slider_handle_height) / 2) + 0.1875rem) + var(--_ui5_slider_progress_border_width)); - --_ui5_range_slider_progress_focus_left: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); - --_ui5_range_slider_progress_focus_right: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); - --_ui5_range_slider_progress_focus_padding: 0 1rem 0 1rem; - --_ui5_range_slider_root_hover_handle_icon_display: inline-block; - --_ui5_range_slider_root_hover_handle_bg: var(--_ui5_slider_handle_hover_background); - --_ui5_range_slider_root_active_handle_icon_display: none; - --_ui5_slider_handle_box_sizing: border-box; --_ui5_range_slider_handle_background: var(--sapSlider_RangeHandleBackground); + --_ui5_range_slider_root_hover_handle_bg: var(--sapSlider_Hover_HandleBackground); + --_ui5_range_slider_handle_active_background: var(--sapSlider_Active_RangeHandleBackground); } - -@container style(--ui5_content_density: compact) { - :host { - --_ui5_slider_tooltip_bottom: 1.75rem; - --_ui5_slider_handle_focused_tooltip_distance: calc(var(--_ui5_slider_tooltip_bottom) - var(--_ui5_slider_handle_focus_width)); - } -} \ No newline at end of file diff --git a/packages/main/src/themes/sap_horizon/SliderHandle-parameters.css b/packages/main/src/themes/sap_horizon/SliderHandle-parameters.css index 721230c3be3a..42491e39adbc 100644 --- a/packages/main/src/themes/sap_horizon/SliderHandle-parameters.css +++ b/packages/main/src/themes/sap_horizon/SliderHandle-parameters.css @@ -2,4 +2,12 @@ :host { --ui5_slider_handle_outline: none; -} \ No newline at end of file + --_ui5_slider_handle_background: var(--sapSlider_HandleBackground); + --_ui5_slider_handle_border: 0.0625rem solid var(--sapSlider_HandleBorderColor); + --_ui5_slider_handle_border_radius: 0.5rem; + --_ui5_slider_handle_box_sizing: border-box; + --_ui5_slider_handle_hover_background: var(--sapSlider_Hover_HandleBackground); + --_ui5_slider_handle_hover_border: 0.0625rem solid var(--sapSlider_Hover_HandleBorderColor); + --_ui5_slider_handle_background_focus: var(--sapSlider_Active_RangeHandleBackground); + --_ui5_slider_handle_icon_display: inline-block; +} diff --git a/packages/main/src/themes/sap_horizon/SliderScale-parameters.css b/packages/main/src/themes/sap_horizon/SliderScale-parameters.css index 387c75be922f..3d6dd6c568c9 100644 --- a/packages/main/src/themes/sap_horizon/SliderScale-parameters.css +++ b/packages/main/src/themes/sap_horizon/SliderScale-parameters.css @@ -7,4 +7,16 @@ --_ui5_slider_scale_progress_height: 100%; --_ui5_slider_scale_progress_top: 0; --_ui5_slider_scale_dots_display: inline-block; + + /* Progress bar focus styling - Horizon theme overrides */ + --_ui5_range_slider_legacy_progress_focus_display: none; + --_ui5_range_slider_progress_focus_display: block; + --_ui5_slider_handle_height: 1.5rem; + --_ui5_slider_handle_width: 2rem; + --_ui5_slider_progress_border_width: 0.0625rem; + --_ui5_range_slider_progress_focus_height: calc(var(--_ui5_slider_handle_height) + 0.375rem); + --_ui5_range_slider_progress_focus_top: calc(-1 * ((var(--_ui5_slider_handle_height) / 2) + 0.1875rem) + var(--_ui5_slider_progress_border_width) + 0.0625rem); + --_ui5_range_slider_progress_focus_left: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); + --_ui5_range_slider_progress_focus_right: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); + --_ui5_range_slider_progress_focus_padding: 0 1rem 0 1rem; } \ No newline at end of file diff --git a/packages/main/src/themes/sap_horizon_dark/SliderBase-parameters.css b/packages/main/src/themes/sap_horizon_dark/SliderBase-parameters.css index 777d1a94eddc..ed1d35df21f8 100644 --- a/packages/main/src/themes/sap_horizon_dark/SliderBase-parameters.css +++ b/packages/main/src/themes/sap_horizon_dark/SliderBase-parameters.css @@ -1,50 +1,8 @@ @import "../base/SliderBase-parameters.css"; :host { - --_ui5_slider_progress_container_background: var(--sapSlider_Background); - --_ui5_slider_progress_container_dot_display: block; - --_ui5_slider_progress_background: var(--sapSlider_Selected_Background); - --_ui5_slider_progress_before_background: var(--sapSlider_Selected_Background); - --_ui5_slider_progress_after_background: var(--sapContent_MeasureIndicatorColor); - --_ui5_slider_handle_background: var(--sapSlider_HandleBackground); - --_ui5_slider_handle_icon_display: inline-block; - --_ui5_slider_handle_border: 0.0625rem solid var(--sapSlider_HandleBorderColor); - --_ui5_slider_handle_border_radius: 0.5rem; - --_ui5_slider_handle_font_family: "SAP-icons"; - --_ui5_slider_handle_hover_border: 0.0625rem solid var(--sapSlider_Hover_HandleBorderColor); --_ui5_slider_handle_focus_border: 0.125rem solid var(--sapContent_FocusColor); - --_ui5_slider_handle_background_focus: var(--sapSlider_Active_RangeHandleBackground); - --_ui5_slider_handle_outline: none; - --_ui5_slider_handle_hover_background: var(--sapSlider_Hover_HandleBackground); - --_ui5_slider_tooltip_background: var(--sapField_Focus_Background); - --_ui5_slider_tooltip_border: none; - --_ui5_slider_tooltip_border_radius: 0.5rem; - --_ui5_slider_tooltip_box_shadow: var(--sapContent_Shadow1); - --_ui5_range_slider_legacy_progress_focus_display: none; - --_ui5_range_slider_progress_focus_display: block; - --_ui5_slider_tickmark_in_range_bg: var(--sapSlider_Selected_BorderColor); - --_ui5_slider_tooltip_padding: 0.25rem; - --_ui5_slider_tooltip_height: 1.375rem; - --_ui5_slider_handle_focus_width: 1px; - --_ui5_slider_handle_focused_tooltip_distance: calc(var(--_ui5_slider_tooltip_bottom) - var(--_ui5_slider_handle_focus_width)); - --_ui5_slider_tooltip_border_box: border-box; - --_ui5_range_slider_handle_active_background: var(--sapSlider_Active_RangeHandleBackground); - --_ui5_range_slider_active_handle_icon_display: none; - --_ui5_range_slider_progress_focus_height: calc(var(--_ui5_slider_handle_height) + 0.375rem); - --_ui5_range_slider_progress_focus_top: calc(-1 * ((var(--_ui5_slider_handle_height) / 2) + 0.1875rem) + var(--_ui5_slider_progress_border_width)); - --_ui5_range_slider_progress_focus_left: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); - --_ui5_range_slider_progress_focus_right: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); - --_ui5_range_slider_progress_focus_padding: 0 1rem 0 1rem; - --_ui5_range_slider_root_hover_handle_icon_display: inline-block; - --_ui5_range_slider_root_hover_handle_bg: var(--_ui5_slider_handle_hover_background); - --_ui5_range_slider_root_active_handle_icon_display: none; - --_ui5_slider_handle_box_sizing: border-box; --_ui5_range_slider_handle_background: var(--sapSlider_RangeHandleBackground); -} - -@container style(--ui5_content_density: compact) { - :host { - --_ui5_slider_tooltip_bottom: 1.75rem; - --_ui5_slider_handle_focused_tooltip_distance: calc(var(--_ui5_slider_tooltip_bottom) - var(--_ui5_slider_handle_focus_width)); - } + --_ui5_range_slider_root_hover_handle_bg: var(--sapSlider_Hover_HandleBackground); + --_ui5_range_slider_handle_active_background: var(--sapSlider_Active_RangeHandleBackground); } \ No newline at end of file diff --git a/packages/main/src/themes/sap_horizon_dark/SliderHandle-parameters.css b/packages/main/src/themes/sap_horizon_dark/SliderHandle-parameters.css index 721230c3be3a..42491e39adbc 100644 --- a/packages/main/src/themes/sap_horizon_dark/SliderHandle-parameters.css +++ b/packages/main/src/themes/sap_horizon_dark/SliderHandle-parameters.css @@ -2,4 +2,12 @@ :host { --ui5_slider_handle_outline: none; -} \ No newline at end of file + --_ui5_slider_handle_background: var(--sapSlider_HandleBackground); + --_ui5_slider_handle_border: 0.0625rem solid var(--sapSlider_HandleBorderColor); + --_ui5_slider_handle_border_radius: 0.5rem; + --_ui5_slider_handle_box_sizing: border-box; + --_ui5_slider_handle_hover_background: var(--sapSlider_Hover_HandleBackground); + --_ui5_slider_handle_hover_border: 0.0625rem solid var(--sapSlider_Hover_HandleBorderColor); + --_ui5_slider_handle_background_focus: var(--sapSlider_Active_RangeHandleBackground); + --_ui5_slider_handle_icon_display: inline-block; +} diff --git a/packages/main/src/themes/sap_horizon_dark/SliderScale-parameters.css b/packages/main/src/themes/sap_horizon_dark/SliderScale-parameters.css index 387c75be922f..00af9c84f2b2 100644 --- a/packages/main/src/themes/sap_horizon_dark/SliderScale-parameters.css +++ b/packages/main/src/themes/sap_horizon_dark/SliderScale-parameters.css @@ -7,4 +7,16 @@ --_ui5_slider_scale_progress_height: 100%; --_ui5_slider_scale_progress_top: 0; --_ui5_slider_scale_dots_display: inline-block; + + /* Progress bar focus styling - Horizon Dark theme overrides */ + --_ui5_range_slider_legacy_progress_focus_display: none; + --_ui5_range_slider_progress_focus_display: block; + --_ui5_slider_handle_height: 1.5rem; + --_ui5_slider_handle_width: 2rem; + --_ui5_slider_progress_border_width: 0.0625rem; + --_ui5_range_slider_progress_focus_height: calc(var(--_ui5_slider_handle_height) + 0.375rem); + --_ui5_range_slider_progress_focus_top: calc(-1 * ((var(--_ui5_slider_handle_height) / 2) + 0.1875rem) + var(--_ui5_slider_progress_border_width) + 0.0625rem); + --_ui5_range_slider_progress_focus_left: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); + --_ui5_range_slider_progress_focus_right: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); + --_ui5_range_slider_progress_focus_padding: 0 1rem 0 1rem; } \ No newline at end of file diff --git a/packages/main/src/themes/sap_horizon_hcb/SliderBase-parameters.css b/packages/main/src/themes/sap_horizon_hcb/SliderBase-parameters.css index 7319cb6902b5..a6243ac2625e 100644 --- a/packages/main/src/themes/sap_horizon_hcb/SliderBase-parameters.css +++ b/packages/main/src/themes/sap_horizon_hcb/SliderBase-parameters.css @@ -1,71 +1,8 @@ @import "../base/SliderBase-parameters.css"; :host { - /* handle */ - --_ui5_slider_handle_icon_display: inline-block; - --_ui5_range_slider_root_hover_handle_icon_display: inline-block; - --_ui5_slider_handle_hover_border: var(--_ui5_slider_handle_border); - --_ui5_slider_handle_background_focus: var(--sapSlider_Active_RangeHandleBackground); --_ui5_slider_handle_focus_border: 0.125rem solid var(--sapField_BorderColor); - --_ui5_slider_handle_outline: none; - --_ui5_slider_handle_box_sizing: border-box; - --_ui5_slider_start_end_point_top: -0.125rem; --_ui5_range_slider_handle_background: var(--sapSlider_RangeHandleBackground); --_ui5_range_slider_root_hover_handle_bg: var(--sapButton_Hover_Background); --_ui5_range_slider_handle_active_background: var(--sapSlider_Active_RangeHandleBackground); - --_ui5_slider_inner_height: 0.375rem; - --_ui5_slider_track_total_height: var(--_ui5_slider_inner_height); - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2); - --_ui5_slider_tickmark_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_tickmark_height)) / 2); - --_ui5_slider_progress_background: var(--sapSlider_Selected_Background); - --_ui5_slider_progress_container_background: var(--sapSlider_Background); - --_ui5_slider_progress_container_dot_display: block; - --_ui5_slider_progress_before_background: var(--sapSlider_Selected_Background); - --_ui5_slider_progress_after_background: var(--sapContent_MeasureIndicatorColor); - --_ui5_slider_progress_after_border: solid 0.0625rem var(--sapContent_Selected_MeasureIndicatorColor); - --_ui5_slider_progress_before_border: solid 0.0625rem var(--sapContent_MeasureIndicatorColor); - --_ui5_slider_progress_outline_offset: -14px; - --_ui5_slider_outer_height: calc(var(--_ui5_slider_handle_height) + 9px); - --_ui5_slider_progress_outline_offset_left: calc(-1 * (var(--_ui5_slider_handle_width) / 2) - 6px); - --_ui5_slider_progress_outline: var(--sapContent_FocusWidth) dotted var(--sapContent_FocusColor); - --_ui5_range_slider_focus_outline_width: calc(100% + var(--_ui5_slider_handle_width) + 12px); - --_ui5_range_slider_focus_outline_radius: .5rem; - - --_ui5_slider_progress_container_top: 0; - --_ui5_slider_progress_height: .375rem; - --_ui5_slider_active_progress_border: solid 0.0625rem var(--sapSlider_Selected_BorderColor); - --_ui5_slider_active_progress_top: -.0625rem; - - --_ui5_slider_no_tickmarks_progress_container_top: 0; - --_ui5_slider_no_tickmarks_active_progress_border: none; - --_ui5_slider_no_tickmarks_active_progress_left: 0; - --_ui5_slider_no_tickmarks_active_progress_top: 0; - - --_ui5_slider_tooltip_background: var(--sapField_Background); - --_ui5_slider_tooltip_border_radius: var(--sapElement_BorderCornerRadius); - --_ui5_slider_tooltip_border_color: var(--sapField_BorderColor); - --_ui5_slider_tooltip_border: 0.0625rem solid var(--_ui5_slider_tooltip_border_color); - --_ui5_slider_tooltip_box_shadow: none; - --_ui5_slider_tooltip_padding: 0.25rem; - --_ui5_slider_tooltip_height: 1.375rem; - --_ui5_slider_handle_focused_tooltip_distance: calc(var(--_ui5_slider_tooltip_bottom) - 1px); - --_ui5_slider_tooltip_border_box: border-box; - --_ui5_slider_handle_focus_visibility: block; - - --_ui5_range_slider_legacy_progress_focus_display: none; - --_ui5_range_slider_progress_focus_display: block; - --_ui5_range_slider_progress_focus_height: calc(var(--_ui5_slider_handle_height) + 0.375rem); - --_ui5_range_slider_progress_focus_top: calc(-1 * ((var(--_ui5_slider_handle_height) / 2) + 0.1875rem) + 2 * var(--_ui5_slider_progress_border_width)); - --_ui5_range_slider_progress_focus_left: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); - --_ui5_range_slider_progress_focus_right: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); -} - -@container style(--ui5_content_density: compact) { - :host { - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2); - --_ui5_range_slider_focus_outline_width: calc(100% + var(--_ui5_slider_handle_width) + 12px); - --_ui5_slider_outer_height: calc(var(--_ui5_slider_handle_height) + 10px); - --_ui5_slider_progress_outline_offset: calc((-1 * var(--_ui5_slider_outer_height)) + 1rem); - --_ui5_slider_progress_outline_offset_left: calc(-1 * (var(--_ui5_slider_handle_width) / 2) - 6px); - } } \ No newline at end of file diff --git a/packages/main/src/themes/sap_horizon_hcb/SliderHandle-parameters.css b/packages/main/src/themes/sap_horizon_hcb/SliderHandle-parameters.css index 9abaa383f4ba..b95efe4f7708 100644 --- a/packages/main/src/themes/sap_horizon_hcb/SliderHandle-parameters.css +++ b/packages/main/src/themes/sap_horizon_hcb/SliderHandle-parameters.css @@ -1,5 +1,10 @@ @import "../base/SliderHandle-parameters.css"; :host { + --ui5_slider_handle_outline: none; --ui5_slider_handle_outline_offset: 3px; -} \ No newline at end of file + --_ui5_slider_handle_box_sizing: border-box; + --_ui5_slider_handle_hover_border: var(--_ui5_slider_handle_border); + --_ui5_slider_handle_background_focus: var(--sapSlider_Active_RangeHandleBackground); + --_ui5_slider_handle_icon_display: inline-block; +} diff --git a/packages/main/src/themes/sap_horizon_hcb/SliderScale-parameters.css b/packages/main/src/themes/sap_horizon_hcb/SliderScale-parameters.css index d07d994cffa3..17de19c63980 100644 --- a/packages/main/src/themes/sap_horizon_hcb/SliderScale-parameters.css +++ b/packages/main/src/themes/sap_horizon_hcb/SliderScale-parameters.css @@ -7,4 +7,15 @@ --_ui5_slider_scale_progress_height: 0.375rem; --_ui5_slider_scale_progress_top: -1px; --_ui5_slider_scale_dots_display: inline-block; + + /* Progress bar focus styling - Horizon HCB theme overrides */ + --_ui5_range_slider_legacy_progress_focus_display: none; + --_ui5_range_slider_progress_focus_display: block; + --_ui5_slider_handle_height: 1.5rem; + --_ui5_slider_handle_width: 2rem; + --_ui5_slider_progress_border_width: 0.0625rem; + --_ui5_range_slider_progress_focus_height: calc(var(--_ui5_slider_handle_height) + 0.375rem); + --_ui5_range_slider_progress_focus_top: calc(-1 * ((var(--_ui5_slider_handle_height) / 2) + 0.1875rem) + 2 * var(--_ui5_slider_progress_border_width) + 0.0625rem); + --_ui5_range_slider_progress_focus_left: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); + --_ui5_range_slider_progress_focus_right: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); } \ No newline at end of file diff --git a/packages/main/src/themes/sap_horizon_hcw/SliderBase-parameters.css b/packages/main/src/themes/sap_horizon_hcw/SliderBase-parameters.css index bf6ec22fd21d..a6243ac2625e 100644 --- a/packages/main/src/themes/sap_horizon_hcw/SliderBase-parameters.css +++ b/packages/main/src/themes/sap_horizon_hcw/SliderBase-parameters.css @@ -1,72 +1,8 @@ @import "../base/SliderBase-parameters.css"; :host { - /* handle */ - --_ui5_slider_handle_icon_display: inline-block; - --_ui5_range_slider_root_hover_handle_icon_display: inline-block; - --_ui5_slider_handle_hover_border: var(--_ui5_slider_handle_border); - --_ui5_slider_handle_background_focus: var(--sapSlider_Active_RangeHandleBackground); --_ui5_slider_handle_focus_border: 0.125rem solid var(--sapField_BorderColor); - --_ui5_slider_handle_outline: none; - --_ui5_slider_handle_box_sizing: border-box; - --_ui5_slider_start_end_point_top: -0.125rem; --_ui5_range_slider_handle_background: var(--sapSlider_RangeHandleBackground); --_ui5_range_slider_root_hover_handle_bg: var(--sapButton_Hover_Background); --_ui5_range_slider_handle_active_background: var(--sapSlider_Active_RangeHandleBackground); - --_ui5_slider_inner_height: 0.375rem; - --_ui5_slider_track_total_height: var(--_ui5_slider_inner_height); - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2); - --_ui5_slider_tickmark_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_tickmark_height)) / 2); - --_ui5_slider_progress_background: var(--sapSlider_Selected_Background); - --_ui5_slider_progress_container_background: var(--sapSlider_Background); - --_ui5_slider_progress_container_dot_display: block; - --_ui5_slider_progress_before_background: var(--sapSlider_Selected_Background); - --_ui5_slider_progress_after_background: var(--sapContent_MeasureIndicatorColor); - --_ui5_slider_progress_after_border: solid 0.0625rem var(--sapContent_Selected_MeasureIndicatorColor); - --_ui5_slider_progress_before_border: solid 0.0625rem var(--sapContent_MeasureIndicatorColor); - --_ui5_slider_progress_outline_offset: -14px; - --_ui5_slider_outer_height: calc(var(--_ui5_slider_handle_height) + 9px); - --_ui5_slider_progress_outline_offset_left: calc(-1 * (var(--_ui5_slider_handle_width) / 2) - 6px); - --_ui5_slider_progress_outline: var(--sapContent_FocusWidth) dotted var(--sapContent_FocusColor); - --_ui5_range_slider_focus_outline_width: calc(100% + var(--_ui5_slider_handle_width) + 12px); - --_ui5_range_slider_focus_outline_radius: .5rem; - - --_ui5_slider_progress_container_top: 0; - --_ui5_slider_progress_height: .375rem; - --_ui5_slider_active_progress_border: solid 0.0625rem var(--sapSlider_Selected_BorderColor); - --_ui5_slider_active_progress_top: -.0625rem; - - --_ui5_slider_no_tickmarks_progress_container_top: 0; - --_ui5_slider_no_tickmarks_active_progress_border: none; - --_ui5_slider_no_tickmarks_active_progress_left: 0; - --_ui5_slider_no_tickmarks_active_progress_top: 0; - - --_ui5_slider_tooltip_background: var(--sapField_Background); - --_ui5_slider_tooltip_border_radius: var(--sapElement_BorderCornerRadius); - --_ui5_slider_tooltip_border_color: var(--sapField_BorderColor); - --_ui5_slider_tooltip_border: 0.0625rem solid var(--_ui5_slider_tooltip_border_color); - --_ui5_slider_tooltip_box_shadow: none; - --_ui5_slider_tooltip_padding: 0.25rem; - --_ui5_slider_tooltip_height: 1.375rem; - --_ui5_slider_handle_focused_tooltip_distance: calc(var(--_ui5_slider_tooltip_bottom) - 1px); - --_ui5_slider_tooltip_border_box: border-box; - --_ui5_slider_handle_focus_visibility: block; - - --_ui5_range_slider_legacy_progress_focus_display: none; - --_ui5_range_slider_progress_focus_display: block; - --_ui5_range_slider_progress_focus_height: calc(var(--_ui5_slider_handle_height) + 0.375rem); - --_ui5_range_slider_progress_focus_top: calc(-1 * ((var(--_ui5_slider_handle_height) / 2) + 0.1875rem) + 2 * var(--_ui5_slider_progress_border_width)); - --_ui5_range_slider_progress_focus_left: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); - --_ui5_range_slider_progress_focus_right: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); -} - -@container style(--ui5_content_density: compact) { - :host { - --_ui5_slider_track_total_height: var(--_ui5_slider_inner_height); - --_ui5_slider_handle_top: calc((var(--_ui5_slider_track_total_height) - var(--_ui5_slider_handle_height)) / 2); - --_ui5_range_slider_focus_outline_width: calc(100% + var(--_ui5_slider_handle_width) + 12px); - --_ui5_slider_outer_height: calc(var(--_ui5_slider_handle_height) + 10px); - --_ui5_slider_progress_outline_offset: calc((-1 * var(--_ui5_slider_outer_height)) + 1rem); - --_ui5_slider_progress_outline_offset_left: calc(-1 * (var(--_ui5_slider_handle_width) / 2) - 6px); - } } \ No newline at end of file diff --git a/packages/main/src/themes/sap_horizon_hcw/SliderHandle-parameters.css b/packages/main/src/themes/sap_horizon_hcw/SliderHandle-parameters.css index 9abaa383f4ba..b95efe4f7708 100644 --- a/packages/main/src/themes/sap_horizon_hcw/SliderHandle-parameters.css +++ b/packages/main/src/themes/sap_horizon_hcw/SliderHandle-parameters.css @@ -1,5 +1,10 @@ @import "../base/SliderHandle-parameters.css"; :host { + --ui5_slider_handle_outline: none; --ui5_slider_handle_outline_offset: 3px; -} \ No newline at end of file + --_ui5_slider_handle_box_sizing: border-box; + --_ui5_slider_handle_hover_border: var(--_ui5_slider_handle_border); + --_ui5_slider_handle_background_focus: var(--sapSlider_Active_RangeHandleBackground); + --_ui5_slider_handle_icon_display: inline-block; +} diff --git a/packages/main/src/themes/sap_horizon_hcw/SliderScale-parameters.css b/packages/main/src/themes/sap_horizon_hcw/SliderScale-parameters.css index d07d994cffa3..b83af5b841e0 100644 --- a/packages/main/src/themes/sap_horizon_hcw/SliderScale-parameters.css +++ b/packages/main/src/themes/sap_horizon_hcw/SliderScale-parameters.css @@ -7,4 +7,15 @@ --_ui5_slider_scale_progress_height: 0.375rem; --_ui5_slider_scale_progress_top: -1px; --_ui5_slider_scale_dots_display: inline-block; + + /* Progress bar focus styling - Horizon HCW theme overrides */ + --_ui5_range_slider_legacy_progress_focus_display: none; + --_ui5_range_slider_progress_focus_display: block; + --_ui5_slider_handle_height: 1.5rem; + --_ui5_slider_handle_width: 2rem; + --_ui5_slider_progress_border_width: 0.0625rem; + --_ui5_range_slider_progress_focus_height: calc(var(--_ui5_slider_handle_height) + 0.375rem); + --_ui5_range_slider_progress_focus_top: calc(-1 * ((var(--_ui5_slider_handle_height) / 2) + 0.1875rem) + 2 * var(--_ui5_slider_progress_border_width) + 0.0625rem); + --_ui5_range_slider_progress_focus_left: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); + --_ui5_range_slider_progress_focus_right: calc(-1 * ((var(--_ui5_slider_handle_width) / 2) + 0.1875rem + var(--_ui5_slider_progress_border_width))); } \ No newline at end of file