diff --git a/packages/components/src/range-control/index.js b/packages/components/src/range-control/index.js index 90f55c3c0cd555..543d25accfcfbd 100644 --- a/packages/components/src/range-control/index.js +++ b/packages/components/src/range-control/index.js @@ -99,9 +99,7 @@ function RangeControl( const inputSliderValue = isValueReset ? '' : currentValue; - const rangeFillValue = isValueReset - ? floatClamp( max / 2, min, max ) - : value; + const rangeFillValue = isValueReset ? ( max - min ) / 2 + min : value; const calculatedFillValue = ( ( value - min ) / ( max - min ) ) * 100; const fillValue = isValueReset ? 50 : calculatedFillValue; diff --git a/packages/components/src/range-control/rail.js b/packages/components/src/range-control/rail.js index 93db3351c68121..51c188e8f46493 100644 --- a/packages/components/src/range-control/rail.js +++ b/packages/components/src/range-control/rail.js @@ -64,33 +64,33 @@ function useMarks( { marks, min = 0, max = 100, step = 1, value = 0 } ) { return []; } - const isCustomMarks = Array.isArray( marks ); - - const markCount = Math.round( ( max - min ) / step ); - const marksArray = isCustomMarks - ? marks - : [ ...Array( markCount + 1 ) ].map( ( _, index ) => ( { - value: index, - } ) ); - - const enhancedMarks = marksArray.map( ( mark, index ) => { - const markValue = mark.value !== undefined ? mark.value : value; + const range = max - min; + if ( ! Array.isArray( marks ) ) { + marks = []; + const count = 1 + Math.round( range / step ); + while ( count > marks.push( { value: step * marks.length + min } ) ); + } + const placedMarks = []; + marks.forEach( ( mark, index ) => { + if ( mark.value < min || mark.value > max ) { + return; + } const key = `mark-${ index }`; - const isFilled = markValue * step + min <= value; - const offset = `${ ( markValue / markCount ) * 100 }%`; + const isFilled = mark.value <= value; + const offset = `${ ( ( mark.value - min ) / range ) * 100 }%`; const offsetStyle = { [ isRTL ? 'right' : 'left' ]: offset, }; - return { + placedMarks.push( { ...mark, isFilled, key, style: offsetStyle, - }; + } ); } ); - return enhancedMarks; + return placedMarks; } diff --git a/packages/components/src/range-control/stories/index.js b/packages/components/src/range-control/stories/index.js index d3dca6a1ca1a35..e91fde04b8fbc3 100644 --- a/packages/components/src/range-control/stories/index.js +++ b/packages/components/src/range-control/stories/index.js @@ -75,6 +75,11 @@ const DefaultExample = () => { ); }; +const RangeControlLabeledByMarksType = ( props ) => { + const label = Array.isArray( props.marks ) ? 'Custom' : 'Automatic'; + return ; +}; + export const _default = () => { return ; }; @@ -131,33 +136,51 @@ export const withReset = () => { return ; }; -export const customMarks = () => { - const marks = [ - { - value: 0, - label: '0', - }, - { - value: 1, - label: '1', - }, - { - value: 2, - label: '2', - }, - { - value: 8, - label: '8', - }, - { - value: 10, - label: '10', - }, +export const marks = () => { + const marksBase = [ + { value: 0, label: '0' }, + { value: 1, label: '1' }, + { value: 2, label: '2' }, + { value: 8, label: '8' }, + { value: 10, label: '10' }, + ]; + const marksWithDecimal = [ + ...marksBase, + { value: 3.5, label: '3.5' }, + { value: 5.8, label: '5.8' }, + ]; + const marksWithNegatives = [ + ...marksBase, + { value: -1, label: '-1' }, + { value: -2, label: '-2' }, + { value: -4, label: '-4' }, + { value: -8, label: '-8' }, ]; + const stepInteger = { min: 0, max: 10, step: 1 }; + const stepDecimal = { min: 0, max: 10, step: 0.1 }; + const minNegative = { min: -10, max: 10, step: 1 }; + const rangeNegative = { min: -10, max: -1, step: 1 }; + + // use a short alias to keep formatting to fewer lines + const Range = RangeControlLabeledByMarksType; return ( - +

Integer Step

+ + + +

Decimal Step

+ + + +

Negative Minimum

+ + + +

Negative Range

+ +
); }; diff --git a/packages/components/src/range-control/styles/range-control-styles.js b/packages/components/src/range-control/styles/range-control-styles.js index 0fa3fbbeb233d9..4f49803f81d945 100644 --- a/packages/components/src/range-control/styles/range-control-styles.js +++ b/packages/components/src/range-control/styles/range-control-styles.js @@ -11,11 +11,11 @@ import NumberControl from '../../number-control'; import { color, reduceMotion, rtl, space } from '../../utils/style-mixins'; const rangeHeight = () => css( { height: 30, minHeight: 30 } ); +const thumbSize = 20; export const Root = styled.span` -webkit-tap-highlight-color: transparent; box-sizing: border-box; - cursor: pointer; align-items: flex-start; display: inline-flex; justify-content: flex-start; @@ -115,6 +115,7 @@ export const Track = styled.span` export const MarksWrapper = styled.span` box-sizing: border-box; display: block; + pointer-events: none; position: relative; width: 100%; user-select: none; @@ -166,7 +167,7 @@ export const ThumbWrapper = styled.span` align-items: center; box-sizing: border-box; display: flex; - height: 20px; + height: ${ thumbSize }px; justify-content: center; margin-top: 5px; outline: 0; @@ -174,7 +175,7 @@ export const ThumbWrapper = styled.span` position: absolute; top: 0; user-select: none; - width: 20px; + width: ${ thumbSize }px; ${ rtl( { marginLeft: -10 } ) } `; @@ -202,7 +203,6 @@ export const Thumb = styled.span` box-sizing: border-box; height: 100%; outline: 0; - pointer-events: none; position: absolute; user-select: none; width: 100%; @@ -216,13 +216,13 @@ export const InputRange = styled.input` display: block; height: 100%; left: 0; - margin: 0; + margin: 0 -${ thumbSize / 2 }px; opacity: 0; outline: none; position: absolute; right: 0; top: 0; - width: 100%; + width: calc( 100% + ${ thumbSize }px ); `; const tooltipShow = ( { show } ) => {