diff --git a/src/components/calcite-slider/calcite-slider.e2e.ts b/src/components/calcite-slider/calcite-slider.e2e.ts index e2c099d2109..12491f577f7 100644 --- a/src/components/calcite-slider/calcite-slider.e2e.ts +++ b/src/components/calcite-slider/calcite-slider.e2e.ts @@ -48,8 +48,8 @@ describe("calcite-slider", () => { > `); - const maxButton = await page.find("calcite-slider >>> .thumb--max"); - const minButton = await page.find("calcite-slider >>> .thumb--min"); + const maxButton = await page.find("calcite-slider >>> .thumb--value"); + const minButton = await page.find("calcite-slider >>> .thumb--minValue"); expect(minButton).toEqualAttribute("role", "slider"); expect(maxButton).toEqualAttribute("role", "slider"); expect(minButton).toEqualAttribute("aria-label", "Min Label"); @@ -112,7 +112,7 @@ describe("calcite-slider", () => { `); const slider = await page.find("calcite-slider"); - const handle = await page.find("calcite-slider >>> .thumb--max"); + const handle = await page.find("calcite-slider >>> .thumb--value"); await page.waitForChanges(); let value = await slider.getProperty("value"); expect(value).toBe(20); diff --git a/src/components/calcite-slider/calcite-slider.scss b/src/components/calcite-slider/calcite-slider.scss index 0aa119fd9cb..b2a95dc4de0 100644 --- a/src/components/calcite-slider/calcite-slider.scss +++ b/src/components/calcite-slider/calcite-slider.scss @@ -9,6 +9,15 @@ $thumb-padding: ($thumb-size - $handle-size) / 2; $track-height: 2px; $tick-height: 4px; +@mixin histogramEndcaps() { + .tick__label--min, + .tick__label--max { + margin: 6px -3px; + font-weight: 300; + color: var(--calcite-ui-text-3); + } +} + :host { display: block; padding: $handle-size / 2 0; @@ -26,76 +35,189 @@ $tick-height: 4px; * with text elements to prevent overlap */ :host([label-handles]), -:host([precise]) { +:host([precise]:not([precise="false"])) { margin-top: $handle-size + $thumb-padding; } :host([label-ticks]), -:host([precise][is-range]) { +:host([precise]:not([precise="false"])[is-range]) { margin-bottom: $handle-size + $thumb-padding; } -:host([precise][label-handles]) { +:host([precise]:not([precise="false"])[label-handles]) { margin-top: $thumb-size + $thumb-padding; } -:host([precise][label-handles][is-range]) { +:host([precise]:not([precise="false"])[label-handles][is-range]) { margin-bottom: $thumb-size + $thumb-padding; } -// focus styles -.thumb { - @include focus-style-base(); - &:focus { - @include focus-style-outset(); - } -} - .thumb { position: absolute; - height: $thumb-size; - width: $thumb-size; - margin: -15px; - box-sizing: border-box; border: none; background: transparent; cursor: pointer; font-family: inherit; z-index: 2; -} + outline: none; + padding: 0; + display: flex; + flex-direction: column; + align-items: center; + transform: translate(7px, -8px); -.handle { - position: absolute; - top: 0; - left: 0; - height: $handle-size; - width: $handle-size; - margin: $thumb-padding; - box-sizing: border-box; - border-radius: 100%; - background-color: var(--calcite-ui-foreground-1); - border: 2px solid var(--calcite-ui-text-3); - transition: border 0.25s ease, background-color 0.25s ease, - box-shadow 0.25s ease; -} - -.handle__label { - position: absolute; - left: 0; - bottom: $thumb-size; - width: $thumb-size; - height: 0.75em; - @include font-size(-3); - font-weight: 500; - line-height: 1; - color: var(--calcite-ui-text-3); - text-align: center; -} + .handle__label { + transition: transform 150ms; + @include font-size(-4); + font-weight: 500; + line-height: 1; + color: var(--calcite-ui-text-2); + margin-bottom: 5px; + &.static, + &.transformed { + opacity: 0; + position: absolute; + top: 0; + } + &--minValue.hyphen::after { + content: "\2014"; + display: inline-block; + width: 1em; + } + &--value.hyphen::before { + content: "\2014"; + display: inline-block; + width: 1em; + } + } + + .handle { + @include focus-style-base(); + height: $handle-size; + width: $handle-size; + box-sizing: border-box; + border-radius: 100%; + background-color: var(--calcite-ui-foreground-1); + box-shadow: 0 0 0 2px var(--calcite-ui-text-3) inset; + transition: border 0.25s ease, background-color 0.25s ease, + box-shadow 0.25s ease; + } + + .handle-extension { + width: 2px; + height: $thumb-padding; + background-color: var(--calcite-ui-text-3); + } -.thumb:hover .handle { - border-width: 3px; - border-color: var(--calcite-ui-blue-1); - @include shadow(1, "hover"); + &:hover { + .handle { + box-shadow: 0 0 0 3px var(--calcite-ui-blue-1) inset; + } + .handle-extension { + background-color: var(--calcite-ui-blue-1); + } + } + + &:focus { + .handle { + @include focus-style-outset(); + outline-offset: 2px; + } + .handle-extension { + background-color: var(--calcite-ui-blue-1); + } + } +} +.thumb--minValue { + transform: translate(-7px, -8px); +} +:host([label-handles]) { + .thumb { + transform: translate(50%, -25px); + } + .thumb--minValue { + transform: translate(-50%, -25px); + } +} +:host([has-histogram][label-handles]) { + .thumb { + transform: translate(50%, -8px); + .handle__label { + margin-bottom: unset; + margin-top: 5px; + } + } + .thumb--minValue { + transform: translate(-50%, -8px); + } +} +:host([precise]:not([precise="false"])) { + .thumb { + transform: translate(7px, -21px); + } + .thumb--minValue { + transform: translate(-7px, -2px); + .handle__label { + margin-bottom: unset; + margin-top: 5px; + } + } +} +:host([has-histogram][precise]:not([precise="false"])) { + .thumb { + transform: translate(7px, -2px); + } + .thumb--minValue { + transform: translate(-50%, -2px); + } +} +:host([ticks][precise]:not([precise="false"])) { + .thumb { + transform: translate(7px, -20px); + } + .thumb--minValue { + transform: translate(-7px, -3px); + } +} +:host([has-histogram][ticks][precise]:not([precise="false"])) { + .thumb { + transform: translate(7px, -3px); + } + .thumb--minValue { + transform: translate(-50%, -3px); + } +} +:host([label-handles][precise]:not([precise="false"])) { + .thumb { + transform: translate(50%, -38px); + } + .thumb--minValue { + transform: translate(-50%, -2px); + } +} +:host([has-histogram][label-handles][precise]:not([precise="false"])) { + .thumb { + transform: translate(50%, -2px); + } + .thumb--minValue { + transform: translate(-50%, -2px); + } +} +:host([ticks][label-handles][precise]:not([precise="false"])) { + .thumb { + transform: translate(50%, -37px); + } + .thumb--minValue { + transform: translate(-50%, -3px); + } +} +:host([has-histogram][ticks][label-handles][precise]:not([precise="false"])) { + .thumb { + transform: translate(50%, -3px); + } + .thumb--minValue { + transform: translate(-50%, -3px); + } } .thumb:focus, @@ -103,48 +225,16 @@ $tick-height: 4px; z-index: 3; .handle { background-color: var(--calcite-ui-blue-1); - border-color: var(--calcite-ui-blue-1); @include shadow(1, "press"); } } -.thumb--precise { - margin-top: -$thumb-size; -} - -.thumb--precise:after { - content: ""; - display: block; - position: absolute; - top: $handle-size; - left: 50%; - width: 2px; - height: $thumb-padding; - background-color: var(--calcite-ui-text-3); - margin-left: -1px; - margin-top: $thumb-padding; - z-index: 1; -} - .thumb:hover.thumb--precise:after, .thumb:focus.thumb--precise:after, .thumb--active.thumb--precise:after { background-color: var(--calcite-ui-blue-1); } -.thumb--precise.thumb--min { - margin-top: -$track-height; - .handle__label { - bottom: unset; - top: $thumb-size; - } -} - -.thumb--precise.thumb--min:after { - top: 0; - margin-top: 0; -} - .track { height: $track-height; border-radius: 0; @@ -181,10 +271,8 @@ $tick-height: 4px; width: 2px; height: $tick-height; left: var(--calcite-ui-border-1-offset); - margin-left: -3px; + margin-left: -2px; border: 1px solid var(--calcite-ui-foreground-1); - border-right-width: 2px; - border-left-width: 2px; background-color: var(--calcite-ui-border-1); } @@ -194,9 +282,9 @@ $tick-height: 4px; .tick__label { position: absolute; - @include font-size(-3); + @include font-size(-4); font-weight: 500; - color: var(--calcite-ui-text-3); + color: var(--calcite-ui-text-2); width: 4em; margin: $thumb-size / 2 -2em; text-align: center; @@ -208,6 +296,7 @@ $tick-height: 4px; left: 0; margin: $thumb-size / 2 -3px; text-align: left; + transition: opacity 150ms; } .tick__label--max { @@ -215,6 +304,14 @@ $tick-height: 4px; right: 0; margin: $thumb-size / 2 -3px; text-align: right; + transition: opacity 50ms; +} + +:host([has-histogram][label-handles]) { + @include histogramEndcaps(); +} +:host([has-histogram][precise]:not([precise="false"])) { + @include histogramEndcaps(); } .graph { diff --git a/src/components/calcite-slider/calcite-slider.tsx b/src/components/calcite-slider/calcite-slider.tsx index 3096ef4a1aa..cbf071b39b4 100644 --- a/src/components/calcite-slider/calcite-slider.tsx +++ b/src/components/calcite-slider/calcite-slider.tsx @@ -10,12 +10,14 @@ import { h, State, VNode, + Watch, } from "@stencil/core"; import { guid } from "../../utils/guid"; import { getKey } from "../../utils/key"; -type activeSliderProperty = "minValue" | "maxValue" | "value" | "minMaxValue"; import { DataSeries } from "../../interfaces/Graph"; +type activeSliderProperty = "minValue" | "maxValue" | "value" | "minMaxValue"; + @Component({ tag: "calcite-slider", styleUrl: "calcite-slider.scss", @@ -68,6 +70,11 @@ export class CalciteSlider { @Prop() precise?: boolean; /** Display a histogram above the slider */ @Prop() histogram?: DataSeries; + @Watch("histogram") histogramWatcher(newHistogram) { + this.hasHistogram = newHistogram ? true : false; + } + /** Indicates if a histogram is present */ + @Prop({ reflect: true, mutable: true }) hasHistogram: boolean = false; //-------------------------------------------------------------------------- // // Lifecycle @@ -80,17 +87,456 @@ export class CalciteSlider { if (this.snap) { this.value = this.getClosestStep(this.value); } + if (this.histogram) { + this.hasHistogram = true; + } this.calciteSliderUpdate.emit(); } + componentDidRender() { + const valueOffset = this.adjustObscuredEndcapLabel("value"); + if (this.isRange && this.labelHandles) { + const minValueOffset = this.adjustObscuredEndcapLabel("minValue"); + if (!(this.precise && this.isRange && !this.hasHistogram)) { + this.hyphenateCollidingRangeHandleLabels(valueOffset, minValueOffset); + } + } + this.hideObscuredBoundingTickLabels(); + } + render() { const id = this.el.id || this.guid; const min = this.minValue || this.min; const max = this.maxValue || this.value; const maxProp = this.isRange ? "maxValue" : "value"; + const value = this[maxProp]; const left = `${this.getUnitInterval(min) * 100}%`; const right = `${100 - this.getUnitInterval(max) * 100}%`; + const handle = ( + + ); + + const labeledHandle = ( + + ); + + const histogramLabeledHandle = ( + + ); + + const preciseHandle = ( + + ); + + const histogramPreciseHandle = ( + + ); + + const labeledPreciseHandle = ( + + ); + + const histogramLabeledPreciseHandle = ( + + ); + + const minHandle = ( + + ); + + const minLabeledHandle = ( + + ); + + const minHistogramLabeledHandle = ( + + ); + + const minPreciseHandle = ( + + ); + + const minLabeledPreciseHandle = ( + + ); + return ( {this.renderGraph()} @@ -102,98 +548,63 @@ export class CalciteSlider { style={{ left, right }} />
- {this.tickValues.map((number) => ( + {this.tickValues.map((tick) => ( = min && number <= max, + "tick--active": tick >= min && tick <= max, }} style={{ - left: `${this.getUnitInterval(number) * 100}%`, + left: `${this.getUnitInterval(tick) * 100}%`, }} > - {this.labelTicks ? ( - - {number} - - ) : ( - "" - )} + {this.renderTickLabel(tick)} ))}
- {this.isRange ? ( - - ) : ( - "" - )} - + {!this.precise && !this.labelHandles && this.isRange && minHandle} + {!this.hasHistogram && + !this.precise && + this.labelHandles && + this.isRange && + minLabeledHandle} + {this.precise && !this.labelHandles && this.isRange && minPreciseHandle} + {this.precise && + this.labelHandles && + this.isRange && + minLabeledPreciseHandle} + {this.hasHistogram && + !this.precise && + this.labelHandles && + this.isRange && + minHistogramLabeledHandle} + + {!this.precise && !this.labelHandles && handle} + {!this.hasHistogram && + !this.precise && + this.labelHandles && + labeledHandle} + {!this.hasHistogram && + this.precise && + !this.labelHandles && + preciseHandle} + {this.hasHistogram && + this.precise && + !this.labelHandles && + histogramPreciseHandle} + {!this.hasHistogram && + this.precise && + this.labelHandles && + labeledPreciseHandle} + {this.hasHistogram && + !this.precise && + this.labelHandles && + histogramLabeledHandle} + {this.hasHistogram && + this.precise && + this.labelHandles && + histogramLabeledPreciseHandle}
); } @@ -205,12 +616,95 @@ export class CalciteSlider { width={300} height={48} data={this.histogram} - highlightMin={this.isRange ? this.minValue : null} - highlightMax={this.isRange ? this.maxValue : null} + highlightMin={this.isRange ? this.minValue : this.min} + highlightMax={this.isRange ? this.maxValue : this.value} /> ) : null; } + + private renderTickLabel(tick: number): VNode { + const isMinTickLabel = tick === this.min; + const isMaxTickLabel = tick === this.max; + const tickLabel = ( + + {tick.toLocaleString()} + + ); + if (this.labelTicks && !this.hasHistogram && !this.isRange) { + return tickLabel; + } + if ( + this.labelTicks && + !this.hasHistogram && + this.isRange && + !this.precise && + !this.labelHandles + ) { + return tickLabel; + } + if ( + this.labelTicks && + !this.hasHistogram && + this.isRange && + !this.precise && + this.labelHandles + ) { + return tickLabel; + } + if ( + this.labelTicks && + !this.hasHistogram && + this.isRange && + this.precise && + (isMinTickLabel || isMaxTickLabel) + ) { + return tickLabel; + } + if ( + this.labelTicks && + this.hasHistogram && + !this.precise && + !this.labelHandles + ) { + return tickLabel; + } + if ( + this.labelTicks && + this.hasHistogram && + this.precise && + !this.labelHandles && + (isMinTickLabel || isMaxTickLabel) + ) { + return tickLabel; + } + if ( + this.labelTicks && + this.hasHistogram && + !this.precise && + this.labelHandles && + (isMinTickLabel || isMaxTickLabel) + ) { + return tickLabel; + } + if ( + this.labelTicks && + this.hasHistogram && + this.precise && + this.labelHandles && + (isMinTickLabel || isMaxTickLabel) + ) { + return tickLabel; + } + return null; + } + //-------------------------------------------------------------------------- // // Event Listeners @@ -462,6 +956,14 @@ export class CalciteSlider { } return num; } + private getFontSizeForElement(element: HTMLElement) { + return Number( + window + .getComputedStyle(element) + .getPropertyValue("font-size") + .match(/\d+/)[0] + ); + } /** * Get position of value along range as fractional value * @return {number} number in the unit interval [0,1] @@ -472,4 +974,295 @@ export class CalciteSlider { const range = this.max - this.min; return (num - this.min) / range; } + private adjustObscuredEndcapLabel(name: "value" | "minValue"): number { + const handle: HTMLButtonElement | null = this.el.shadowRoot.querySelector( + `.thumb--${name}` + ); + const label: HTMLSpanElement | null = this.el.shadowRoot.querySelector( + `.handle__label--${name}` + ); + const labelStatic: HTMLSpanElement | null = this.el.shadowRoot.querySelector( + `.handle__label--${name}.static` + ); + const labelTransformed: HTMLSpanElement | null = this.el.shadowRoot.querySelector( + `.handle__label--${name}.transformed` + ); + if (handle && label && labelStatic && labelTransformed) { + const labelOffset = this.getLabelOffset(handle, labelStatic); + if (labelOffset) { + (label as HTMLSpanElement).style.transform = `translateX(${labelOffset}px)`; + (labelTransformed as HTMLSpanElement).style.transform = `translateX(${labelOffset}px)`; + } else { + (label as HTMLSpanElement).style.transform = ""; + (labelTransformed as HTMLSpanElement).style.transform = ""; + } + return Math.abs(labelOffset); + } + return 0; + } + private hyphenateCollidingRangeHandleLabels( + valueLabelOffset: number, + minValueLabelOffset: number + ) { + const minValueLabel: HTMLSpanElement | null = this.el.shadowRoot.querySelector( + `.handle__label--minValue` + ); + const minValueLabelStatic: HTMLSpanElement | null = this.el.shadowRoot.querySelector( + `.handle__label--minValue.static` + ); + const minValueLabelTransformed: HTMLSpanElement | null = this.el.shadowRoot.querySelector( + `.handle__label--minValue.transformed` + ); + const valueLabel: HTMLSpanElement | null = this.el.shadowRoot.querySelector( + `.handle__label--value` + ); + const valueLabelStatic: HTMLSpanElement | null = this.el.shadowRoot.querySelector( + `.handle__label--value.static` + ); + const valueLabelTransformed: HTMLSpanElement | null = this.el.shadowRoot.querySelector( + `.handle__label--value.transformed` + ); + const labelFontSize = this.getFontSizeForElement(minValueLabel); + if ( + minValueLabel && + valueLabel && + minValueLabelStatic && + valueLabelStatic && + minValueLabelTransformed && + valueLabelTransformed + ) { + if ( + valueLabelOffset > 0 || + valueLabel.getBoundingClientRect().right > + this.el.getBoundingClientRect().right + ) { + const valueLabelTransformedOverlap = this.getRangeLabelOverlap( + minValueLabelStatic, + valueLabelTransformed + ); + if (valueLabelTransformedOverlap > 0) { + minValueLabel.classList.add("hyphen"); + minValueLabel.classList.add("max-offset"); + minValueLabel.style.marginRight = `${ + valueLabelTransformedOverlap * 2 - labelFontSize + }px`; + } else { + minValueLabel.classList.remove("hyphen"); + minValueLabel.classList.remove("max-offset"); + minValueLabel.style.marginRight = "0px"; + } + valueLabel.style.marginLeft = "0px"; + } else if ( + minValueLabelOffset > 0 || + minValueLabel.getBoundingClientRect().left < + this.el.getBoundingClientRect().left + ) { + const minValueLabelTransformedOverlap = this.getRangeLabelOverlap( + minValueLabelTransformed, + valueLabelStatic + ); + if (minValueLabelTransformedOverlap > 0) { + valueLabel.classList.add("hyphen"); + valueLabel.classList.add("min-offset"); + valueLabel.style.marginLeft = `${ + minValueLabelTransformedOverlap * 2 - labelFontSize + }px`; + } else { + valueLabel.classList.remove("hyphen"); + valueLabel.classList.remove("min-offset"); + valueLabel.style.marginLeft = "0px"; + } + minValueLabel.style.marginRight = "0px"; + } else { + const labelStaticOverlap = this.getRangeLabelOverlap( + minValueLabelStatic, + valueLabelStatic + ); + if (labelStaticOverlap > 0) { + minValueLabel.classList.add("hyphen"); + valueLabel.classList.add("hyphen"); + minValueLabel.style.marginRight = `${ + labelStaticOverlap - labelFontSize + }px`; + valueLabel.style.marginLeft = `${ + labelStaticOverlap - labelFontSize + }px`; + } else { + minValueLabel.classList.remove("hyphen"); + valueLabel.classList.remove("hyphen"); + minValueLabel.style.marginRight = "0px"; + valueLabel.style.marginLeft = "0px"; + } + } + } + } + /** + * Hides bounding tick labels that are obscured by either handle. + */ + private hideObscuredBoundingTickLabels() { + if ( + !this.hasHistogram && + !this.isRange && + !this.labelHandles && + !this.precise + ) { + return; + } + if ( + !this.hasHistogram && + !this.isRange && + this.labelHandles && + !this.precise + ) { + return; + } + if ( + !this.hasHistogram && + !this.isRange && + !this.labelHandles && + this.precise + ) { + return; + } + if ( + !this.hasHistogram && + !this.isRange && + this.labelHandles && + this.precise + ) { + return; + } + if (!this.hasHistogram && this.isRange && !this.precise) { + return; + } + if (this.hasHistogram && !this.precise && !this.labelHandles) { + return; + } + + const minHandle: HTMLButtonElement | null = this.el.shadowRoot.querySelector( + ".thumb--minValue" + ); + const maxHandle: HTMLButtonElement | null = this.el.shadowRoot.querySelector( + ".thumb--value" + ); + + const minTickLabel: HTMLSpanElement | null = this.el.shadowRoot.querySelector( + ".tick__label--min" + ); + const maxTickLabel: HTMLSpanElement | null = this.el.shadowRoot.querySelector( + ".tick__label--max" + ); + + if (!minHandle && maxHandle && minTickLabel && maxTickLabel) { + if (this.isMinTickLabelObscured(minTickLabel, maxHandle)) { + minTickLabel.style.opacity = "0"; + } else { + minTickLabel.style.opacity = "1"; + } + if (this.isMaxTickLabelObscured(maxTickLabel, maxHandle)) { + maxTickLabel.style.opacity = "0"; + } else { + maxTickLabel.style.opacity = "1"; + } + } + + if (minHandle && maxHandle && minTickLabel && maxTickLabel) { + if ( + this.isMinTickLabelObscured(minTickLabel, minHandle) || + this.isMinTickLabelObscured(minTickLabel, maxHandle) + ) { + minTickLabel.style.opacity = "0"; + } else { + minTickLabel.style.opacity = "1"; + } + if ( + this.isMaxTickLabelObscured(maxTickLabel, minHandle) || + (this.isMaxTickLabelObscured(maxTickLabel, maxHandle) && + this.hasHistogram) + ) { + maxTickLabel.style.opacity = "0"; + } else { + maxTickLabel.style.opacity = "1"; + } + } + } + /** + * Returns an integer representing the number of pixels to offset handle labels based on desired position behavior. + * @internal + */ + private getLabelOffset( + handle: HTMLButtonElement, + label: HTMLSpanElement + ): number { + const handleBounds = handle.getBoundingClientRect(); + const labelBounds = label.getBoundingClientRect(); + const hostBounds = this.el.getBoundingClientRect(); + if ( + handleBounds.left < labelBounds.left || + handleBounds.right > labelBounds.right + ) { + return 0; + } + if (labelBounds.left < hostBounds.left) { + const offset = Math.floor(hostBounds.left - labelBounds.left - 7); + return offset; + } + if ( + labelBounds.right > hostBounds.right || + labelBounds.right > handleBounds.right + ) { + const offset = Math.floor(-(labelBounds.right - hostBounds.right) + 7); + return offset; + } + return 0; + } + /** + * Returns an integer representing the number of pixels that the two given span elements are overlapping, taking into account + * a space in between the two spans equal to the font-size set on them to account for the space needed to render a hyphen. + * @param minValueLabel + * @param valueLabel + */ + private getRangeLabelOverlap( + minValueLabel: HTMLSpanElement, + valueLabel: HTMLSpanElement + ): number { + const minValueLabelBounds = minValueLabel.getBoundingClientRect(); + const valueLabelBounds = valueLabel.getBoundingClientRect(); + const minValueLabelFontSize = this.getFontSizeForElement(minValueLabel); + const rangeLabelOverlap = + minValueLabelBounds.right + minValueLabelFontSize - valueLabelBounds.left; + return rangeLabelOverlap > 0 ? rangeLabelOverlap : 0; + } + /** + * Returns a boolean value representing if the minLabel span element is obscured (being overlapped) by the given handle button element. + * @param minLabel + * @param handle + */ + private isMinTickLabelObscured( + minLabel: HTMLSpanElement, + handle: HTMLButtonElement + ): boolean { + const minLabelBounds = minLabel.getBoundingClientRect(); + const handleBounds = handle.getBoundingClientRect(); + if (handleBounds.left < minLabelBounds.right) { + return true; + } + return false; + } + /** + * Returns a boolean value representing if the maxLabel span element is obscured (being overlapped) by the given handle button element. + * @param maxLabel + * @param handle + */ + private isMaxTickLabelObscured( + maxLabel: HTMLSpanElement, + handle: HTMLButtonElement + ): boolean { + const maxLabelBounds = maxLabel.getBoundingClientRect(); + const handleBounds = handle.getBoundingClientRect(); + if (handleBounds.right > maxLabelBounds.left) { + return true; + } + return false; + } } diff --git a/src/demos/calcite-radio-button.html b/src/demos/calcite-radio-button.html index 3f9a5d0f4ae..9503d87c70d 100644 --- a/src/demos/calcite-radio-button.html +++ b/src/demos/calcite-radio-button.html @@ -65,10 +65,13 @@

Scale s


- Stencil - React + Stencil + + React + Ember - Angular + Angular +

Scale m (default)

Stencil @@ -91,10 +94,13 @@

Scale l


- Stencil - React + Stencil + + React + Ember - Angular + Angular +

Uses value as label if missing

@@ -121,8 +127,10 @@

Only one checked value (first wins, first two checked)


- - + + + +

Only one checked value (first wins, second two checked)

@@ -131,34 +139,44 @@

Only one checked value (first wins, second two checked)


- - + + + +

Only one checked value (first wins, first and last checked)


- - - + + + + + +

Only one checked value (first wins, all checked)


- - - + + + + + + - -
+
+

Scale s

- Stencil + Stencil + React Ember - Angular + Angular +
@@ -166,100 +184,142 @@

Scale s

Stencil React - Ember - Angular + Ember + + Angular +

Scale m (default)

- Stencil + Stencil + React Ember Angular
- Stencil - React - Ember - Angular + Stencil + + React + + Ember + + Angular +

Scale l

- Stencil - React - Ember - Angular + Stencil + + React + Ember + Angular + -
+
- Stencil - React - Ember - Angular + + Stencil + + React + Ember + + Angular +

Uses value as label if missing

- - - + + + -
+
- - - + + + + + +

None checked

- - - + + + -
+
- - - + + + + + +

Only one checked value (first wins, first two checked)

- - - + + + + + -
+
- - - + + + + +

Only one checked value (first wins, second two checked)

- - - + + + + + + -
+
- - - + + + + +

Only one checked value (first wins, first and last checked)

- - - + + + + + + -
+
- - - + + +

Only one checked value (first wins, all checked)

- - - + + + + + + -
+
- - - + + + + +
diff --git a/src/demos/calcite-slider.html b/src/demos/calcite-slider.html index 2ff9fb90187..e85c0e5fa4e 100644 --- a/src/demos/calcite-slider.html +++ b/src/demos/calcite-slider.html @@ -7,11 +7,24 @@ Calcite Slider