diff --git a/packages/elements/src/components/ino-range/ino-range.e2e.ts b/packages/elements/src/components/ino-range/ino-range.e2e.ts
deleted file mode 100644
index 5374b65b0d..0000000000
--- a/packages/elements/src/components/ino-range/ino-range.e2e.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import { setupPageWithContent } from '../../util/e2etests-setup';
-
-const INO_RANGE = ``;
-const INO_RANGE_SELECTOR = 'ino-range';
-const MDC_INPUT_SELECTOR = 'ino-range input';
-const MDC_SELECTOR = 'ino-range .mdc-slider';
-
-describe('InoRange', () => {
- describe('Properties', () => {
- it('should disable the range component if disabled property is set to true', async () => {
- const page = await setupPageWithContent(INO_RANGE);
- const inoRange = await page.find(INO_RANGE_SELECTOR);
- const mdcSlider = await page.find(MDC_SELECTOR);
-
- await inoRange.setAttribute('disabled', true);
- await page.waitForChanges();
-
- expect(mdcSlider).toHaveClass('mdc-slider--disabled');
- });
-
- it('should set the min and max value of the range component', async () => {
- const page = await setupPageWithContent(INO_RANGE);
- const inoRange = await page.find(INO_RANGE_SELECTOR);
- const mdcSlider = await page.find(MDC_INPUT_SELECTOR);
-
- await inoRange.setAttribute('min', 20);
- await inoRange.setAttribute('max', 400);
- await page.waitForChanges();
-
- const min = await mdcSlider.getAttribute('min');
- const max = await mdcSlider.getAttribute('max');
-
- expect(min).toBe('20');
- expect(max).toBe('400');
- });
-
- it('should set the step value of the range component', async () => {
- const page = await setupPageWithContent(INO_RANGE);
- const inoRange = await page.find(INO_RANGE_SELECTOR);
- const mdcSlider = await page.find(MDC_INPUT_SELECTOR);
-
- await inoRange.setAttribute('step', 5);
- await page.waitForChanges();
-
- const step = await mdcSlider.getAttribute('step');
-
- expect(step).toBe('5');
- });
-
- it('should render as a discrete slider if discrete is true', async () => {
- const page = await setupPageWithContent(INO_RANGE);
- const inoRange = await page.find(INO_RANGE_SELECTOR);
- const mdcSlider = await page.find(MDC_SELECTOR);
-
- await inoRange.setAttribute('discrete', true);
- await page.waitForChanges();
-
- expect(mdcSlider).toHaveClass('mdc-slider--discrete');
- });
-
- it('should render with tick marks if markers is true', async () => {
- const page = await setupPageWithContent(INO_RANGE);
- const inoRange = await page.find(INO_RANGE_SELECTOR);
- const mdcSlider = await page.find(MDC_SELECTOR);
-
- await inoRange.setAttribute('markers', true);
- await page.waitForChanges();
-
- expect(mdcSlider).toHaveClass('mdc-slider--tick-marks');
- });
- });
-
- describe('Events', () => {
- it('should prevent the propagation of the MDCSlider:change event', async () => {
- const page = await setupPageWithContent(INO_RANGE);
- const mdcSlider = await page.find(MDC_INPUT_SELECTOR);
- const valueChangeEvent = await page.spyOnEvent('MDCSlider:change');
-
- await mdcSlider.triggerEvent('MDCSlider:change');
- await page.waitForChanges();
-
- expect(valueChangeEvent).not.toHaveReceivedEvent();
- });
- });
-});
diff --git a/packages/elements/src/components/ino-range/ino-range.tsx b/packages/elements/src/components/ino-range/ino-range.tsx
index 38847b1cce..eea495e32e 100644
--- a/packages/elements/src/components/ino-range/ino-range.tsx
+++ b/packages/elements/src/components/ino-range/ino-range.tsx
@@ -34,6 +34,10 @@ export class Range implements ComponentInterface {
* Disables this element.
*/
@Prop() disabled?: boolean;
+ @Watch('disabled')
+ handleDisabledChange(isDisabled: boolean) {
+ this.sliderInstance.setDisabled(isDisabled);
+ }
/**
* Restricts the slider to only allow discrete values.
@@ -131,7 +135,7 @@ export class Range implements ComponentInterface {
);
this.inputElStart?.setAttribute('value', `${this.valueStart}`);
this.sliderInstance = new MDCSlider(this.sliderEl);
-
+ this.sliderInstance.setDisabled(this.disabled);
this.sliderInstance.listen('MDCSlider:change', preventEvent);
this.sliderInstance.listen('MDCSlider:input', this.handleInput);
}
@@ -144,7 +148,6 @@ export class Range implements ComponentInterface {
private handleInput = (e: CustomEvent) => {
e.stopPropagation();
-
const { thumb, value } = e.detail;
if (!this.ranged) {
diff --git a/packages/storybook/src/stories/ino-button/ino-button.scss b/packages/storybook/src/stories/ino-button/ino-button.scss
index ef66288e31..16ea9cf0b9 100644
--- a/packages/storybook/src/stories/ino-button/ino-button.scss
+++ b/packages/storybook/src/stories/ino-button/ino-button.scss
@@ -1,5 +1,7 @@
+@import '../utils';
+
#story--buttons-ino-button--leading-and-trailing-icon-inner {
- #root-inner {
+ @include story-container {
display: flex;
column-gap: 20px;
}
diff --git a/packages/storybook/src/stories/ino-fab-set/ino-fab-set.scss b/packages/storybook/src/stories/ino-fab-set/ino-fab-set.scss
index f3717e9f8e..1c29669540 100644
--- a/packages/storybook/src/stories/ino-fab-set/ino-fab-set.scss
+++ b/packages/storybook/src/stories/ino-fab-set/ino-fab-set.scss
@@ -1,3 +1,5 @@
+@import '../utils';
+
// only selects Stories of ino-fab-set without decorating stories with wrapper classes
.sbdocs.sbdocs-content:has(#anchor--buttons-ino-fab-set--default) {
[scale] {
@@ -5,7 +7,7 @@
}
}
-#root-inner {
+@include story-container {
min-width: 10px;
min-height: 10px;
}
diff --git a/packages/storybook/src/stories/ino-input/ino-input.scss b/packages/storybook/src/stories/ino-input/ino-input.scss
index 7957be50fc..537b03451c 100644
--- a/packages/storybook/src/stories/ino-input/ino-input.scss
+++ b/packages/storybook/src/stories/ino-input/ino-input.scss
@@ -1,12 +1,16 @@
+@import '../utils';
+
.sbdocs.sbdocs-content:has(#anchor--input-ino-input--default) {
[scale] {
width: 100%;
}
- #story--input-ino-input--states-inner #root-inner,
- #story--input-ino-input--labels-inner #root-inner {
- display: flex;
- flex-direction: column;
- gap: 15px;
+ #story--input-ino-input--states-inner,
+ #story--input-ino-input--labels-inner {
+ @include story-container {
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+ }
}
}
diff --git a/packages/storybook/src/stories/ino-popover/ino-popover.scss b/packages/storybook/src/stories/ino-popover/ino-popover.scss
index 8867a98518..4aee364103 100644
--- a/packages/storybook/src/stories/ino-popover/ino-popover.scss
+++ b/packages/storybook/src/stories/ino-popover/ino-popover.scss
@@ -1,3 +1,5 @@
+@import '../utils';
+
.sbdocs.sbdocs-content:has(#anchor--notification-ino-popover--default) {
[scale] {
width: 100%;
@@ -16,7 +18,7 @@
.innerZoomElementWrapper > div > div {
overflow: unset;
- #root-inner {
+ @include story-container {
display: flex;
gap: 5px;
}
diff --git a/packages/storybook/src/stories/ino-range/ino-range.scss b/packages/storybook/src/stories/ino-range/ino-range.scss
index a63f4c53b6..9dc5ac0f6b 100644
--- a/packages/storybook/src/stories/ino-range/ino-range.scss
+++ b/packages/storybook/src/stories/ino-range/ino-range.scss
@@ -1,5 +1,11 @@
+@import '../utils';
+
.sbdocs.sbdocs-content:has(#anchor--input-ino-range--default) {
[scale] {
width: 100%;
}
}
+
+@include story-container {
+ min-width: 200px;
+}
diff --git a/packages/storybook/src/stories/ino-range/ino-range.spec.ts b/packages/storybook/src/stories/ino-range/ino-range.spec.ts
new file mode 100644
index 0000000000..b15aab433f
--- /dev/null
+++ b/packages/storybook/src/stories/ino-range/ino-range.spec.ts
@@ -0,0 +1,64 @@
+import { expect, Page, test } from '@playwright/test';
+import { goToStory, setAttribute } from '../test-utils';
+
+test.describe('ino-range', () => {
+ const move = async (page: Page, targetPercentage: number) => {
+ const slider = page.locator('.mdc-slider');
+ const knob = slider.locator('.mdc-slider__thumb-knob');
+ const knobBox = await knob.boundingBox();
+ const sliderBox = await slider.boundingBox();
+
+ // Start from the middle of the slider's thumb
+ const start = {
+ x: knobBox.x + knobBox.width / 2,
+ y: knobBox.y + knobBox.height / 2,
+ };
+ // Slide it to some endpoint determined by the target percentage
+ const end = {
+ x: sliderBox.x + sliderBox.width * targetPercentage,
+ y: knobBox.y + knobBox.height / 2,
+ };
+
+ await page.mouse.move(start.x, start.y);
+ await page.mouse.down();
+ await page.mouse.move(end.x, end.y);
+ await page.mouse.up();
+ };
+
+ test('should not move thumb knob when is disabled', async ({ page }) => {
+ await goToStory(page, ['Input', 'ino-range', 'default']);
+ const inoRange = page.locator('ino-range');
+ const input = inoRange.getByRole('slider');
+ await expect(input).toHaveValue('70');
+
+ await setAttribute(inoRange, 'disabled', 'disabled');
+ await expect(input).toBeDisabled();
+
+ await move(page, 0.1);
+ await expect(input).toHaveValue('70');
+ });
+
+ test('should move thumb knob', async ({ page }) => {
+ await goToStory(page, ['Input', 'ino-range', 'default']);
+ const input = page.getByRole('slider');
+ await expect(input).toHaveValue('70');
+
+ await move(page, 0.95);
+ await expect(input).toHaveValue('95');
+ await move(page, 0.17);
+ await expect(input).toHaveValue('17');
+ });
+
+ test('should apply custom step value', async ({ page }) => {
+ await goToStory(page, ['Input', 'ino-range', 'default']);
+ const inoRange = page.locator('ino-range');
+ await setAttribute(inoRange, 'step', '10');
+ const input = page.getByRole('slider');
+ await expect(input).toHaveValue('70');
+
+ await move(page, 0.61);
+ await expect(input).toHaveValue('60');
+ await move(page, 0.86);
+ await expect(input).toHaveValue('90');
+ });
+});
diff --git a/packages/storybook/src/stories/ino-select/ino-select.spec.ts b/packages/storybook/src/stories/ino-select/ino-select.spec.ts
index c10f1f864f..80e0d7bea1 100644
--- a/packages/storybook/src/stories/ino-select/ino-select.spec.ts
+++ b/packages/storybook/src/stories/ino-select/ino-select.spec.ts
@@ -2,35 +2,26 @@ import { expect, Locator, test } from '@playwright/test';
import { goToStory, setAttribute } from '../test-utils';
test.describe('ino-select - Properties', () => {
- let inoSelect: Locator;
-
test.beforeEach(async ({ page }) => {
await goToStory(page, ['Input', 'ino-select', 'default']);
- inoSelect = page.locator('ino-select');
});
- test('should render with the disabled property set to true', async () => {
+ test('should render with the disabled property set to true', async ({
+ page,
+ }) => {
+ const inoSelect = page.locator('ino-select');
await setAttribute(inoSelect, 'disabled', 'true');
await inoSelect.click();
await expect(inoSelect.locator('li').first()).toBeHidden();
});
- test('should render with the required property set to true', async () => {
+ test('should render with the required property set to true', async ({
+ page,
+ }) => {
+ const inoSelect = page.locator('ino-select');
await setAttribute(inoSelect, 'required', 'true');
await expect(inoSelect.locator('input[required]')).toBeAttached();
});
-
- test('should render as an outlined element if inoOutlined is true', async () => {
- await inoSelect.hover();
- const bBoxDefault = await inoSelect.boundingBox();
-
- await setAttribute(inoSelect, 'outline', 'true');
- await inoSelect.hover();
- const bBoxOutline = await inoSelect.boundingBox();
-
- expect(bBoxOutline.height).toBe(bBoxDefault.height);
- expect(bBoxOutline.width).toBeGreaterThan(bBoxDefault.width);
- });
});
test.describe('ino-select - Form integration', () => {
diff --git a/packages/storybook/src/stories/ino-textarea/ino-textarea.scss b/packages/storybook/src/stories/ino-textarea/ino-textarea.scss
index ce56c91908..765f072fcc 100644
--- a/packages/storybook/src/stories/ino-textarea/ino-textarea.scss
+++ b/packages/storybook/src/stories/ino-textarea/ino-textarea.scss
@@ -1,3 +1,5 @@
+@import '../utils';
+
.sbdocs.sbdocs-content:has(#anchor--input-ino-textarea--default) {
[scale] {
width: 100%;
@@ -8,8 +10,10 @@
margin-bottom: 15px;
}
- #story--input-ino-textarea--label-inner #root-inner {
- display: flex;
- gap: 15px;
+ #story--input-ino-textarea--label-inner {
+ @include story-container {
+ display: flex;
+ gap: 15px;
+ }
}
}
diff --git a/packages/storybook/src/stories/ino-textarea/ino-textarea.spec.ts b/packages/storybook/src/stories/ino-textarea/ino-textarea.spec.ts
index cc072c96de..6c48f9008a 100644
--- a/packages/storybook/src/stories/ino-textarea/ino-textarea.spec.ts
+++ b/packages/storybook/src/stories/ino-textarea/ino-textarea.spec.ts
@@ -46,13 +46,15 @@ test.describe('ino-textarea', () => {
page,
}) => {
const inoTextArea = page.locator('ino-textarea');
+ const textarea = inoTextArea.getByRole('textbox');
+
await setAttribute(inoTextArea, 'cols', '1');
- await inoTextArea.hover();
- const { width: oneColWidth } = await inoTextArea.boundingBox();
+ await inoTextArea.blur();
+ const { width: oneColWidth } = await textarea.boundingBox();
await setAttribute(inoTextArea, 'cols', '10');
- await inoTextArea.hover();
- const { width: tenColsWidth } = await inoTextArea.boundingBox();
+ await inoTextArea.blur();
+ const { width: tenColsWidth } = await textarea.boundingBox();
expect(oneColWidth).toBeLessThan(tenColsWidth);
});
diff --git a/packages/storybook/src/stories/ino-tooltip/ino-tooltip.scss b/packages/storybook/src/stories/ino-tooltip/ino-tooltip.scss
index 4e42a0d05a..62c668c6a6 100644
--- a/packages/storybook/src/stories/ino-tooltip/ino-tooltip.scss
+++ b/packages/storybook/src/stories/ino-tooltip/ino-tooltip.scss
@@ -1,3 +1,5 @@
+@import '../utils';
+
.story-tooltip {
display: flex;
justify-content: center;
@@ -21,9 +23,11 @@
align-items: flex-end;
height: 110px;
- #story--notification-ino-tooltip--color-scheme-inner #root-inner {
- display: flex;
- gap: 15px;
+ #story--notification-ino-tooltip--color-scheme-inner {
+ @include story-container {
+ display: flex;
+ gap: 15px;
+ }
}
h4 {
diff --git a/packages/storybook/src/stories/utils.scss b/packages/storybook/src/stories/utils.scss
new file mode 100644
index 0000000000..fa303e4f36
--- /dev/null
+++ b/packages/storybook/src/stories/utils.scss
@@ -0,0 +1,9 @@
+/**
+ * Applies styling to the container of a story.
+ * The styling is encapsulated within this mixin because the ID may change in the future.
+ */
+@mixin story-container {
+ #root-inner {
+ @content;
+ }
+}