Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions BREAKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
- [Picker](#version-8x-picker)
- [Progress bar](#version-8x-progress-bar)
- [Radio](#version-8x-radio)
- [Range](#version-8x-range)
- [Select](#version-8x-select)
- [Textarea](#version-8x-textarea)
- [Toggle](#version-8x-toggle)
Expand Down Expand Up @@ -183,6 +184,10 @@ For more information on styling toast buttons, refer to the [Toast Theming docum

- The `legacy` property and support for the legacy syntax, which involved placing an `ion-radio` inside of an `ion-item` with an `ion-label`, have been removed. For more information on migrating from the legacy radio syntax, refer to the [Radio documentation](https://ionicframework.com/docs/api/radio#migrating-from-legacy-radio-syntax).

<h4 id="version-8x-range">Range</h4>

- The `legacy` property and support for the legacy syntax, which involved placing an `ion-range` inside of an `ion-item` with an `ion-label`, have been removed. For more information on migrating from the legacy range syntax, refer to the [Range documentation](https://ionicframework.com/docs/api/range#migrating-from-legacy-range-syntax).

<h4 id="version-8x-select">Select</h4>

- The `legacy` property and support for the legacy syntax, which involved placing an `ion-select` inside of an `ion-item` with an `ion-label`, have been removed. For more information on migrating from the legacy select syntax, refer to the [Select documentation](https://ionicframework.com/docs/api/select#migrating-from-legacy-select-syntax).
Expand Down
1 change: 0 additions & 1 deletion core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1065,7 +1065,6 @@ ion-range,prop,disabled,boolean,false,false,false
ion-range,prop,dualKnobs,boolean,false,false,false
ion-range,prop,label,string | undefined,undefined,false,false
ion-range,prop,labelPlacement,"end" | "fixed" | "stacked" | "start",'start',false,false
ion-range,prop,legacy,boolean | undefined,undefined,false,false
ion-range,prop,max,number,100,false,false
ion-range,prop,min,number,0,false,false
ion-range,prop,mode,"ios" | "md",undefined,false,false
Expand Down
13 changes: 0 additions & 13 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2315,10 +2315,6 @@ export namespace Components {
* Where to place the label relative to the range. `"start"`: The label will appear to the left of the range in LTR and to the right in RTL. `"end"`: The label will appear to the right of the range in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). `"stacked"`: The label will appear above the range regardless of the direction.
*/
"labelPlacement": 'start' | 'end' | 'fixed' | 'stacked';
/**
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt components in to the modern form markup when they are using either the `aria-label` attribute or the `label` property. As a result, the `legacy` property should only be used as an escape hatch when you want to avoid this automatic opt-in behavior. Note that this property will be removed in an upcoming major release of Ionic, and all form components will be opted-in to using the modern form markup.
*/
"legacy"?: boolean;
/**
* Maximum integer value of the range.
*/
Expand Down Expand Up @@ -4179,7 +4175,6 @@ declare global {
interface HTMLIonRangeElementEventMap {
"ionChange": RangeChangeEventDetail;
"ionInput": RangeChangeEventDetail;
"ionStyle": StyleEventDetail;
"ionFocus": void;
"ionBlur": void;
"ionKnobMoveStart": RangeKnobMoveStartEventDetail;
Expand Down Expand Up @@ -7001,10 +6996,6 @@ declare namespace LocalJSX {
* Where to place the label relative to the range. `"start"`: The label will appear to the left of the range in LTR and to the right in RTL. `"end"`: The label will appear to the right of the range in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). `"stacked"`: The label will appear above the range regardless of the direction.
*/
"labelPlacement"?: 'start' | 'end' | 'fixed' | 'stacked';
/**
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt components in to the modern form markup when they are using either the `aria-label` attribute or the `label` property. As a result, the `legacy` property should only be used as an escape hatch when you want to avoid this automatic opt-in behavior. Note that this property will be removed in an upcoming major release of Ionic, and all form components will be opted-in to using the modern form markup.
*/
"legacy"?: boolean;
/**
* Maximum integer value of the range.
*/
Expand Down Expand Up @@ -7045,10 +7036,6 @@ declare namespace LocalJSX {
* Emitted when the user starts moving the range knob, whether through mouse drag, touch gesture, or keyboard interaction.
*/
"onIonKnobMoveStart"?: (event: IonRangeCustomEvent<RangeKnobMoveStartEventDetail>) => void;
/**
* Emitted when the styles change.
*/
"onIonStyle"?: (event: IonRangeCustomEvent<StyleEventDetail>) => void;
/**
* If `true`, a pin with integer value is shown when the knob is pressed.
*/
Expand Down
5 changes: 0 additions & 5 deletions core/src/components/range/range.ios.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@
--height: #{$range-ios-slider-height};
}

// TODO FW-2997 remove this
:host(.legacy-range) {
@include padding($range-ios-padding-vertical, $range-ios-padding-horizontal);
}

:host(.range-item-start-adjustment) {
@include padding(null, null, null, $range-ios-item-padding-horizontal);
}
Expand Down
4 changes: 0 additions & 4 deletions core/src/components/range/range.ios.vars.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
/// @prop - Padding top/bottom of the range
$range-ios-padding-vertical: 8px !default;

/// @prop - Padding start/end of the range
// TODO FW-2997 Remove this
$range-ios-padding-horizontal: 16px !default;

/// @prop - Padding start/end of the range - modern syntax
/**
* 24px was chosen so the knob and its
Expand Down
18 changes: 3 additions & 15 deletions core/src/components/range/range.md.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,9 @@
--pin-color: #{ion-color(primary, contrast)};
}

// TODO FW-2997 Remove this
:host(.legacy-range) ::slotted([slot="label"]) {
font-size: initial;
}

:host(:not(.legacy-range)) ::slotted(:not(ion-icon)[slot="start"]),
:host(:not(.legacy-range)) ::slotted(:not(ion-icon)[slot="end"]),
:host(:not(.legacy-range)) .native-wrapper {
font-size: $range-md-pin-font-size;
}

// TODO FW-2997 remove this
:host(.legacy-range) {
@include padding($range-md-padding-vertical, $range-md-padding-horizontal);

::slotted(:not(ion-icon)[slot="start"]),
::slotted(:not(ion-icon)[slot="end"]),
.native-wrapper {
font-size: $range-md-pin-font-size;
}

Expand Down
4 changes: 0 additions & 4 deletions core/src/components/range/range.md.vars.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
/// @prop - Padding top/bottom of the range
$range-md-padding-vertical: 8px !default;

/// @prop - Padding start/end of the range
// TODO FW-2997 Remove this
$range-md-padding-horizontal: 14px !default;

/// @prop - Padding start/end of the range - modern range
/**
* 18px was chosen so the knob and its focus/active
Expand Down
101 changes: 3 additions & 98 deletions core/src/components/range/range.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import type { ComponentInterface, EventEmitter } from '@stencil/core';
import { Component, Element, Event, Host, Prop, State, Watch, h } from '@stencil/core';
import { findClosestIonContent, disableContentScrollY, resetContentScrollY } from '@utils/content';
import type { LegacyFormController } from '@utils/forms';
import { createLegacyFormController } from '@utils/forms';
import type { Attributes } from '@utils/helpers';
import { inheritAriaAttributes, clamp, debounceEvent, getAriaLabel, renderHiddenInput } from '@utils/helpers';
import { printIonWarning } from '@utils/logging';
import { isRTL } from '@utils/rtl';
import { createColorClasses, hostContext } from '@utils/theme';

import { getIonMode } from '../../global/ionic-global';
import type { Color, Gesture, GestureDetail, StyleEventDetail } from '../../interface';
import type { Color, Gesture, GestureDetail } from '../../interface';
import { roundToMaxDecimalPlaces } from '../../utils/floating-point';

import type {
Expand Down Expand Up @@ -59,10 +57,6 @@ export class Range implements ComponentInterface {
private contentEl: HTMLElement | null = null;
private initialContentScrollY = true;
private originalIonInput?: EventEmitter<RangeChangeEventDetail>;
private legacyFormController!: LegacyFormController;

// This flag ensures we log the deprecation warning at most once.
private hasLoggedDeprecationWarning = false;

@Element() el!: HTMLIonRangeElement;

Expand Down Expand Up @@ -198,7 +192,6 @@ export class Range implements ComponentInterface {
if (this.gesture) {
this.gesture.enable(!this.disabled);
}
this.emitStyle();
}

/**
Expand Down Expand Up @@ -236,17 +229,6 @@ export class Range implements ComponentInterface {
*/
@Prop() labelPlacement: 'start' | 'end' | 'fixed' | 'stacked' = 'start';

/**
* Set the `legacy` property to `true` to forcibly use the legacy form control markup.
* Ionic will only opt components in to the modern form markup when they are
* using either the `aria-label` attribute or the `label` property. As a result,
* the `legacy` property should only be used as an escape hatch when you want to
* avoid this automatic opt-in behavior.
* Note that this property will be removed in an upcoming major release
* of Ionic, and all form components will be opted-in to using the modern form markup.
*/
@Prop() legacy?: boolean;

/**
* The `ionChange` event is fired for `<ion-range>` elements when the user
* modifies the element's value:
Expand All @@ -264,12 +246,6 @@ export class Range implements ComponentInterface {
*/
@Event() ionInput!: EventEmitter<RangeChangeEventDetail>;

/**
* Emitted when the styles change.
* @internal
*/
@Event() ionStyle!: EventEmitter<StyleEventDetail>;

/**
* Emitted when the range has focus.
*/
Expand Down Expand Up @@ -328,10 +304,6 @@ export class Range implements ComponentInterface {
}

connectedCallback() {
const { el } = this;

this.legacyFormController = createLegacyFormController(el);

this.updateRatio();
this.debounceChanged();
this.disabledChanged();
Expand Down Expand Up @@ -395,18 +367,6 @@ export class Range implements ComponentInterface {
}
}

// TODO FW-2997 remove this
private emitStyle() {
if (this.legacyFormController.hasLegacyControl()) {
this.ionStyle.emit({
interactive: true,
'interactive-disabled': this.disabled,
// TODO(FW-2997): remove this
legacy: !!this.legacy,
});
}
}

/**
* Emits an `ionChange` event.
*
Expand Down Expand Up @@ -553,70 +513,16 @@ export class Range implements ComponentInterface {
if (this.hasFocus) {
this.hasFocus = false;
this.ionBlur.emit();
this.emitStyle();
}
};

private onFocus = () => {
if (!this.hasFocus) {
this.hasFocus = true;
this.ionFocus.emit();
this.emitStyle();
}
};

// TODO FW-2997 remove this
private renderLegacyRange() {
if (!this.hasLoggedDeprecationWarning) {
printIonWarning(
`ion-range now requires providing a label with either the label slot or the "aria-label" attribute. To migrate, remove any usage of "ion-label" and pass the label text to either the component or the "aria-label" attribute.

Example: <ion-range><div slot="label">Volume</div></ion-range>
Example with aria-label: <ion-range aria-label="Volume"></ion-range>

Developers can use the "legacy" property to continue using the legacy form markup. This property will be removed in an upcoming major release of Ionic where this form control will use the modern form markup.`,
this.el
);

if (this.legacy) {
printIonWarning(
`ion-range is being used with the "legacy" property enabled which will forcibly enable the legacy form markup. This property will be removed in an upcoming major release of Ionic where this form control will use the modern form markup.

Developers can dismiss this warning by removing their usage of the "legacy" property and using the new range syntax.`,
this.el
);
}

this.hasLoggedDeprecationWarning = true;
}

const { el, pressedKnob, disabled, pin, rangeId } = this;

const mode = getIonMode(this);

renderHiddenInput(true, el, this.name, JSON.stringify(this.getValue()), disabled);

return (
<Host
onFocusin={this.onFocus}
onFocusout={this.onBlur}
id={rangeId}
class={createColorClasses(this.color, {
[mode]: true,
'in-item': hostContext('ion-item', el),
'range-disabled': disabled,
'range-pressed': pressedKnob !== undefined,
'range-has-pin': pin,
'legacy-range': true,
})}
>
<slot name="start"></slot>
{this.renderRangeSlider()}
<slot name="end"></slot>
</Host>
);
}

/**
* Returns true if content was passed to the "start" slot
*/
Expand Down Expand Up @@ -794,7 +700,7 @@ Developers can dismiss this warning by removing their usage of the "legacy" prop
}

let labelledBy: string | undefined;
if (!this.legacyFormController.hasLegacyControl() && this.hasLabel) {
if (this.hasLabel) {
labelledBy = 'range-label';
}

Expand Down Expand Up @@ -861,8 +767,7 @@ Developers can dismiss this warning by removing their usage of the "legacy" prop
}

render() {
const { legacyFormController } = this;
return legacyFormController.hasLegacyControl() ? this.renderLegacyRange() : this.renderRange();
return this.renderRange();
}
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/components/range/test/a11y/range.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, co
await page.setContent(
`<ion-app>
<ion-content>
<ion-range min="0" max="100" value="80" legacy="true"></ion-range>
<ion-range min="0" max="100" value="80" aria-label="Range"></ion-range>
</ion-content>
</ion-app>
`,
Expand Down Expand Up @@ -67,7 +67,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
await page.setContent(
`<ion-app>
<ion-content>
<ion-range min="0" max="100" value="50" pin="true" legacy="true"></ion-range>
<ion-range min="0" max="100" value="50" pin="true" aria-label="Range"></ion-range>
</ion-content>
</ion-app>
`,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 0 additions & 14 deletions core/src/components/range/test/range.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,20 +186,6 @@ describe('range: item adjustments', () => {
expect(range.classList.contains('range-item-end-adjustment')).toBe(false);
});

// TODO FW-2997 remove this
it('should not add adjustment with legacy syntax', async () => {
const page = await newSpecPage({
components: [Item, Range],
html: `
<ion-range legacy="true"></ion-range>
`,
});

const range = page.body.querySelector('ion-range')!;
expect(range.classList.contains('range-item-start-adjustment')).toBe(false);
expect(range.classList.contains('range-item-end-adjustment')).toBe(false);
});

it('should not add start adjustment when with start adornment', async () => {
const page = await newSpecPage({
components: [Item, Range],
Expand Down
4 changes: 2 additions & 2 deletions packages/angular/src/directives/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1640,14 +1640,14 @@ export declare interface IonRadioGroup extends Components.IonRadioGroup {


@ProxyCmp({
inputs: ['activeBarStart', 'color', 'debounce', 'disabled', 'dualKnobs', 'label', 'labelPlacement', 'legacy', 'max', 'min', 'mode', 'name', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'value']
inputs: ['activeBarStart', 'color', 'debounce', 'disabled', 'dualKnobs', 'label', 'labelPlacement', 'max', 'min', 'mode', 'name', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'value']
})
@Component({
selector: 'ion-range',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['activeBarStart', 'color', 'debounce', 'disabled', 'dualKnobs', 'label', 'labelPlacement', 'legacy', 'max', 'min', 'mode', 'name', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'value'],
inputs: ['activeBarStart', 'color', 'debounce', 'disabled', 'dualKnobs', 'label', 'labelPlacement', 'max', 'min', 'mode', 'name', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'value'],
})
export class IonRange {
protected el: HTMLElement;
Expand Down
1 change: 0 additions & 1 deletion packages/angular/standalone/src/directives/range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ const RANGE_INPUTS = [
'dualKnobs',
'label',
'labelPlacement',
'legacy',
'max',
'min',
'mode',
Expand Down
2 changes: 0 additions & 2 deletions packages/vue/src/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -641,10 +641,8 @@ export const IonRange = /*@__PURE__*/ defineContainer<JSX.IonRange, JSX.IonRange
'disabled',
'value',
'labelPlacement',
'legacy',
'ionChange',
'ionInput',
'ionStyle',
'ionFocus',
'ionBlur',
'ionKnobMoveStart',
Expand Down