Skip to content

Commit

Permalink
feat(Slider): add tooltip on active thumb button
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Sep 1, 2022
1 parent 7f492a5 commit e15203e
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const SliderExampleDefault = () => (
max={100}
value={70}
label="Default Slider:"
numberFormat={{ currency: 'EUR' }}
onChange={({ value }) => console.log('onChange:', value)}
/>
`
Expand All @@ -33,6 +34,7 @@ export const SliderExampleMultiButtons = () => (
value={[30, 70]}
step={5}
label="Range with steps:"
numberFormat={{ currency: 'EUR' }}
onChange={({ value }) => console.log('onChange:', value)}
bottom
/>
Expand All @@ -41,7 +43,7 @@ export const SliderExampleMultiButtons = () => (
max={100}
value={[10, 30, 50, 70]}
label="Multi thumbs:"
numberFormat={{ decimals: 2, currency: true }}
numberFormat={{ currency: true }}
onChange={({ value, number }) => console.log('onChange:', value, number)}
/>
</FormRow>
Expand All @@ -59,6 +61,7 @@ export const SliderExampleMultiButtonsThumbBehavior = () => (
multiThumbBehavior="omit"
value={[30, 70]}
label="Omit behavior:"
numberFormat={{ currency: 'EUR' }}
onChange={({ value }) => console.log('onChange:', value)}
bottom
/>
Expand All @@ -67,7 +70,7 @@ export const SliderExampleMultiButtonsThumbBehavior = () => (
value={[10, 50, 70]}
step={1}
label="Push behavior:"
numberFormat={{ decimals: 2, currency: true }}
numberFormat={{ currency: true }}
onChange={({ value, number }) => console.log('onChange:', value, number)}
/>
</FormRow>
Expand All @@ -88,6 +91,7 @@ const Component = () => {
step={10}
hideButtons
label="Slider A:"
numberFormat={{ currency: 'EUR' }}
onChange={({ value }) => setValue(value)}
/>
<VerticalWrapper>
Expand All @@ -98,6 +102,7 @@ const Component = () => {
step={1}
label="Slider B:"
labelDirection="vertical"
numberFormat={{ currency: 'NOK' }}
onChange={({ value }) => setValue(value)}
/>
<Input
Expand Down
11 changes: 4 additions & 7 deletions packages/dnb-eufemia/src/components/slider/SliderHelpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,19 +134,16 @@ export const formatNumber = (
return value
}

export const getHumanNumber = (
export const getFormattedNumber = (
value: number,
numberFormat: formatOptionParams
) => {
const num = value as number
const { aria: humanNumber } = (
return (
numberFormat
? formatNumber(num, {
? formatNumber(value as number, {
...(numberFormat || {}),
returnAria: true,
})
: { aria: null }
: { aria: null, number: null }
) as formatReturnValue

return String(humanNumber || value)
}
16 changes: 11 additions & 5 deletions packages/dnb-eufemia/src/components/slider/SliderInstance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
} from './SliderTrack'
import { SliderThumb } from './SliderThumb'
import { useSliderProps } from './hooks/useSliderProps'
import { clamp, getHumanNumber } from './SliderHelpers'
import { clamp, getFormattedNumber } from './SliderHelpers'

export function SliderInstance() {
const context = React.useContext(Context)
Expand Down Expand Up @@ -164,15 +164,18 @@ function SubtractButton() {
subtractParams['aria-hidden'] = attributes['aria-hidden']
}

const humanNumber = getHumanNumber(value as number, numberFormat)
const humanNumber = getFormattedNumber(value as number, numberFormat)

return (
<Button
className="dnb-slider__button dnb-slider__button--subtract"
variant="secondary"
icon="subtract"
size="small"
aria-label={subtractTitle?.replace('%s', humanNumber)}
aria-label={subtractTitle?.replace(
'%s',
humanNumber.aria || String(value)
)}
on_click={onSubtractClickHandler}
disabled={disabled}
skeleton={skeleton}
Expand All @@ -196,15 +199,18 @@ function AddButton() {
addParams['aria-hidden'] = attributes['aria-hidden']
}

const humanNumber = getHumanNumber(value as number, numberFormat)
const humanNumber = getFormattedNumber(value as number, numberFormat)

return (
<Button
className="dnb-slider__button dnb-slider__button--add"
variant="secondary"
icon="add"
size="small"
aria-label={addTitle?.replace('%s', humanNumber)}
aria-label={addTitle?.replace(
'%s',
humanNumber.aria || String(value)
)}
on_click={onAddClickHandler}
disabled={disabled}
skeleton={skeleton}
Expand Down
140 changes: 86 additions & 54 deletions packages/dnb-eufemia/src/components/slider/SliderThumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,30 @@ import {
validateDOMAttributes,
} from '../../shared/component-helper'
import Button from '../button/Button'
import Tooltip from '../tooltip/Tooltip'
import { useSliderEvents } from './hooks/useSliderEvents'
import { useSliderProps } from './hooks/useSliderProps'
import { clamp, getHumanNumber } from './SliderHelpers'
import { clamp, getFormattedNumber } from './SliderHelpers'

export function SliderThumb() {
const { values } = useSliderProps()

return (
<>
{values.map((value, i) => {
return <Thumb key={i} value={value} currentIndex={i} />
})}
</>
)
}

type ThumbProps = {
value: number
currentIndex: number
}

function Thumb({ value, currentIndex }: ThumbProps) {
const {
values,
thumbIndex,
isVertical,
isReverse,
Expand All @@ -32,6 +49,28 @@ export function SliderThumb() {
numberFormat,
} = allProps

const index = thumbIndex.current
let percent = clamp(((value - min) * 100) / (max - min))

if (isReverse) {
percent = 100 - percent
}

const style = {
zIndex: index === currentIndex ? 4 : 3,
[`${isVertical ? 'top' : 'left'}`]: `${percent}%`,
} as React.CSSProperties

const { number, aria } = getFormattedNumber(value, numberFormat)

const [hover, setHover] = React.useState(false)
const onMouseEnterHandler = () => {
setHover(true)
}
const onMouseLeaveHandler = () => {
setHover(false)
}

const {
onThumbMouseDownHandler,
onThumbMouseUpHandler,
Expand Down Expand Up @@ -68,58 +107,51 @@ export function SliderThumb() {

return (
<>
{values.map((value, i) => {
const index = thumbIndex.current
let percent = clamp(((value - min) * 100) / (max - min))

if (isReverse) {
percent = 100 - percent
}

const style: React.CSSProperties = {
zIndex: index === i ? 4 : 3,
[`${isVertical ? 'top' : 'left'}`]: `${percent}%`,
}

const humanNumber = getHumanNumber(value, numberFormat)

return (
<React.Fragment key={i}>
<span className="dnb-slider__thumb" style={style}>
<input
type="range"
className="dnb-slider__button-helper"
min={min}
max={max}
step={step}
value={value}
disabled={disabled}
onChange={onHelperChangeHandler}
onFocus={onHelperFocusHandler}
aria-valuemin={min}
aria-valuemax={max}
aria-valuenow={value}
aria-valuetext={humanNumber ? humanNumber : undefined}
aria-orientation={isVertical ? 'vertical' : 'horizontal'}
data-index={i}
{...helperParams}
/>

<Button
element="span"
type=""
variant="secondary"
disabled={disabled}
skeleton={skeleton}
data-index={i}
onMouseDown={onThumbMouseDownHandler}
onMouseUp={onThumbMouseUpHandler}
{...thumbParams}
/>
</span>
</React.Fragment>
)
})}
<span
className="dnb-slider__thumb"
style={style}
onMouseEnter={onMouseEnterHandler}
onTouchStart={onMouseEnterHandler}
onMouseLeave={onMouseLeaveHandler}
onTouchEnd={onMouseLeaveHandler}
>
<input
type="range"
className="dnb-slider__button-helper"
min={min}
max={max}
step={step}
value={value}
disabled={disabled}
onChange={onHelperChangeHandler}
onFocus={onHelperFocusHandler}
onFocusCapture={onMouseEnterHandler}
onBlurCapture={onMouseLeaveHandler}
aria-valuemin={min}
aria-valuemax={max}
aria-valuenow={value}
aria-valuetext={aria ? aria : undefined}
aria-orientation={isVertical ? 'vertical' : 'horizontal'}
data-index={currentIndex}
{...helperParams}
/>

<Button
element="span"
type=""
variant="secondary"
disabled={disabled}
skeleton={skeleton}
data-index={currentIndex}
onMouseDown={onThumbMouseDownHandler}
onMouseUp={onThumbMouseUpHandler}
{...thumbParams}
/>

<Tooltip active={hover} omit_portal>
{number || value}
</Tooltip>
</span>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('Slider screenshot', () => {

it('have to match the focus state', async () => {
const screenshot = await testPageScreenshot({
style: { width: '20rem' },
style: { width: '20rem', 'padding-top': '3rem' },
selector: '[data-visual-test="slider-default"] .dnb-slider__wrapper',
simulateSelector:
'[data-visual-test="slider-default"] .dnb-slider__thumb .dnb-slider__button-helper',
Expand All @@ -32,7 +32,7 @@ describe('Slider screenshot', () => {

it('have to match the hover state', async () => {
const screenshot = await testPageScreenshot({
style: { width: '20rem' },
style: { width: '20rem', 'padding-top': '3rem' },
selector: '[data-visual-test="slider-default"] .dnb-slider__wrapper',
simulateSelector:
'[data-visual-test="slider-default"] .dnb-slider__thumb .dnb-slider__button-helper',
Expand All @@ -43,7 +43,7 @@ describe('Slider screenshot', () => {

it('have to match the active state', async () => {
const screenshot = await testPageScreenshot({
style: { width: '20rem' },
style: { width: '20rem', 'padding-top': '3rem' },
selector: '[data-visual-test="slider-default"] .dnb-slider__wrapper',
simulateSelector:
'[data-visual-test="slider-default"] .dnb-slider__thumb .dnb-slider__button-helper',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,8 @@ legend.dnb-form-label {
left: 0;
top: 0;
z-index: 3;
display: block;
display: flex;
justify-content: center;
transform: translate3d(-50%, 0, 0);
border-radius: 50%; }
.dnb-slider__button-helper,
Expand Down Expand Up @@ -869,6 +870,12 @@ legend.dnb-form-label {
margin-top: 0.5rem; }
.dnb-slider--vertical .dnb-form-status {
margin-top: 1rem; }
.dnb-slider .dnb-tooltip {
top: -3rem;
transition: opacity 400ms ease; }
.dnb-slider .dnb-tooltip__content {
min-width: 0;
white-space: nowrap; }
@media screen and (max-width: 40em) {
.dnb-responsive-component .dnb-slider {
display: flex;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ export function MultiButtons() {
max={1000}
step={10}
stretch
// vertical
reverse
vertical
// reverse
numberFormat={{
decimals: 2,
currency: 'EUR',
Expand Down
13 changes: 12 additions & 1 deletion packages/dnb-eufemia/src/components/slider/style/_slider.scss
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@
top: 0;
z-index: 3;

display: block;
display: flex;
justify-content: center;
transform: translate3d(-50%, 0, 0);

// Because of the DropShadow
Expand Down Expand Up @@ -236,6 +237,16 @@
margin-top: 1rem;
}

.dnb-tooltip {
top: -3rem;
transition: opacity 400ms ease;

&__content {
min-width: 0;
white-space: nowrap;
}
}

.dnb-responsive-component & {
@media screen and (max-width: 40em) {
display: flex;
Expand Down

0 comments on commit e15203e

Please sign in to comment.