feat(checkbox, radio, toggle, range): stacked labels for form controls (#28075)
Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com> Co-authored-by: ionitron <hi@ionicframework.com>
11
core/api.txt
@@ -289,12 +289,13 @@ ion-card-title,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-card-title,css-prop,--color
|
||||
|
||||
ion-checkbox,shadow
|
||||
ion-checkbox,prop,alignment,"center" | "start",'center',false,false
|
||||
ion-checkbox,prop,checked,boolean,false,false,false
|
||||
ion-checkbox,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
|
||||
ion-checkbox,prop,disabled,boolean,false,false,false
|
||||
ion-checkbox,prop,indeterminate,boolean,false,false,false
|
||||
ion-checkbox,prop,justify,"end" | "space-between" | "start",'space-between',false,false
|
||||
ion-checkbox,prop,labelPlacement,"end" | "fixed" | "start",'start',false,false
|
||||
ion-checkbox,prop,labelPlacement,"end" | "fixed" | "stacked" | "start",'start',false,false
|
||||
ion-checkbox,prop,legacy,boolean | undefined,undefined,false,false
|
||||
ion-checkbox,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-checkbox,prop,name,string,this.inputId,false,false
|
||||
@@ -1008,10 +1009,11 @@ ion-progress-bar,part,stream
|
||||
ion-progress-bar,part,track
|
||||
|
||||
ion-radio,shadow
|
||||
ion-radio,prop,alignment,"center" | "start",'center',false,false
|
||||
ion-radio,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
|
||||
ion-radio,prop,disabled,boolean,false,false,false
|
||||
ion-radio,prop,justify,"end" | "space-between" | "start",'space-between',false,false
|
||||
ion-radio,prop,labelPlacement,"end" | "fixed" | "start",'start',false,false
|
||||
ion-radio,prop,labelPlacement,"end" | "fixed" | "stacked" | "start",'start',false,false
|
||||
ion-radio,prop,legacy,boolean | undefined,undefined,false,false
|
||||
ion-radio,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-radio,prop,name,string,this.inputId,false,false
|
||||
@@ -1038,7 +1040,7 @@ ion-range,prop,debounce,number | undefined,undefined,false,false
|
||||
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" | "start",'start',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
|
||||
@@ -1478,12 +1480,13 @@ ion-toast,part,icon
|
||||
ion-toast,part,message
|
||||
|
||||
ion-toggle,shadow
|
||||
ion-toggle,prop,alignment,"center" | "start",'center',false,false
|
||||
ion-toggle,prop,checked,boolean,false,false,false
|
||||
ion-toggle,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
|
||||
ion-toggle,prop,disabled,boolean,false,false,false
|
||||
ion-toggle,prop,enableOnOffLabels,boolean | undefined,config.get('toggleOnOffLabels'),false,false
|
||||
ion-toggle,prop,justify,"end" | "space-between" | "start",'space-between',false,false
|
||||
ion-toggle,prop,labelPlacement,"end" | "fixed" | "start",'start',false,false
|
||||
ion-toggle,prop,labelPlacement,"end" | "fixed" | "stacked" | "start",'start',false,false
|
||||
ion-toggle,prop,legacy,boolean | undefined,undefined,false,false
|
||||
ion-toggle,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-toggle,prop,name,string,this.inputId,false,false
|
||||
|
||||
56
core/src/components.d.ts
vendored
@@ -602,6 +602,10 @@ export namespace Components {
|
||||
"mode"?: "ios" | "md";
|
||||
}
|
||||
interface IonCheckbox {
|
||||
/**
|
||||
* How to control the alignment of the checkbox and label on the cross axis. `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
*/
|
||||
"alignment": 'start' | 'center';
|
||||
/**
|
||||
* If `true`, the checkbox is selected.
|
||||
*/
|
||||
@@ -623,9 +627,9 @@ export namespace Components {
|
||||
*/
|
||||
"justify": 'start' | 'end' | 'space-between';
|
||||
/**
|
||||
* Where to place the label relative to the checkbox. `"start"`: The label will appear to the left of the checkbox in LTR and to the right in RTL. `"end"`: The label will appear to the right of the checkbox 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 ("...").
|
||||
* Where to place the label relative to the checkbox. `"start"`: The label will appear to the left of the checkbox in LTR and to the right in RTL. `"end"`: The label will appear to the right of the checkbox 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 checkbox regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
|
||||
*/
|
||||
"labelPlacement": 'start' | 'end' | 'fixed';
|
||||
"labelPlacement": 'start' | 'end' | 'fixed' | 'stacked';
|
||||
/**
|
||||
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt checkboxes in to the modern form markup when they are using either the `aria-label` attribute or have text in the default slot. 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.
|
||||
*/
|
||||
@@ -2216,6 +2220,10 @@ export namespace Components {
|
||||
"value": number;
|
||||
}
|
||||
interface IonRadio {
|
||||
/**
|
||||
* How to control the alignment of the radio and label on the cross axis. `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
*/
|
||||
"alignment": 'start' | 'center';
|
||||
/**
|
||||
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
|
||||
*/
|
||||
@@ -2229,9 +2237,9 @@ export namespace Components {
|
||||
*/
|
||||
"justify": 'start' | 'end' | 'space-between';
|
||||
/**
|
||||
* Where to place the label relative to the radio. `"start"`: The label will appear to the left of the radio in LTR and to the right in RTL. `"end"`: The label will appear to the right of the radio 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 ("...").
|
||||
* Where to place the label relative to the radio. `"start"`: The label will appear to the left of the radio in LTR and to the right in RTL. `"end"`: The label will appear to the right of the radio 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 radio regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
|
||||
*/
|
||||
"labelPlacement": 'start' | 'end' | 'fixed';
|
||||
"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 default slot that contains the label text. 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.
|
||||
*/
|
||||
@@ -2291,9 +2299,9 @@ export namespace Components {
|
||||
*/
|
||||
"label"?: string;
|
||||
/**
|
||||
* 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 ("...").
|
||||
* 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';
|
||||
"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.
|
||||
*/
|
||||
@@ -3165,6 +3173,10 @@ export namespace Components {
|
||||
"trigger": string | undefined;
|
||||
}
|
||||
interface IonToggle {
|
||||
/**
|
||||
* How to control the alignment of the toggle and label on the cross axis. ``"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
*/
|
||||
"alignment": 'start' | 'center';
|
||||
/**
|
||||
* If `true`, the toggle is selected.
|
||||
*/
|
||||
@@ -3186,9 +3198,9 @@ export namespace Components {
|
||||
*/
|
||||
"justify": 'start' | 'end' | 'space-between';
|
||||
/**
|
||||
* Where to place the label relative to the input. `"start"`: The label will appear to the left of the toggle in LTR and to the right in RTL. `"end"`: The label will appear to the right of the toggle 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 ("...").
|
||||
* Where to place the label relative to the input. `"start"`: The label will appear to the left of the toggle in LTR and to the right in RTL. `"end"`: The label will appear to the right of the toggle 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 toggle regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
|
||||
*/
|
||||
"labelPlacement": 'start' | 'end' | 'fixed';
|
||||
"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 default slot that contains the label text. 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.
|
||||
*/
|
||||
@@ -4625,6 +4637,10 @@ declare namespace LocalJSX {
|
||||
"mode"?: "ios" | "md";
|
||||
}
|
||||
interface IonCheckbox {
|
||||
/**
|
||||
* How to control the alignment of the checkbox and label on the cross axis. `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
*/
|
||||
"alignment"?: 'start' | 'center';
|
||||
/**
|
||||
* If `true`, the checkbox is selected.
|
||||
*/
|
||||
@@ -4646,9 +4662,9 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"justify"?: 'start' | 'end' | 'space-between';
|
||||
/**
|
||||
* Where to place the label relative to the checkbox. `"start"`: The label will appear to the left of the checkbox in LTR and to the right in RTL. `"end"`: The label will appear to the right of the checkbox 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 ("...").
|
||||
* Where to place the label relative to the checkbox. `"start"`: The label will appear to the left of the checkbox in LTR and to the right in RTL. `"end"`: The label will appear to the right of the checkbox 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 checkbox regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
|
||||
*/
|
||||
"labelPlacement"?: 'start' | 'end' | 'fixed';
|
||||
"labelPlacement"?: 'start' | 'end' | 'fixed' | 'stacked';
|
||||
/**
|
||||
* Set the `legacy` property to `true` to forcibly use the legacy form control markup. Ionic will only opt checkboxes in to the modern form markup when they are using either the `aria-label` attribute or have text in the default slot. 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.
|
||||
*/
|
||||
@@ -6226,6 +6242,10 @@ declare namespace LocalJSX {
|
||||
"value"?: number;
|
||||
}
|
||||
interface IonRadio {
|
||||
/**
|
||||
* How to control the alignment of the radio and label on the cross axis. `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
*/
|
||||
"alignment"?: 'start' | 'center';
|
||||
/**
|
||||
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
|
||||
*/
|
||||
@@ -6239,9 +6259,9 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"justify"?: 'start' | 'end' | 'space-between';
|
||||
/**
|
||||
* Where to place the label relative to the radio. `"start"`: The label will appear to the left of the radio in LTR and to the right in RTL. `"end"`: The label will appear to the right of the radio 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 ("...").
|
||||
* Where to place the label relative to the radio. `"start"`: The label will appear to the left of the radio in LTR and to the right in RTL. `"end"`: The label will appear to the right of the radio 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 radio regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
|
||||
*/
|
||||
"labelPlacement"?: 'start' | 'end' | 'fixed';
|
||||
"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 default slot that contains the label text. 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.
|
||||
*/
|
||||
@@ -6319,9 +6339,9 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"label"?: string;
|
||||
/**
|
||||
* 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 ("...").
|
||||
* 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';
|
||||
"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.
|
||||
*/
|
||||
@@ -7298,6 +7318,10 @@ declare namespace LocalJSX {
|
||||
"trigger"?: string | undefined;
|
||||
}
|
||||
interface IonToggle {
|
||||
/**
|
||||
* How to control the alignment of the toggle and label on the cross axis. ``"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
*/
|
||||
"alignment"?: 'start' | 'center';
|
||||
/**
|
||||
* If `true`, the toggle is selected.
|
||||
*/
|
||||
@@ -7319,9 +7343,9 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"justify"?: 'start' | 'end' | 'space-between';
|
||||
/**
|
||||
* Where to place the label relative to the input. `"start"`: The label will appear to the left of the toggle in LTR and to the right in RTL. `"end"`: The label will appear to the right of the toggle 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 ("...").
|
||||
* Where to place the label relative to the input. `"start"`: The label will appear to the left of the toggle in LTR and to the right in RTL. `"end"`: The label will appear to the right of the toggle 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 toggle regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
|
||||
*/
|
||||
"labelPlacement"?: 'start' | 'end' | 'fixed';
|
||||
"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 default slot that contains the label text. 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.
|
||||
*/
|
||||
|
||||
@@ -108,6 +108,14 @@
|
||||
@include margin($checkbox-item-label-margin-top, null, $checkbox-item-label-margin-bottom, null);
|
||||
}
|
||||
|
||||
:host(.in-item.checkbox-label-placement-stacked) .label-text-wrapper {
|
||||
@include margin($checkbox-item-label-margin-top, null, $form-control-label-margin, null);
|
||||
}
|
||||
|
||||
:host(.in-item.checkbox-label-placement-stacked) .native-wrapper {
|
||||
@include margin(null, null, $checkbox-item-label-margin-bottom, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* If no label text is placed into the slot
|
||||
* then the element should be hidden otherwise
|
||||
@@ -181,6 +189,17 @@ input {
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
// Align Items
|
||||
// ---------------------------------------------
|
||||
|
||||
:host(.checkbox-alignment-start) .checkbox-wrapper {
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
:host(.checkbox-alignment-center) .checkbox-wrapper {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
// Label Placement - Start
|
||||
// ----------------------------------------------------------------
|
||||
@@ -248,6 +267,24 @@ input {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
// Label Placement - Stacked
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Label is on top of the checkbox.
|
||||
*/
|
||||
:host(.checkbox-label-placement-stacked) .checkbox-wrapper {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
:host(.checkbox-label-placement-stacked) .label-text-wrapper {
|
||||
/**
|
||||
* The margin between the label and
|
||||
* the checkbox should be on the bottom
|
||||
* when the label sits at the top.
|
||||
*/
|
||||
@include margin(null, 0, $form-control-label-margin, 0);
|
||||
}
|
||||
|
||||
// Checked / Indeterminate Checkbox
|
||||
// ---------------------------------------------
|
||||
|
||||
@@ -81,8 +81,9 @@ export class Checkbox implements ComponentInterface {
|
||||
* `"start"`: The label will appear to the left of the checkbox in LTR and to the right in RTL.
|
||||
* `"end"`: The label will appear to the right of the checkbox 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 checkbox regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
|
||||
*/
|
||||
@Prop() labelPlacement: 'start' | 'end' | 'fixed' = 'start';
|
||||
@Prop() labelPlacement: 'start' | 'end' | 'fixed' | 'stacked' = 'start';
|
||||
|
||||
/**
|
||||
* How to pack the label and checkbox within a line.
|
||||
@@ -95,6 +96,13 @@ export class Checkbox implements ComponentInterface {
|
||||
*/
|
||||
@Prop() justify: 'start' | 'end' | 'space-between' = 'space-between';
|
||||
|
||||
/**
|
||||
* How to control the alignment of the checkbox and label on the cross axis.
|
||||
* `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL.
|
||||
* `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
*/
|
||||
@Prop() alignment: 'start' | 'center' = 'center';
|
||||
|
||||
// TODO(FW-3100): remove this
|
||||
/**
|
||||
* Set the `legacy` property to `true` to forcibly use the legacy form control markup.
|
||||
@@ -224,6 +232,7 @@ export class Checkbox implements ComponentInterface {
|
||||
labelPlacement,
|
||||
name,
|
||||
value,
|
||||
alignment,
|
||||
} = this;
|
||||
const mode = getIonMode(this);
|
||||
const path = getSVGPath(mode, indeterminate);
|
||||
@@ -240,6 +249,7 @@ export class Checkbox implements ComponentInterface {
|
||||
'checkbox-indeterminate': indeterminate,
|
||||
interactive: true,
|
||||
[`checkbox-justify-${justify}`]: true,
|
||||
[`checkbox-alignment-${alignment}`]: true,
|
||||
[`checkbox-label-placement-${labelPlacement}`]: true,
|
||||
})}
|
||||
>
|
||||
|
||||
@@ -70,4 +70,21 @@ configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ title, screenshot, co
|
||||
await expect(list).toHaveScreenshot(screenshot(`checkbox-long-label-in-item`));
|
||||
});
|
||||
});
|
||||
|
||||
test.describe(title('checkbox: stacked label in item'), () => {
|
||||
test('should render margins correctly when using stacked label in item', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-list>
|
||||
<ion-item>
|
||||
<ion-checkbox label-placement="stacked">Enable Notifications</ion-checkbox>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
`,
|
||||
config
|
||||
);
|
||||
const list = page.locator('ion-list');
|
||||
await expect(list).toHaveScreenshot(screenshot(`checkbox-stacked-label-in-item`));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
@@ -137,6 +137,27 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Placement Stacked</h1>
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<h2>Align Start</h2>
|
||||
<ion-list>
|
||||
<ion-item>
|
||||
<ion-checkbox label-placement="stacked" alignment="start">Enable Notifications</ion-checkbox>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Align Center</h2>
|
||||
<ion-list>
|
||||
<ion-item>
|
||||
<ion-checkbox label-placement="stacked" alignment="center">Enable Notifications</ion-checkbox>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>States</h1>
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
|
||||
@@ -138,5 +138,31 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-label-fixed-justify-space-between`));
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('checkbox: stacked placement', () => {
|
||||
test('should align the label to the start of the container in the stacked position', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-checkbox label-placement="stacked" alignment="start" style="width: 200px">This is a long label</ion-checkbox>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const checkbox = page.locator('ion-checkbox');
|
||||
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-label-stacked-align-start`));
|
||||
});
|
||||
|
||||
test('should align the label to the center of the container in the stacked position', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-checkbox label-placement="stacked" alignment="center" style="width: 200px">This is a long label</ion-checkbox>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const checkbox = page.locator('ion-checkbox');
|
||||
await expect(checkbox).toHaveScreenshot(screenshot(`checkbox-label-stacked-align-center`));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
@@ -104,6 +104,19 @@
|
||||
<ion-checkbox label-placement="fixed" justify="space-between">Enable Notifications</ion-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Placement Stacked</h1>
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<h2>Align Start</h2>
|
||||
<ion-checkbox label-placement="stacked" alignment="start">Enable Notifications</ion-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Align Center</h2>
|
||||
<ion-checkbox label-placement="stacked" alignment="center">Enable Notifications</ion-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
</body>
|
||||
|
||||
@@ -127,6 +127,14 @@ input {
|
||||
@include margin($radio-item-label-margin-top, null, $radio-item-label-margin-bottom, null);
|
||||
}
|
||||
|
||||
:host(.in-item.radio-label-placement-stacked) .label-text-wrapper {
|
||||
@include margin($radio-item-label-margin-top, null, $form-control-label-margin, null);
|
||||
}
|
||||
|
||||
:host(.in-item.radio-label-placement-stacked) .native-wrapper {
|
||||
@include margin(null, null, $radio-item-label-margin-bottom, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* If no label text is placed into the slot
|
||||
* then the element should be hidden otherwise
|
||||
@@ -160,6 +168,17 @@ input {
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
// Radio Align
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.radio-alignment-start) .radio-wrapper {
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
:host(.radio-alignment-center) .radio-wrapper {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
// Radio Label Placement - Start
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@@ -222,3 +241,22 @@ input {
|
||||
width: 100px;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
// Radio Label Placement - Stacked
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Label is on top of the radio.
|
||||
*/
|
||||
:host(.radio-label-placement-stacked) .radio-wrapper {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
:host(.radio-label-placement-stacked) .label-text-wrapper {
|
||||
/**
|
||||
* The margin between the label and
|
||||
* the radio should be on the bottom
|
||||
* when the label sits on top.
|
||||
*/
|
||||
@include margin(null, 0, $form-control-label-margin, 0);
|
||||
}
|
||||
|
||||
@@ -84,8 +84,9 @@ export class Radio implements ComponentInterface {
|
||||
* `"start"`: The label will appear to the left of the radio in LTR and to the right in RTL.
|
||||
* `"end"`: The label will appear to the right of the radio 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 radio regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
|
||||
*/
|
||||
@Prop() labelPlacement: 'start' | 'end' | 'fixed' = 'start';
|
||||
@Prop() labelPlacement: 'start' | 'end' | 'fixed' | 'stacked' = 'start';
|
||||
|
||||
// TODO FW-3125: Remove the legacy property and implementation
|
||||
/**
|
||||
@@ -110,6 +111,13 @@ export class Radio implements ComponentInterface {
|
||||
*/
|
||||
@Prop() justify: 'start' | 'end' | 'space-between' = 'space-between';
|
||||
|
||||
/**
|
||||
* How to control the alignment of the radio and label on the cross axis.
|
||||
* `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL.
|
||||
* `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
|
||||
*/
|
||||
@Prop() alignment: 'start' | 'center' = 'center';
|
||||
|
||||
/**
|
||||
* Emitted when the styles change.
|
||||
* @internal
|
||||
@@ -250,7 +258,7 @@ export class Radio implements ComponentInterface {
|
||||
}
|
||||
|
||||
private renderRadio() {
|
||||
const { checked, disabled, color, el, justify, labelPlacement, hasLabel, buttonTabindex } = this;
|
||||
const { checked, disabled, color, el, justify, labelPlacement, hasLabel, buttonTabindex, alignment } = this;
|
||||
const mode = getIonMode(this);
|
||||
const inItem = hostContext('ion-item', el);
|
||||
|
||||
@@ -265,6 +273,7 @@ export class Radio implements ComponentInterface {
|
||||
'radio-checked': checked,
|
||||
'radio-disabled': disabled,
|
||||
[`radio-justify-${justify}`]: true,
|
||||
[`radio-alignment-${alignment}`]: true,
|
||||
[`radio-label-placement-${labelPlacement}`]: true,
|
||||
// Focus and active styling should not apply when the radio is in an item
|
||||
'ion-activatable': !inItem,
|
||||
|
||||
@@ -155,6 +155,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Placement Stacked</h1>
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<h2>Align Start</h2>
|
||||
<ion-list>
|
||||
<ion-radio-group>
|
||||
<ion-item>
|
||||
<ion-radio label-placement="stacked" alignment="start">Enable Notifications</ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
</ion-list>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Align Center</h2>
|
||||
<ion-list>
|
||||
<ion-radio-group>
|
||||
<ion-item>
|
||||
<ion-radio label-placement="stacked" alignment="center">Enable Notifications</ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
</ion-list>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>States</h1>
|
||||
<div class="grid">
|
||||
<ion-list>
|
||||
|
||||
@@ -59,4 +59,23 @@ configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ title, screenshot, co
|
||||
await expect(list).toHaveScreenshot(screenshot(`radio-long-label-in-item`));
|
||||
});
|
||||
});
|
||||
|
||||
test.describe(title('radio: stacked label in item'), () => {
|
||||
test('should render margins correctly when using stacked label in item', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-list>
|
||||
<ion-radio-group>
|
||||
<ion-item>
|
||||
<ion-radio label-placement="stacked">Enable Notifications</ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
</ion-list>
|
||||
`,
|
||||
config
|
||||
);
|
||||
const list = page.locator('ion-list');
|
||||
await expect(list).toHaveScreenshot(screenshot(`radio-stacked-label-in-item`));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
@@ -122,6 +122,23 @@
|
||||
</ion-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Placement Stacked</h1>
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<h2>Align Start</h2>
|
||||
<ion-radio-group value="1">
|
||||
<ion-radio label-placement="stacked" alignment="start" value="1">Enable Notifications</ion-radio>
|
||||
</ion-radio-group>
|
||||
</div>
|
||||
|
||||
<div class="grid-item">
|
||||
<h2>Align Center</h2>
|
||||
<ion-radio-group value="1">
|
||||
<ion-radio label-placement="stacked" alignment="center" value="1">Enable Notifications</ion-radio>
|
||||
</ion-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
</body>
|
||||
|
||||
@@ -137,5 +137,34 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
await expect(radio).toHaveScreenshot(screenshot(`radio-label-fixed-justify-space-between`));
|
||||
});
|
||||
});
|
||||
test.describe('radio: stacked placement', () => {
|
||||
test('should align the label to the start of the container in the stacked position', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-radio-group value="1">
|
||||
<ion-radio label-placement="stacked" alignment="start" style="width: 200px" value="1">This is a long label</ion-radio>
|
||||
</ion-radio-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const radio = page.locator('ion-radio');
|
||||
await expect(radio).toHaveScreenshot(screenshot(`radio-label-stacked-align-start`));
|
||||
});
|
||||
|
||||
test('should align the label to the center of the container in the stacked position', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-radio-group value="1">
|
||||
<ion-radio label-placement="stacked" alignment="center" style="width: 200px" value="1">This is a long label</ion-radio>
|
||||
</ion-radio-group>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const radio = page.locator('ion-radio');
|
||||
await expect(radio).toHaveScreenshot(screenshot(`radio-label-stacked-align-center`));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
@@ -34,10 +34,31 @@
|
||||
@include margin(0, 0, 0, 16px);
|
||||
}
|
||||
|
||||
:host(.range-has-pin) {
|
||||
:host(.range-has-pin:not(.range-label-placement-stacked)) {
|
||||
/**
|
||||
* The pin should not overlap any elements that are
|
||||
* above the range. By adding padding to the top of the
|
||||
* range, it provides a buffer for the pin to move into
|
||||
* when it is pressed.
|
||||
*
|
||||
* The padding is not included when the label is stacked
|
||||
* because the pin is below the label.
|
||||
* It still requires a buffer to prevent the pin from
|
||||
* overlapping the range. The buffer is added to the
|
||||
* bottom of the range label instead of the host.
|
||||
*/
|
||||
@include padding($range-ios-padding-vertical + $range-ios-pin-font-size, null, null, null);
|
||||
}
|
||||
|
||||
:host(.range-has-pin.range-label-placement-stacked) .label-text-wrapper {
|
||||
/**
|
||||
* The pin should not overlap the stacked label. By adding
|
||||
* margin to the bottom of the label, it provides a buffer
|
||||
* for the pin to move into when it is pressed.
|
||||
*/
|
||||
@include margin(null, null, $range-ios-padding-vertical + $range-ios-pin-font-size, null);
|
||||
}
|
||||
|
||||
.range-bar-active {
|
||||
bottom: 0;
|
||||
|
||||
|
||||
@@ -52,10 +52,31 @@
|
||||
@include margin(0, 0, 0, 14px);
|
||||
}
|
||||
|
||||
:host(.range-has-pin) {
|
||||
:host(.range-has-pin:not(.range-label-placement-stacked)) {
|
||||
/**
|
||||
* The pin should not overlap any elements that are
|
||||
* above the range. By adding padding to the top of the
|
||||
* range, it provides a buffer for the pin to move into
|
||||
* when it is pressed.
|
||||
*
|
||||
* The padding is not included when the label is stacked
|
||||
* because the pin is below the label.
|
||||
* It still requires a buffer to prevent the pin from
|
||||
* overlapping the range. The buffer is added to the
|
||||
* bottom of the range label instead of the host.
|
||||
*/
|
||||
@include padding($range-md-padding-vertical + $range-md-pin-font-size + $range-md-pin-padding-vertical, null, null, null);
|
||||
}
|
||||
|
||||
:host(.range-has-pin.range-label-placement-stacked) .label-text-wrapper {
|
||||
/**
|
||||
* The pin should not overlap the stacked label. By adding
|
||||
* margin to the bottom of the label, it provides a buffer
|
||||
* for the pin to move into when it is pressed.
|
||||
*/
|
||||
@include margin(null, null, $range-md-padding-vertical + $range-md-pin-font-size + $range-md-pin-padding-vertical, null);
|
||||
}
|
||||
|
||||
.range-bar-active {
|
||||
bottom: 0;
|
||||
|
||||
|
||||
@@ -308,3 +308,24 @@
|
||||
min-width: 100px;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
// Range Label Placement - Stacked
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Label is on top of the range.
|
||||
*/
|
||||
:host(.range-label-placement-stacked) .range-wrapper {
|
||||
flex-direction: column;
|
||||
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
:host(.range-label-placement-stacked) .label-text-wrapper {
|
||||
/**
|
||||
* The margin between the label and
|
||||
* the range should be on the bottom
|
||||
* when the label sits on top.
|
||||
*/
|
||||
@include margin(null, 0, $form-control-label-margin, 0);
|
||||
}
|
||||
|
||||
@@ -228,8 +228,9 @@ export class Range implements ComponentInterface {
|
||||
* `"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.
|
||||
*/
|
||||
@Prop() labelPlacement: 'start' | 'end' | 'fixed' = 'start';
|
||||
@Prop() labelPlacement: 'start' | 'end' | 'fixed' | 'stacked' = 'start';
|
||||
|
||||
/**
|
||||
* Set the `legacy` property to `true` to forcibly use the legacy form control markup.
|
||||
|
||||
@@ -65,6 +65,12 @@
|
||||
<span slot="label">Temperature</span>
|
||||
</ion-range>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<h2>Placement Stacked</h2>
|
||||
<ion-range label-placement="stacked">
|
||||
<span slot="label">Temperature</span>
|
||||
</ion-range>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Label Property</h1>
|
||||
@@ -81,6 +87,10 @@
|
||||
<h2>Placement Fixed</h2>
|
||||
<ion-range label="Temperature" label-placement="fixed"></ion-range>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<h2>Placement Stacked</h2>
|
||||
<ion-range label="Temperature" label-placement="stacked"></ion-range>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Slotted Items</h1>
|
||||
@@ -109,6 +119,14 @@
|
||||
<ion-icon name="flame" slot="end"></ion-icon>
|
||||
</ion-range>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<h2>Placement Stacked</h2>
|
||||
<ion-range label-placement="stacked">
|
||||
<span slot="label">Temperature</span>
|
||||
<ion-icon name="snow" slot="start"></ion-icon>
|
||||
<ion-icon name="flame" slot="end"></ion-icon>
|
||||
</ion-range>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
|
||||
@@ -58,6 +58,22 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
|
||||
await expect(range).toHaveScreenshot(screenshot(`range-no-items-fixed`));
|
||||
});
|
||||
test('should render label above the range slider', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<div id="container" style="padding-inline-start: 20px;">
|
||||
<ion-range label-placement="stacked">
|
||||
<span slot="label">Volume</span>
|
||||
</ion-range>
|
||||
</div>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const range = page.locator('#container');
|
||||
|
||||
await expect(range).toHaveScreenshot(screenshot(`range-no-items-stacked`));
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('range: start and end items', () => {
|
||||
@@ -124,6 +140,22 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
|
||||
await expect(range).toHaveScreenshot(screenshot(`range-items-fixed`));
|
||||
});
|
||||
test('should render label above the range slider', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-range label-placement="stacked">
|
||||
<ion-icon name="volume-off" slot="start"></ion-icon>
|
||||
<ion-icon name="volume-high" slot="end"></ion-icon>
|
||||
<span slot="label">Volume</span>
|
||||
</ion-range>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const range = page.locator('ion-range');
|
||||
|
||||
await expect(range).toHaveScreenshot(screenshot(`range-items-stacked`));
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('range: label prop', () => {
|
||||
@@ -150,6 +182,20 @@ configs().forEach(({ title, screenshot, config }) => {
|
||||
|
||||
await expect(range).toHaveScreenshot(screenshot(`range-label-prop-fixed`));
|
||||
});
|
||||
test('should render label above the range slider', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<div id="container" style="padding-inline-start: 20px;">
|
||||
<ion-range label-placement="stacked" label="Volume"></ion-range>
|
||||
</div>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const range = page.locator('#container');
|
||||
|
||||
await expect(range).toHaveScreenshot(screenshot(`range-label-prop-stacked`));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -171,4 +217,28 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, co
|
||||
await expect(range).toHaveScreenshot(screenshot(`range-label-truncate`));
|
||||
});
|
||||
});
|
||||
|
||||
test.describe(title('range: with pin'), () => {
|
||||
test('should render pin below a stacked label', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<div id="container" style="padding-inline-start: 20px;">
|
||||
<ion-range label-placement="stacked" pin="true">
|
||||
<span slot="label">Volume</span>
|
||||
</ion-range>
|
||||
</div>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const container = page.locator('#container');
|
||||
const range = page.locator('ion-range');
|
||||
const knob = range.locator('.range-knob-handle');
|
||||
|
||||
// Force the pin to show
|
||||
await knob.evaluate((el: HTMLElement) => el.classList.add('ion-focused'));
|
||||
|
||||
await expect(container).toHaveScreenshot(screenshot(`range-stacked-pin`));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.5 KiB |