Skip to content

Commit

Permalink
feat(Slider): add toolbar on active thumb button
Browse files Browse the repository at this point in the history
  • Loading branch information
tujoworker committed Aug 25, 2022
1 parent f32d029 commit 9cd1721
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 86 deletions.
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 @@ -126,19 +126,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 @@ -158,15 +158,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 @@ -190,15 +193,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
141 changes: 84 additions & 57 deletions packages/dnb-eufemia/src/components/slider/SliderThumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,31 @@ 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,
thumbIndex,
isVertical,
showStatus,
attributes,
allProps,
} = useSliderProps()
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 { thumbIndex, isVertical, showStatus, attributes, allProps } =
useSliderProps()

const {
id,
Expand All @@ -31,6 +43,24 @@ export function SliderThumb() {
numberFormat,
} = allProps

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

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,54 +98,51 @@ export function SliderThumb() {

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

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 @@ -812,7 +812,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 @@ -872,6 +873,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 @@ -7,14 +7,7 @@ import React from 'react'
import { Wrapper, Box } from 'storybook-utils/helpers'
import styled from '@emotion/styled'

import {
Slider,
ToggleButton,
Input,
FormRow,
FormLabel,
Tooltip,
} from '../../'
import { Slider, ToggleButton, Input, FormRow, FormLabel } from '../../'

import '../../slider/style/dnb-range.scss'

Expand Down Expand Up @@ -50,12 +43,13 @@ export function MultiButtons() {
return (
<>
<FixedSizeWrapper>
<Tooltip active show>
Tooltip
</Tooltip>
<Slider
label="Label2:"
top="x-large"
// multiThumbBehavior="push"
multiThumbBehavior="omit"
label="Label:"
value={value}
step={1}
stretch
numberFormat={{ decimals: 2, currency: true }}
onChange={({ value, number }) => {
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 @@ -157,7 +157,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 @@ -241,6 +242,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 9cd1721

Please sign in to comment.