diff --git a/core/src/components/range/range.scss b/core/src/components/range/range.common.scss similarity index 77% rename from core/src/components/range/range.scss rename to core/src/components/range/range.common.scss index a6e67940f5c..8a914c77e49 100644 --- a/core/src/components/range/range.scss +++ b/core/src/components/range/range.common.scss @@ -1,4 +1,4 @@ -@import "../../themes/native/native.globals"; +@import "../../themes/mixins"; @import "./range.vars.scss"; // Range @@ -18,7 +18,6 @@ * @prop --pin-background: Background of the range pin (only available in MD mode) * @prop --pin-color: Color of the range pin (only available in MD mode) */ - --knob-handle-size: calc(var(--knob-size) * 2); display: flex; position: relative; @@ -26,10 +25,7 @@ flex: 3; align-items: center; - font-family: $font-family-base; - user-select: none; - z-index: $z-index-item-input; } :host(.range-disabled) { @@ -40,10 +36,6 @@ flex: initial; } -::slotted(ion-icon[slot]) { - font-size: 24px; -} - .range-slider { position: relative; @@ -214,8 +206,6 @@ * only the label would show and users * would not be able to see the range. */ - max-width: 200px; - text-overflow: ellipsis; white-space: nowrap; @@ -254,15 +244,6 @@ 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, $form-control-label-margin, 0, 0); -} - // Range Label Placement - End // ---------------------------------------------------------------- @@ -274,27 +255,9 @@ 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, $form-control-label-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, $form-control-label-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. @@ -321,26 +284,4 @@ :host(.range-label-placement-stacked) .label-text-wrapper { @include transform-origin(start, top); - @include transform(scale(#{$form-control-label-stacked-scale})); - - /** - * 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); - - /** - * Label text should not extend - * beyond the bounds of the range. - */ - max-width: calc(100% / #{$form-control-label-stacked-scale}); -} - -:host(.in-item.range-label-placement-stacked) .label-text-wrapper { - @include margin($range-item-label-margin-top, null, $form-control-label-margin, null); -} - -:host(.in-item.range-label-placement-stacked) .native-wrapper { - @include margin(null, null, $range-item-label-margin-bottom, null); } diff --git a/core/src/components/range/range.ionic.scss b/core/src/components/range/range.ionic.scss new file mode 100644 index 00000000000..8d75a8ff4c4 --- /dev/null +++ b/core/src/components/range/range.ionic.scss @@ -0,0 +1,217 @@ +@use "../../themes/ionic/ionic.globals.scss" as globals; +@import "./range.common"; + +// Ionic Range +// -------------------------------------------------- + +:host { + --knob-border-radius: #{globals.$ion-border-radius-full}; + --knob-background: #{globals.$ion-primitives-base-white}; + --knob-box-shadow: none; + --knob-size: #{globals.$ion-scale-600}; + --knob-handle-size: #{globals.$ion-scale-1000}; + --bar-height: #{globals.$ion-scale-200}; + --bar-background: #{globals.$ion-primitives-neutral-100}; + --bar-background-active: #{globals.ion-color(primary, base)}; + --bar-border-radius: #{globals.$ion-border-radius-400}; + --height: #{globals.$ion-scale-1000}; + + @include globals.typography(globals.$ion-body-md-regular); + + z-index: globals.$ion-z-index-100; +} + +:host(.range-item-start-adjustment) { + @include padding(null, null, null, globals.$ion-space-600); +} + +:host(.range-item-end-adjustment) { + @include padding(null, globals.$ion-space-600, null, null); +} + +:host(.ion-color) .range-bar-active, +:host(.ion-color) .range-tick-active { + background: globals.current-color(base); +} + +::slotted(ion-icon[slot]) { + font-size: globals.$ion-font-size-600; +} + +::slotted([slot="start"]) { + @include margin(0, globals.$ion-space-400, 0, 0); +} + +::slotted([slot="end"]) { + @include margin(0, 0, 0, globals.$ion-space-400); +} + +::slotted([slot="label"]) { + max-width: globals.$ion-scale-5000; +} + +: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(calc(globals.$ion-space-200 + globals.dynamic-font(12px)), 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, calc(globals.$ion-space-200 + globals.dynamic-font(12px)), null); +} + +.range-bar-active { + bottom: 0; + + width: auto; + + background: var(--bar-background-active); + + &.has-ticks { + @include border-radius(0); + @include margin(null, calc(-1 * globals.$ion-scale-100 * 0.5), null, calc(-1 * globals.$ion-scale-100 * 0.5)); + } +} + +.range-tick { + @include margin-horizontal(calc(globals.$ion-scale-100 * -0.5), null); + @include border-radius(globals.$ion-border-radius-0); + + position: absolute; + top: calc((var(--height) * 0.5) - (globals.$ion-scale-300 * 0.5)); + + width: globals.$ion-scale-100; + height: globals.$ion-scale-300; + + background: globals.$ion-primitives-neutral-100; + pointer-events: none; +} + +.range-tick-active { + background: var(--bar-background-active); +} + +.range-pin { + @include transform(translate3d(0, 100%, 0), scale(0.01)); + @include padding(globals.$ion-space-200, globals.$ion-space-200, globals.$ion-space-200, globals.$ion-space-200); + + min-width: globals.$ion-scale-700; + + transition: transform 120ms ease; + + background: transparent; + + font-size: globals.dynamic-font(12px); + + text-align: center; +} + +.range-knob { + border-width: globals.$ion-border-size-025; + border-style: globals.$ion-border-style-solid; + border-color: globals.ion-color(primary, base); + box-sizing: border-box; +} + +/** + * The -100% ensures the pin sits on top + * of the range-knob-handle container. + * We apply 11px so that the pin + * text is closer to the knob inside of the container. + * We also apply the 11px here instead of using "top" + * otherwise the pin text will translate below the knob + * when the text is scaled. + */ +.range-knob-pressed .range-pin, +.range-knob-handle.ion-focused .range-pin { + transform: translate3d(0, calc(-100% + 11px), 0) scale(1); +} + +// Ionic Range: Disabled (based on iOS Range) +// -------------------------------------------------- +// When the range is disabled, the entire range, +// range label, any slotted labels, and any slotted +// icons need to receive the same opacity. + +:host(.range-disabled) { + opacity: 0.3; +} + +// Range Label Placement - Start +// ---------------------------------------------------------------- + +: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, globals.$ion-space-400, 0, 0); +} + +// Range Label Placement - End +// ---------------------------------------------------------------- + +:host(.range-label-placement-end) .label-text-wrapper { + /** + * The margin between the label and + * the range should be on the start + * when the label sits at the end. + */ + @include margin(0, 0, 0, globals.$ion-space-400); +} + +// 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, globals.$ion-space-400, 0, 0); +} + +// Range Label Placement - Stacked +// ---------------------------------------------------------------- + +:host(.range-label-placement-stacked) .label-text-wrapper { + @include transform(scale(0.75)); + + /** + * The margin between the label and + * the range should be on the bottom + * when the label sits on top. + */ + @include margin(null, 0, globals.$ion-space-400, 0); + + /** + * Label text should not extend + * beyond the bounds of the range. + */ + max-width: calc(100% / 0.75); +} + +:host(.in-item.range-label-placement-stacked) .label-text-wrapper { + @include margin(globals.$ion-space-250, null, globals.$ion-space-400, null); +} + +:host(.in-item.range-label-placement-stacked) .native-wrapper { + @include margin(null, null, globals.$ion-space-0, null); +} diff --git a/core/src/components/range/range.ios.scss b/core/src/components/range/range.ios.scss index ad715ded787..06a678a97e3 100644 --- a/core/src/components/range/range.ios.scss +++ b/core/src/components/range/range.ios.scss @@ -1,4 +1,4 @@ -@import "./range"; +@import "./range.native"; @import "./range.ios.vars"; // iOS Range diff --git a/core/src/components/range/range.md.scss b/core/src/components/range/range.md.scss index df6bea37546..a9298300314 100644 --- a/core/src/components/range/range.md.scss +++ b/core/src/components/range/range.md.scss @@ -1,4 +1,4 @@ -@import "./range"; +@import "./range.native"; @import "./range.md.vars"; // Material Design Range diff --git a/core/src/components/range/range.native.scss b/core/src/components/range/range.native.scss new file mode 100644 index 00000000000..f7bb5172305 --- /dev/null +++ b/core/src/components/range/range.native.scss @@ -0,0 +1,83 @@ +@import "range.common"; +@import "../../themes/native/native.globals"; +@import "./range.vars.scss"; + +:host { + --knob-handle-size: calc(var(--knob-size) * 2); + + font-family: $font-family-base; + + z-index: $z-index-item-input; +} + +::slotted(ion-icon[slot]) { + font-size: 24px; +} + +::slotted([slot="label"]) { + max-width: 200px; +} + +// Range Label Placement - Start +// ---------------------------------------------------------------- + +: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, $form-control-label-margin, 0, 0); +} + +// Range Label Placement - End +// ---------------------------------------------------------------- + +:host(.range-label-placement-end) .label-text-wrapper { + /** + * The margin between the label and + * the range should be on the start + * when the label sits at the end. + */ + @include margin(0, 0, 0, $form-control-label-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, $form-control-label-margin, 0, 0); +} + +// Range Label Placement - Stacked +// ---------------------------------------------------------------- + +:host(.range-label-placement-stacked) .label-text-wrapper { + @include transform(scale(#{$form-control-label-stacked-scale})); + + /** + * 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); + + /** + * Label text should not extend + * beyond the bounds of the range. + */ + max-width: calc(100% / #{$form-control-label-stacked-scale}); +} + +:host(.in-item.range-label-placement-stacked) .label-text-wrapper { + @include margin($range-item-label-margin-top, null, $form-control-label-margin, null); +} + +:host(.in-item.range-label-placement-stacked) .native-wrapper { + @include margin(null, null, $range-item-label-margin-bottom, null); +} diff --git a/core/src/components/range/range.tsx b/core/src/components/range/range.tsx index af2f2519435..9b749941919 100644 --- a/core/src/components/range/range.tsx +++ b/core/src/components/range/range.tsx @@ -43,7 +43,7 @@ import type { styleUrls: { ios: 'range.ios.scss', md: 'range.md.scss', - ionic: 'range.md.scss', + ionic: 'range.ionic.scss', }, shadow: true, }) diff --git a/core/src/components/range/test/basic/range.e2e.ts b/core/src/components/range/test/basic/range.e2e.ts index f864f2d0493..dcd86272412 100644 --- a/core/src/components/range/test/basic/range.e2e.ts +++ b/core/src/components/range/test/basic/range.e2e.ts @@ -1,7 +1,7 @@ import { expect } from '@playwright/test'; import { configs, test } from '@utils/test/playwright'; -configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => { +configs({ modes: ['ios', 'md', 'ionic-md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => { test.describe(title('range: basic'), () => { test.beforeEach(async ({ page }) => { await page.goto('/src/components/range/test/basic', config); diff --git a/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-default-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-default-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 00000000000..dd38b5d296f Binary files /dev/null and b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-default-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-default-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-default-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 00000000000..23bdef180b9 Binary files /dev/null and b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-default-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-default-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-default-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 00000000000..2084b203b43 Binary files /dev/null and b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-default-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-dual-knobs-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-dual-knobs-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 00000000000..70d9ed4e920 Binary files /dev/null and b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-dual-knobs-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-dual-knobs-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-dual-knobs-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 00000000000..1e27e871bea Binary files /dev/null and b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-dual-knobs-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-dual-knobs-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-dual-knobs-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 00000000000..82611b46e80 Binary files /dev/null and b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-dual-knobs-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-pin-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-pin-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 00000000000..b32c6748093 Binary files /dev/null and b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-pin-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-pin-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-pin-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 00000000000..9023918ae96 Binary files /dev/null and b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-pin-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-pin-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-pin-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 00000000000..6415db4bfcb Binary files /dev/null and b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-pin-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-ticks-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-ticks-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 00000000000..745736714d0 Binary files /dev/null and b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-ticks-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-ticks-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-ticks-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 00000000000..a8b3025458c Binary files /dev/null and b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-ticks-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-ticks-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-ticks-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 00000000000..74a3f734d2a Binary files /dev/null and b/core/src/components/range/test/basic/range.e2e.ts-snapshots/range-ticks-ionic-md-ltr-light-Mobile-Safari-linux.png differ