diff --git a/packages/docs/page-config/ui-elements/slider/examples/InvertedTrack.vue b/packages/docs/page-config/ui-elements/slider/examples/InvertedTrack.vue
new file mode 100644
index 0000000000..ac6702cae7
--- /dev/null
+++ b/packages/docs/page-config/ui-elements/slider/examples/InvertedTrack.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/docs/page-config/ui-elements/slider/index.ts b/packages/docs/page-config/ui-elements/slider/index.ts
index 0dc87dc468..94251990c1 100644
--- a/packages/docs/page-config/ui-elements/slider/index.ts
+++ b/packages/docs/page-config/ui-elements/slider/index.ts
@@ -1,5 +1,5 @@
-import apiOptions from "./api-options";
import apiDescription from './api-description';
+import apiOptions from "./api-options";
export default definePageConfig({
blocks: [
@@ -62,6 +62,10 @@ export default definePageConfig({
title: "Vertical",
description: "Vertical state of slider."
}),
+ block.example("InvertedTrack", {
+ title: "Inverted",
+ description: "Inverted track fill."
+ }),
block.subtitle('Accessibility'),
block.paragraph('The component covers all the requirements of [w3 slider template](https://www.w3.org/WAI/ARIA/apg/patterns/slider/#wai-ariaroles,states,andproperties)[[target=_blank]]. It has [role=\"slider\"](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/slider_role)[[target=_blank]] and the following attributes: [aria-valuemin](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuemin)[[target=_blank]], [aria-valuemax](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuemax)[[target=_blank]], [aria-valuenow](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-valuenow)[[target=_blank]], [aria-label](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label)[[target=_blank]], [aria-orientation](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-orientation)[[target=_blank]], [aria-disabled](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-disabled)[[target=_blank]], [aria-readonly](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-readonly)[[target=_blank]].'),
diff --git a/packages/ui/src/components/va-slider/VaSlider.stories.ts b/packages/ui/src/components/va-slider/VaSlider.stories.ts
index 26a13de1fe..832c864b77 100644
--- a/packages/ui/src/components/va-slider/VaSlider.stories.ts
+++ b/packages/ui/src/components/va-slider/VaSlider.stories.ts
@@ -1,9 +1,9 @@
-import { getStoryId, getStoryIdAll, getStorySelector, getStorySelectorAll } from '../../../.storybook/interaction-utils/storySelector'
-import { userEvent } from '../../../.storybook/interaction-utils/userEvent'
+import { sleep } from '@/utils/sleep'
+import { expect } from '@storybook/jest'
import { fireEvent } from '@storybook/testing-library'
import { StoryFn } from '@storybook/vue3'
-import { expect } from '@storybook/jest'
-import { sleep } from '@/utils/sleep'
+import { getStoryId, getStoryIdAll, getStorySelector, getStorySelectorAll } from '../../../.storybook/interaction-utils/storySelector'
+import { userEvent } from '../../../.storybook/interaction-utils/userEvent'
import { VaSlider } from './'
function getSlider () {
@@ -678,3 +678,26 @@ Vertical.play = async ({ step }) => {
expect(slider[2]).toHaveAttribute('aria-valuetext', '100')
})
}
+
+export const invertTrack: StoryFn = () => ({
+ components: { VaSlider },
+ data: () => ({ value: 25 }),
+ template: `
+ [default inverted]
+
+
+
+ [vertical inverted]
+
+
+
+ [default regular]
+
+
+
+ [vertical regular]
+
+
+
+ `,
+})
diff --git a/packages/ui/src/components/va-slider/VaSlider.vue b/packages/ui/src/components/va-slider/VaSlider.vue
index b5e9a212df..fd45a9fa02 100644
--- a/packages/ui/src/components/va-slider/VaSlider.vue
+++ b/packages/ui/src/components/va-slider/VaSlider.vue
@@ -229,6 +229,7 @@ const props = defineProps({
iconAppend: { type: String, default: '' },
vertical: { type: Boolean, default: false },
showTrack: { type: Boolean, default: true },
+ invertTrack: { type: Boolean, default: false },
ariaLabel: useTranslationProp('$t:sliderValue'),
ariaLabelDot: useTranslationProp('$t:sliderDot'),
ariaLabelMaxDot: useTranslationProp('$t:sliderMaxDot'),
@@ -267,6 +268,7 @@ const orders = computed(() => {
const pinPositionStyle = computed(() => props.vertical ? 'bottom' : 'left')
const trackSizeStyle = computed(() => props.vertical ? 'height' : 'width')
+const trackPositionStyle = computed(() => props.vertical ? props.invertTrack ? 'top' : 'bottom' : props.invertTrack ? 'right' : 'left')
const moreToLess = computed(() => Array.isArray(val.value) && (val.value[1] - stepComputed.value) < val.value[0])
@@ -307,9 +309,11 @@ const processedStyles = computed(() => {
} as CSSProperties
} else {
const val0 = calculatePercentage(val.value)
+ const trackSizeStyleValue = props.invertTrack ? 100 - val0 : val0
return {
- [trackSizeStyle.value]: `${val0 > 100 ? 100 : val0}%`,
+ [trackSizeStyle.value]: `${trackSizeStyleValue > 100 ? 100 : trackSizeStyleValue < 0 ? 0 : trackSizeStyleValue}%`,
+ [trackPositionStyle.value]: 0,
backgroundColor: getColor(props.color),
visibility: props.showTrack ? 'visible' : 'hidden',
} as CSSProperties