Skip to content

Commit

Permalink
feat(range): component can be used outside of ion-item (#26479)
Browse files Browse the repository at this point in the history
  • Loading branch information
liamdebeasi committed Dec 15, 2022
1 parent 6c82435 commit 49baad8
Show file tree
Hide file tree
Showing 277 changed files with 2,236 additions and 542 deletions.
4 changes: 2 additions & 2 deletions angular/src/directives/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1602,13 +1602,13 @@ mouse drag, touch gesture, or keyboard interaction.

@ProxyCmp({
defineCustomElementFn: undefined,
inputs: ['activeBarStart', 'color', 'debounce', 'disabled', 'dualKnobs', 'max', 'min', 'mode', 'name', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'value']
inputs: ['activeBarStart', 'color', 'debounce', 'disabled', 'dualKnobs', 'labelPlacement', 'legacy', 'max', 'min', 'mode', 'name', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'value']
})
@Component({
selector: 'ion-range',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
inputs: ['activeBarStart', 'color', 'debounce', 'disabled', 'dualKnobs', 'max', 'min', 'mode', 'name', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'value']
inputs: ['activeBarStart', 'color', 'debounce', 'disabled', 'dualKnobs', 'labelPlacement', 'legacy', 'max', 'min', 'mode', 'name', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'value']
})
export class IonRange {
protected el: HTMLElement;
Expand Down
2 changes: 2 additions & 0 deletions core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,8 @@ ion-range,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secon
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,labelPlacement,"end" | "fixed" | "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
16 changes: 16 additions & 0 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2196,6 +2196,14 @@ export namespace Components {
* Show two knobs.
*/
"dualKnobs": boolean;
/**
* 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 ("...").
*/
"labelPlacement": 'start' | 'end' | 'fixed';
/**
* 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 @@ -6102,6 +6110,14 @@ declare namespace LocalJSX {
* Show two knobs.
*/
"dualKnobs"?: boolean;
/**
* 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 ("...").
*/
"labelPlacement"?: 'start' | 'end' | 'fixed';
/**
* 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
9 changes: 9 additions & 0 deletions core/src/components/item/item.scss
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,15 @@
overflow: initial;
}

/**
* The shadow of the range knob should
* not be clipped by the item.
*/
// TODO FW-2997 This should check for a slotted ion-range
:host(.item-has-modern-range) {
overflow: initial;
}

// Item: Color
// --------------------------------------------------

Expand Down
9 changes: 7 additions & 2 deletions core/src/components/item/item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,11 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
}

private hasModernInput(): boolean {
const input = this.el.querySelector('ion-input:not(.legacy-input)');
return input !== null;
return this.el.querySelector('ion-input:not(.legacy-input)') !== null;
}

private hasModernRange(): boolean {
return this.el.querySelector('ion-range:not(.legacy-range)') !== null;
}

private getFirstInput(): HTMLIonInputElement | HTMLIonTextareaElement {
Expand Down Expand Up @@ -401,6 +404,7 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
const fillValue = fill || 'none';
const inList = hostContext('ion-list', this.el);
const hasModernInput = this.hasModernInput();
const hasModernRange = this.hasModernRange();

return (
<Host
Expand All @@ -421,6 +425,7 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
'ion-focusable': this.focusable,
'item-rtl': document.dir === 'rtl',
'item-has-modern-input': hasModernInput,
'item-has-modern-range': hasModernRange,
}),
}}
role={inList ? 'listitem' : null}
Expand Down
4 changes: 2 additions & 2 deletions core/src/components/progress-bar/test/basic/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
<ion-progress-bar id="progressBar"></ion-progress-bar>

<ion-item>
<ion-range pin="true" value="0" id="progressValue">
<ion-range legacy="true" pin="true" value="0" id="progressValue">
<ion-label slot="start">0</ion-label>
<ion-label slot="end">100</ion-label>
</ion-range>
Expand Down Expand Up @@ -113,7 +113,7 @@
<ion-progress-bar class="progressBarBuffer" value="0.20" buffer="0.4" reversed="true"></ion-progress-bar>

<ion-item>
<ion-range pin="true" value="0" id="progressValueBuffer">
<ion-range legacy="true" pin="true" value="0" id="progressValueBuffer">
<ion-label slot="start">0</ion-label>
<ion-label slot="end">100</ion-label>
</ion-range>
Expand Down
8 changes: 6 additions & 2 deletions core/src/components/range/range.ios.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
--bar-background-active: #{ion-color(primary, base)};
--bar-border-radius: #{$range-ios-bar-border-radius};
--height: #{$range-ios-slider-height};
--margin: 16px;
}

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

