diff --git a/packages/react-component-library/src/components/RangeSlider/Handle.tsx b/packages/react-component-library/src/components/RangeSlider/Handle.tsx index 6cc10b29fb..3b0a9d2fc4 100644 --- a/packages/react-component-library/src/components/RangeSlider/Handle.tsx +++ b/packages/react-component-library/src/components/RangeSlider/Handle.tsx @@ -4,6 +4,8 @@ import { GetHandleProps, SliderItem } from 'react-compound-slider' import { useThresholdColor } from './useThresholdColor' import { RangeSliderPositionBag, RangeSliderValueFormatter } from '.' import { StyledHandle } from './partials/StyledHandle' +import { StyledPercentage } from './partials/StyledPercentage' +import { StyledValue } from './partials/StyledValue' interface HandleProps { activeHandleID: string @@ -41,10 +43,15 @@ export const Handle: React.FC = ({ aria-valuenow={value} $left={`${percent}%`} {...getHandleProps(id)} - data-value={formatValue(positionBag)} - data-percent={`${Math.floor(percent)}%`} data-testid="rangeslider-handle" - /> + > + + {`${Math.floor(percent)}%`} + + + {formatValue(positionBag)} + + ) } diff --git a/packages/react-component-library/src/components/RangeSlider/RangeSlider.stories.tsx b/packages/react-component-library/src/components/RangeSlider/RangeSlider.stories.tsx index da374ba9cf..bb3175844d 100644 --- a/packages/react-component-library/src/components/RangeSlider/RangeSlider.stories.tsx +++ b/packages/react-component-library/src/components/RangeSlider/RangeSlider.stories.tsx @@ -12,6 +12,19 @@ export default { }, } as Meta +const disableColorContrastRule = { + a11y: { + config: { + rules: [ + { + id: 'color-contrast', + enabled: false, + }, + ], + }, + }, +} + export const Default: Story = (props) => (
@@ -25,6 +38,8 @@ Default.args = { tracksLeft: true, } +Default.parameters = disableColorContrastRule + export const MultipleHandles: Story = (props) => (
= (props) => ( MultipleHandles.storyName = 'Multiple handles' +MultipleHandles.parameters = disableColorContrastRule + export const SingleThreshold: Story = (props) => (
= (props) => ( SingleThreshold.storyName = 'Single threshold' +SingleThreshold.parameters = disableColorContrastRule + export const DoubleThreshold: Story = (props) => (
= (props) => ( DoubleThreshold.storyName = 'Double threshold' +DoubleThreshold.parameters = disableColorContrastRule + export const CustomValueFormatter: Story = (props) => (
= (props) => ( CustomValueFormatter.storyName = 'Custom value formatter' +CustomValueFormatter.parameters = disableColorContrastRule + export const Stepped: Story = (props) => (
= (props) => ( Stepped.storyName = 'Stepped' +Stepped.parameters = disableColorContrastRule + +export const WithPercentage: Story = (props) => ( +
+ +
+) + +WithPercentage.storyName = 'With percentage' + +WithPercentage.parameters = disableColorContrastRule + export const WithIcons: Story = (props) => (
= (props) => ( WithIcons.storyName = 'With icons' +WithIcons.parameters = disableColorContrastRule + export const WithLabels: Story = (props) => (
= (props) => ( WithLabels.storyName = 'With labels' +WithLabels.parameters = disableColorContrastRule + export const ReversedScale: Story = (props) => (
= (props) => ( ReversedScale.storyName = 'Reversed scale' +ReversedScale.parameters = disableColorContrastRule + export const Disabled: Story = (props) => (
= (props) => ( ) Disabled.storyName = 'Disabled' + +Disabled.parameters = disableColorContrastRule diff --git a/packages/react-component-library/src/components/RangeSlider/RangeSlider.test.tsx b/packages/react-component-library/src/components/RangeSlider/RangeSlider.test.tsx index 34e39ad2cb..40ba7bb5ce 100644 --- a/packages/react-component-library/src/components/RangeSlider/RangeSlider.test.tsx +++ b/packages/react-component-library/src/components/RangeSlider/RangeSlider.test.tsx @@ -50,6 +50,10 @@ describe('RangeSlider', () => { ) }) + it('should not display the percentage value next to the handle', () => { + expect(wrapper.getByTestId('rangeslider-percentage')).not.toBeVisible() + }) + it('should set the correct `tabindex`', () => { expect(wrapper.getByTestId('rangeslider-handle')).toHaveAttribute( 'tabindex', @@ -273,10 +277,7 @@ describe('RangeSlider', () => { }) it('should display the percentage value next to the handle', () => { - expect(wrapper.getByTestId('rangeslider-handle')).toHaveAttribute( - 'data-percent', - '50%' - ) + expect(wrapper.getByTestId('rangeslider-percentage')).toBeVisible() }) }) @@ -296,10 +297,7 @@ describe('RangeSlider', () => { }) it('should append the display unit to the handle label', () => { - expect(wrapper.getByTestId('rangeslider-handle')).toHaveAttribute( - 'data-value', - '20pt' - ) + expect(wrapper.getByTestId('rangeslider-value')).toHaveTextContent('20pt') }) }) @@ -319,10 +317,7 @@ describe('RangeSlider', () => { }) it('formats the handle label using the provided formatter', () => { - expect(wrapper.getByTestId('rangeslider-handle')).toHaveAttribute( - 'data-value', - '£20' - ) + expect(wrapper.getByTestId('rangeslider-value')).toHaveTextContent('£20') }) }) diff --git a/packages/react-component-library/src/components/RangeSlider/partials/StyledHandle.tsx b/packages/react-component-library/src/components/RangeSlider/partials/StyledHandle.tsx index 423d62f4d9..27440c24b9 100644 --- a/packages/react-component-library/src/components/RangeSlider/partials/StyledHandle.tsx +++ b/packages/react-component-library/src/components/RangeSlider/partials/StyledHandle.tsx @@ -4,6 +4,8 @@ import { transparentize } from 'polished' import { RANGE_SLIDER_HANDLE_COLOR } from '../constants' import { ThresholdColor } from '../useThresholdColor' +import { StyledValue } from './StyledValue' +import { StyledPercentage } from './StyledPercentage' interface StyledHandleProps { $isActive?: boolean @@ -11,7 +13,7 @@ interface StyledHandleProps { $left: string } -const { color, fontSize, spacing } = selectors +const { color } = selectors export const StyledHandle = styled.div.attrs(({ $left }) => ({ style: { @@ -32,36 +34,12 @@ export const StyledHandle = styled.div.attrs(({ $left }) => ({ transition: box-shadow 0.15s ease-in-out; cursor: pointer; - &::after { - content: attr(data-value); - position: absolute; - transform: translate(-50%, -155%); - font-size: ${fontSize('xs')}; - color: ${color('neutral', '600')}; - opacity: 1; - transition: opacity 0.15s ease-in-out; - padding: ${spacing('2')} ${spacing('3')}; - border-radius: 12px; - font-weight: 600; - } - - &::before { - content: attr(data-percent); - position: absolute; - transform: translate(-50%, -355%); - font-size: ${fontSize('s')}; - color: ${color('neutral', '300')}; - opacity: 1; - transition: opacity 0.15s ease-in-out; - font-weight: 700; - } - &:nth-of-type(2n) { - &::after { + ${StyledValue} { transform: translate(-50%, 125%); } - &::before { + ${StyledPercentage} { transform: translate(-50%, 355%); } } @@ -73,8 +51,8 @@ export const StyledHandle = styled.div.attrs(({ $left }) => ({ ${transparentize(0.5, color('neutral', '200'))}; outline: none; - &::after, - &::before { + ${StyledValue}, + ${StyledPercentage} { opacity: 1; } `} @@ -83,8 +61,8 @@ export const StyledHandle = styled.div.attrs(({ $left }) => ({ box-shadow: 0px 0px 0px 7px ${transparentize(0.5, color('neutral', '200'))}; outline: none; - &::after, - &::before { + ${StyledValue}, + ${StyledPercentage} { opacity: 1; } } @@ -94,7 +72,7 @@ export const StyledHandle = styled.div.attrs(({ $left }) => ({ css` background-color: ${$thresholdColor}; - &::after { + ${StyledValue} { color: ${$thresholdColor}; background-color: ${transparentize(0.75, $thresholdColor)}; } diff --git a/packages/react-component-library/src/components/RangeSlider/partials/StyledPercentage.tsx b/packages/react-component-library/src/components/RangeSlider/partials/StyledPercentage.tsx new file mode 100644 index 0000000000..526b9de1b9 --- /dev/null +++ b/packages/react-component-library/src/components/RangeSlider/partials/StyledPercentage.tsx @@ -0,0 +1,14 @@ +import styled from 'styled-components' +import { selectors } from '@royalnavy/design-tokens' + +const { fontSize, color } = selectors + +export const StyledPercentage = styled.span` + position: absolute; + transform: translate(-50%, -355%); + font-size: ${fontSize('s')}; + color: ${color('neutral', '300')}; + opacity: 1; + transition: opacity 0.15s ease-in-out; + font-weight: 700; +` diff --git a/packages/react-component-library/src/components/RangeSlider/partials/StyledRangeSlider.tsx b/packages/react-component-library/src/components/RangeSlider/partials/StyledRangeSlider.tsx index 78e0ea3c7b..6dc6efd628 100644 --- a/packages/react-component-library/src/components/RangeSlider/partials/StyledRangeSlider.tsx +++ b/packages/react-component-library/src/components/RangeSlider/partials/StyledRangeSlider.tsx @@ -1,5 +1,7 @@ import styled, { css } from 'styled-components' +import { StyledPercentage } from './StyledPercentage' + interface StyledRangeSliderProps { $isReversed?: boolean $isDisabled?: boolean @@ -21,4 +23,12 @@ export const StyledRangeSlider = styled.div` cursor: not-allowed; } `} + + ${({ $hasPercentage }) => + !$hasPercentage && + ` + ${StyledPercentage} { + display: none; + } + `} ` diff --git a/packages/react-component-library/src/components/RangeSlider/partials/StyledValue.tsx b/packages/react-component-library/src/components/RangeSlider/partials/StyledValue.tsx new file mode 100644 index 0000000000..079bbfa73b --- /dev/null +++ b/packages/react-component-library/src/components/RangeSlider/partials/StyledValue.tsx @@ -0,0 +1,16 @@ +import styled from 'styled-components' +import { selectors } from '@royalnavy/design-tokens' + +const { fontSize, spacing, color } = selectors + +export const StyledValue = styled.span` + position: absolute; + transform: translate(-50%, -155%); + font-size: ${fontSize('xs')}; + color: ${color('neutral', '600')}; + opacity: 1; + transition: opacity 0.15s ease-in-out; + padding: ${spacing('2')} ${spacing('3')}; + border-radius: 12px; + font-weight: 600; +`