UNPKG

@ionic/core

Version:
689 lines (627 loc) • 17.8 kB
/** * Convert a font size to a dynamic font size. * Fonts that participate in Dynamic Type should use * dynamic font sizes. * @param size - The initial font size including the unit (i.e. px or pt) * @param unit (optional) - The unit to convert to. Use this if you want to * convert to a unit other than $baselineUnit. */ /** * Convert a font size to a dynamic font size but impose * a maximum font size. * @param size - The initial font size including the unit (i.e. px or pt) * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale). * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to * convert to a unit other than $baselineUnit. */ /** * Convert a font size to a dynamic font size but impose * a minimum font size. * @param size - The initial font size including the unit (i.e. px or pt) * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale). * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to * convert to a unit other than $baselineUnit. */ /** * Convert a font size to a dynamic font size but impose * maximum and minimum font sizes. * @param size - The initial font size including the unit (i.e. px or pt) * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale). * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale). * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to * convert to a unit other than $baselineUnit. */ /** * A heuristic that applies CSS to tablet * viewports. * * Usage: * @include tablet-viewport() { * :host { * background-color: green; * } * } */ /** * A heuristic that applies CSS to mobile * viewports (i.e. phones, not tablets). * * Usage: * @include mobile-viewport() { * :host { * background-color: blue; * } * } */ :host { /** * @prop --bar-background: Background of the range bar * @prop --bar-background-active: Background of the active range bar * @prop --bar-height: Height of the range bar * @prop --bar-border-radius: Border radius of the range bar * @prop --height: Height of the range * @prop --knob-background: Background of the range knob * @prop --knob-border-radius: Border radius of the range knob * @prop --knob-box-shadow: Box shadow of the range knob * @prop --knob-size: Size of the range knob * @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; flex: 3; align-items: center; font-family: var(--ion-font-family, inherit); user-select: none; z-index: 2; } :host(.range-disabled) { pointer-events: none; } ::slotted(ion-label) { flex: initial; } ::slotted(ion-icon[slot]) { font-size: 24px; } .range-slider { position: relative; flex: 1; width: 100%; height: var(--height); contain: size layout style; cursor: grab; touch-action: pan-y; } :host(.range-pressed) .range-slider { cursor: grabbing; } .range-pin { position: absolute; background: var(--ion-color-base); color: var(--ion-color-contrast); text-align: center; box-sizing: border-box; } .range-knob-handle { top: calc((var(--height) - var(--knob-handle-size)) / 2); -webkit-margin-start: calc(0px - var(--knob-handle-size) / 2); margin-inline-start: calc(0px - var(--knob-handle-size) / 2); display: flex; position: absolute; justify-content: center; width: var(--knob-handle-size); height: var(--knob-handle-size); text-align: center; } .range-knob-handle { inset-inline-start: 0; } :host-context([dir=rtl]) .range-knob-handle { /* stylelint-disable-next-line property-disallowed-list */ left: unset; } [dir=rtl] .range-knob-handle { /* stylelint-disable-next-line property-disallowed-list */ left: unset; } @supports selector(:dir(rtl)) { .range-knob-handle:dir(rtl) { /* stylelint-disable-next-line property-disallowed-list */ left: unset; } } .range-knob-handle:active, .range-knob-handle:focus { outline: none; } .range-bar-container { border-radius: var(--bar-border-radius); top: calc((var(--height) - var(--bar-height)) / 2); position: absolute; width: 100%; height: var(--bar-height); } .range-bar-container { inset-inline-start: 0; } :host-context([dir=rtl]) .range-bar-container { /* stylelint-disable-next-line property-disallowed-list */ left: unset; } [dir=rtl] .range-bar-container { /* stylelint-disable-next-line property-disallowed-list */ left: unset; } @supports selector(:dir(rtl)) { .range-bar-container:dir(rtl) { /* stylelint-disable-next-line property-disallowed-list */ left: unset; } } .range-bar { border-radius: var(--bar-border-radius); position: absolute; width: 100%; height: var(--bar-height); background: var(--bar-background); pointer-events: none; } .range-knob { border-radius: var(--knob-border-radius); top: calc(50% - var(--knob-size) / 2); position: absolute; width: var(--knob-size); height: var(--knob-size); background: var(--knob-background); box-shadow: var(--knob-box-shadow); z-index: 2; pointer-events: none; } .range-knob { inset-inline-start: calc(50% - var(--knob-size) / 2); } :host-context([dir=rtl]) .range-knob { /* stylelint-disable-next-line property-disallowed-list */ left: unset; } [dir=rtl] .range-knob { /* stylelint-disable-next-line property-disallowed-list */ left: unset; } @supports selector(:dir(rtl)) { .range-knob:dir(rtl) { /* stylelint-disable-next-line property-disallowed-list */ left: unset; } } :host(.range-pressed) .range-bar-active { will-change: left, right; } :host(.in-item) { width: 100%; } /** * Range can be slotted * in components such as item and * toolbar which is why we do not * limit the below behavior to just ion-item. */ :host([slot=start]), :host([slot=end]) { width: auto; } :host(.in-item) ::slotted(ion-label) { align-self: center; } .range-wrapper { display: flex; position: relative; flex-grow: 1; align-items: center; height: inherit; } ::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; 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; } .native-wrapper { display: flex; flex-grow: 1; align-items: center; } /** * 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. */ -webkit-margin-start: 0; margin-inline-start: 0; -webkit-margin-end: 16px; margin-inline-end: 16px; margin-top: 0; margin-bottom: 0; } /** * 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 { -webkit-margin-start: 16px; margin-inline-start: 16px; -webkit-margin-end: 0; margin-inline-end: 0; margin-top: 0; margin-bottom: 0; } :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. */ -webkit-margin-start: 0; margin-inline-start: 0; -webkit-margin-end: 16px; margin-inline-end: 16px; margin-top: 0; margin-bottom: 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; } /** * 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 { transform-origin: left top; transform: scale(0.75); /** * The margin between the label and * the range should be on the bottom * when the label sits on top. */ margin-left: 0; margin-right: 0; margin-bottom: 16px; /** * Label text should not extend * beyond the bounds of the range. */ max-width: calc(100% / 0.75); } :host-context([dir=rtl]):host(.range-label-placement-stacked) .label-text-wrapper, :host-context([dir=rtl]).range-label-placement-stacked .label-text-wrapper { transform-origin: right top; } @supports selector(:dir(rtl)) { :host(.range-label-placement-stacked:dir(rtl)) .label-text-wrapper { transform-origin: right top; } } :host(.in-item.range-label-placement-stacked) .label-text-wrapper { margin-top: 10px; margin-bottom: 16px; } :host(.in-item.range-label-placement-stacked) .native-wrapper { margin-bottom: 0px; } /** * Convert a font size to a dynamic font size. * Fonts that participate in Dynamic Type should use * dynamic font sizes. * @param size - The initial font size including the unit (i.e. px or pt) * @param unit (optional) - The unit to convert to. Use this if you want to * convert to a unit other than $baselineUnit. */ /** * Convert a font size to a dynamic font size but impose * a maximum font size. * @param size - The initial font size including the unit (i.e. px or pt) * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale). * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to * convert to a unit other than $baselineUnit. */ /** * Convert a font size to a dynamic font size but impose * a minimum font size. * @param size - The initial font size including the unit (i.e. px or pt) * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale). * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to * convert to a unit other than $baselineUnit. */ /** * Convert a font size to a dynamic font size but impose * maximum and minimum font sizes. * @param size - The initial font size including the unit (i.e. px or pt) * @param minScale - The minimum scale of the font (i.e. 0.8 for a minimum 80% scale). * @param maxScale - The maximum scale of the font (i.e. 2.5 for a maximum 250% scale). * @param unit (optional) - The unit to convert the initial font size to. Use this if you want to * convert to a unit other than $baselineUnit. */ /** * A heuristic that applies CSS to tablet * viewports. * * Usage: * @include tablet-viewport() { * :host { * background-color: green; * } * } */ /** * A heuristic that applies CSS to mobile * viewports (i.e. phones, not tablets). * * Usage: * @include mobile-viewport() { * :host { * background-color: blue; * } * } */ /** * 18px was chosen so the knob and its focus/active * effects do not get cut off by the item. */ :host { --knob-border-radius: 50%; --knob-background: var(--bar-background-active); --knob-box-shadow: none; --knob-size: 18px; --bar-height: 2px; --bar-background: rgba(var(--ion-color-primary-rgb, 0, 84, 233), 0.26); --bar-background-active: var(--ion-color-primary, #0054e9); --bar-border-radius: 0; --height: 42px; --pin-background: var(--ion-color-primary, #0054e9); --pin-color: var(--ion-color-primary-contrast, #fff); } ::slotted(:not(ion-icon)[slot=start]), ::slotted(:not(ion-icon)[slot=end]), .native-wrapper { font-size: 0.75rem; } :host(.range-item-start-adjustment) { -webkit-padding-start: 18px; padding-inline-start: 18px; } :host(.range-item-end-adjustment) { -webkit-padding-end: 18px; padding-inline-end: 18px; } :host(.ion-color) .range-bar { background: rgba(var(--ion-color-base-rgb), 0.26); } :host(.ion-color) .range-bar-active, :host(.ion-color) .range-knob, :host(.ion-color) .range-knob::before, :host(.ion-color) .range-pin, :host(.ion-color) .range-pin::before, :host(.ion-color) .range-tick { background: var(--ion-color-base); color: var(--ion-color-contrast); } ::slotted([slot=start]) { -webkit-margin-start: 0; margin-inline-start: 0; -webkit-margin-end: 14px; margin-inline-end: 14px; margin-top: 0; margin-bottom: 0; } ::slotted([slot=end]) { -webkit-margin-start: 14px; margin-inline-start: 14px; -webkit-margin-end: 0; margin-inline-end: 0; margin-top: 0; margin-bottom: 0; } :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. */ padding-top: 1.75rem; } :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. */ margin-bottom: 1.75rem; } .range-bar-active { bottom: 0; width: auto; background: var(--bar-background-active); } .range-knob { transform: scale(0.67); transition-duration: 120ms; transition-property: transform, background-color, border; transition-timing-function: ease; z-index: 2; } .range-knob::before { border-radius: 50%; position: absolute; width: var(--knob-size); height: var(--knob-size); transform: scale(1); transition: 0.267s cubic-bezier(0, 0, 0.58, 1); background: var(--knob-background); content: ""; opacity: 0.13; pointer-events: none; } .range-knob::before { inset-inline-start: 0; } .range-tick { position: absolute; top: calc((var(--height) - var(--bar-height)) / 2); width: var(--bar-height); height: var(--bar-height); background: var(--bar-background-active); z-index: 1; pointer-events: none; } .range-tick-active { background: transparent; } .range-pin { padding-left: 0; padding-right: 0; padding-top: 8px; padding-bottom: 8px; border-radius: 50%; transform: translate3d(0, 0, 0) scale(0.01); display: flex; align-items: center; justify-content: center; /** * The dimensions of the range need * to scale with the size of the text * which is why we use dynamic dimensions here. */ width: 1.75rem; height: 1.75rem; transition: transform 120ms ease, background 120ms ease; background: var(--pin-background); color: var(--pin-color); } .range-pin::before { /** * The -1px here moves the ::before * psuedo-element down to create a uniform pin shape. */ bottom: -1px; -webkit-margin-start: -13px; margin-inline-start: -13px; /* stylelint-disable-next-line property-disallowed-list */ border-radius: 50% 50% 50% 0; position: absolute; width: 26px; height: 26px; transform: rotate(-45deg); transition: background 120ms ease; background: var(--pin-background); content: ""; z-index: -1; } .range-pin::before { inset-inline-start: 50%; } :host-context([dir=rtl]) .range-pin::before { /* stylelint-disable-next-line property-disallowed-list */ left: unset; } [dir=rtl] .range-pin::before { /* stylelint-disable-next-line property-disallowed-list */ left: unset; } @supports selector(:dir(rtl)) { .range-pin::before:dir(rtl) { /* stylelint-disable-next-line property-disallowed-list */ left: unset; } } /** * Move the pin up by its full height * plus a few pixels so the tip is above * (but not touching) the knob. */ .range-knob-pressed .range-pin, .range-knob-handle.ion-focused .range-pin { transform: translate3d(0, calc(-100% + 4px), 0) scale(1); } @media (any-hover: hover) { .range-knob-handle:hover .range-knob:before { transform: scale(2); opacity: 0.13; } } .range-knob-handle.ion-activated .range-knob:before, .range-knob-handle.ion-focused .range-knob:before, .range-knob-handle.range-knob-pressed .range-knob:before { transform: scale(2); } .range-knob-handle.ion-focused .range-knob::before { opacity: 0.13; } .range-knob-handle.ion-activated .range-knob::before, .range-knob-handle.range-knob-pressed .range-knob::before { opacity: 0.25; } :host(:not(.range-has-pin)) .range-knob-pressed .range-knob, :host(:not(.range-has-pin)) .range-knob-handle.ion-focused .range-knob { transform: scale(1); } :host(.range-disabled) .range-bar-active, :host(.range-disabled) .range-bar, :host(.range-disabled) .range-tick { background-color: var(--ion-color-step-250, var(--ion-background-color-step-250, #bfbfbf)); } :host(.range-disabled) .range-knob { transform: scale(0.55); outline: 5px solid #fff; background-color: var(--ion-color-step-250, var(--ion-background-color-step-250, #bfbfbf)); } :host(.range-disabled) .label-text-wrapper, :host(.range-disabled) ::slotted([slot=start]), :host(.range-disabled) ::slotted([slot=end]) { opacity: 0.38; }