Expand All @@ -24,11 +28,11 @@
}

::slotted([slot="start"]) {
@include margin(0, 16px, 0, 0);
@include margin(0, var(--margin), 0, 0);
}

::slotted([slot="end"]) {
@include margin(0, 0, 0, 16px);
@include margin(0, 0, 0, var(--margin));
}

:host(.range-has-pin) {
Expand Down
18 changes: 14 additions & 4 deletions core/src/components/range/range.md.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,22 @@
--height: #{$range-md-slider-height};
--pin-background: #{ion-color(primary, base)};
--pin-color: #{ion-color(primary, contrast)};
--margin: 14px;

@include padding($range-md-padding-vertical, $range-md-padding-horizontal);

// TODO FW-2997 Apply this to the start/end slots, and the native wrapper
font-size: $range-md-pin-font-size;
}

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

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

:host(.ion-color) .range-bar {
background: current-color(base, 0.26);
}
Expand All @@ -37,11 +47,11 @@
}

::slotted([slot="start"]) {
@include margin(0, 14px, 0, 0);
@include margin(0, var(--margin), 0, 0);
}

::slotted([slot="end"]) {
@include margin(0, 0, 0, 14px);
@include margin(0, 0, 0, var(--margin));
}

:host(.range-has-pin) {
Expand Down
138 changes: 138 additions & 0 deletions core/src/components/range/range.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @prop --pin-color: Color of the range pin (only available in MD mode)
*/
--knob-handle-size: calc(var(--knob-size) * 2);
--margin: 8px;

display: flex;
position: relative;
Expand Down Expand Up @@ -172,3 +173,140 @@
:host(.in-item) ::slotted(ion-label) {
align-self: center;
}

// Range Wrapper
// --------------------------------------------------

.range-wrapper {
display: flex;

position: relative;

flex-grow: 1;

align-items: center;

height: 100%;
}

// Range Label
// ----------------------------------------------------------------

/**
* When the range is disabled, only the text
* receives an opacity. The range changes color instead.
*/
:host(.range-disabled) .label-text-wrapper {
opacity: 0.3;
}

::slotted([slot="label"]) {

/**
* Label text should not extend
* beyond the bounds of the range.
* However, we do not set the max
* width to 100% because then
* only the label would show and users
* would not be able to see the range.
*/
max-width: 200px;

/**
* This ensures that double tapping this text
* clicks the <label> and focuses the range
* when a screen reader is enabled.
*/
pointer-events: none;

text-overflow: ellipsis;

white-space: nowrap;

overflow: hidden;
}


/**
* If no label text is placed into the slot
* then the element should be hidden otherwise
* there will be additional margins added.
*/
.label-text-wrapper-hidden {
display: none;
}

// Range Native Wrapper
// ----------------------------------------------------------------

.native-wrapper {
display: flex;

flex-grow: 1;

align-items: center;
}

// Range Label Placement - Start
// ----------------------------------------------------------------

/**
* Label is on the left of the range in LTR and
* on the right in RTL.
*/
:host(.range-label-placement-start) .range-wrapper {
flex-direction: row;
}

:host(.range-label-placement-start) .label-text-wrapper {
/**
* The margin between the label and
* the range should be on the end
* when the label sits at the start.
*/
@include margin(0, var(--margin), 0, 0);
}

// Range Label Placement - End
// ----------------------------------------------------------------

/**
* Label is on the right of the range in LTR and
* on the left in RTL.
*/
:host(.range-label-placement-end) .range-wrapper {
flex-direction: row-reverse;
}

/**
* The margin between the label and
* the range should be on the start
* when the label sits at the end.
*/
:host(.range-label-placement-end) .label-text-wrapper {
@include margin(0, 0, 0, var(--margin));
}

// Range Label Placement - Fixed
// ----------------------------------------------------------------

:host(.range-label-placement-fixed) .label-text-wrapper {
/**
* The margin between the label and
* the range should be on the end
* when the label sits at the start.
*/
@include margin(0, var(--margin), 0, 0);
}

/**
* Label is on the left of the range in LTR and
* on the right in RTL. Label also has a fixed width.
*/
:host(.range-label-placement-fixed) .label-text-wrapper {
flex: 0 0 100px;

width: 100px;
min-width: 100px;
max-width: 200px;
}

0 comments on commit 49baad8

Please sign in to comment.