Skip to content

Commit

Permalink
Adding Props to Slider Component (#1436)
Browse files Browse the repository at this point in the history
  • Loading branch information
marashad001 authored Aug 1, 2023
1 parent 9770df1 commit c83bd5e
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 13 deletions.
1 change: 1 addition & 0 deletions apps/storybook/src/Slider.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ export const CustomTickNoTooltip: Story<SliderProps> = (args) => {
</Text>
</div>
}
tickProps={{ className: 'some-tick' }}
/>
);
};
Expand Down
43 changes: 43 additions & 0 deletions packages/itwinui-react/src/core/Slider/Slider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,49 @@ it('should render correctly in its most basic state', () => {
expect(thumb.getAttribute('aria-disabled')).toEqual('false');
});

it('should render all custom classNames correctly', () => {
const { container } = render(
<Slider
values={defaultSingleValue}
tickLabels={['0', '25', '50', '75', '100']}
minProps={{ className: 'some-min' }}
maxProps={{ className: 'some-max' }}
railProps={{ className: 'some-rail' }}
trackProps={{ className: 'some-track' }}
tickProps={{ className: 'some-tick' }}
ticksProps={{ className: 'some-ticks' }}
/>,
);
assertBaseElement(container);
expect(container.querySelector('.iui-slider-track')).toBeTruthy();
expect(container.querySelector('.iui-slider-min')).toHaveClass(
'iui-slider-min',
'some-min',
);
expect(container.querySelector('.iui-slider-max')).toHaveClass(
'iui-slider-max',
'some-max',
);
expect(container.querySelector('.iui-slider-rail')).toHaveClass(
'iui-slider-rail',
'some-rail',
);
expect(container.querySelector('.iui-slider-track')).toHaveClass(
'iui-slider-track',
'some-track',
);
expect(container.querySelector('.iui-slider-tick')).toHaveClass(
'iui-slider-tick',
'some-tick',
);
expect(container.querySelector('.iui-slider-ticks')).toHaveClass(
'iui-slider-ticks',
'some-ticks',
);
const thumb = container.querySelector('.iui-slider-thumb') as HTMLDivElement;
expect(thumb.getAttribute('aria-disabled')).toEqual('false');
});

it('should not render thumbs if no values are defined', () => {
const { container } = render(<Slider values={[]} />);
expect(
Expand Down
77 changes: 67 additions & 10 deletions packages/itwinui-react/src/core/Slider/Slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,30 @@ export type SliderProps = {
* Additional props for container `<div>` that hold the slider rail, thumbs, and tracks.
*/
railContainerProps?: React.HTMLAttributes<HTMLDivElement>;
/**
* Allows props to be passed for slider-min
*/
minProps?: React.ComponentProps<'span'>;
/**
* Allows props to be passed for slider-max
*/
maxProps?: React.ComponentProps<'span'>;
/**
* Allows props to be passed for slider-rail
*/
railProps?: React.ComponentProps<'div'>;
/**
* Allows props to be passed for slider-track
*/
trackProps?: React.ComponentProps<'div'>;
/**
* Allows props to be passed for slider-tick
*/
tickProps?: React.ComponentProps<'span'>;
/**
* Allows props to be passed for slider-ticks
*/
ticksProps?: React.ComponentProps<'div'>;
/**
* Defines the allowed behavior when moving Thumbs when multiple Thumbs are
* shown. It controls if a Thumb movement should be limited to only move in
Expand Down Expand Up @@ -208,6 +232,12 @@ export const Slider = React.forwardRef((props, ref) => {
thumbProps,
className,
railContainerProps,
minProps,
maxProps,
railProps,
trackProps,
tickProps,
ticksProps,
orientation = 'horizontal',
...rest
} = props;
Expand Down Expand Up @@ -412,9 +442,18 @@ export const Slider = React.forwardRef((props, ref) => {

if (Array.isArray(tickLabels)) {
return (
<Box className='iui-slider-ticks'>
<Box
as='div'
{...ticksProps}
className={cx('iui-slider-ticks', ticksProps?.className)}
>
{tickLabels.map((label, index) => (
<Box as='span' key={index} className='iui-slider-tick'>
<Box
as='span'
{...tickProps}
key={index}
className={cx('iui-slider-tick', tickProps?.className)}
>
{label}
</Box>
))}
Expand All @@ -423,7 +462,7 @@ export const Slider = React.forwardRef((props, ref) => {
}

return tickLabels;
}, [tickLabels]);
}, [tickLabels, tickProps, ticksProps]);

const generateTooltipProps = React.useCallback(
(index: number, val: number): Omit<TooltipProps, 'children'> => {
Expand Down Expand Up @@ -453,19 +492,32 @@ export const Slider = React.forwardRef((props, ref) => {
{...rest}
>
{minValueLabel && (
<Box as='span' className='iui-slider-min'>
<Box
as='span'
{...minProps}
className={cx('iui-slider-min', minProps?.className)}
>
{minValueLabel}
</Box>
)}
<Box
as='div'
ref={containerRef}
className={cx('iui-slider-container', {
'iui-grabbing': undefined !== activeThumbIndex,
})}
onPointerDown={handlePointerDownOnSlider}
{...railContainerProps}
className={cx(
'iui-slider-container',
{
'iui-grabbing': undefined !== activeThumbIndex,
},
railContainerProps?.className,
)}
onPointerDown={handlePointerDownOnSlider}
>
<Box className='iui-slider-rail' />
<Box
as='div'
{...railProps}
className={cx('iui-slider-rail', railProps?.className)}
/>
{currentValues.map((thumbValue, index) => {
const [minVal, maxVal] = getAllowableThumbRange(index);
const thisThumbProps = thumbProps?.(index);
Expand Down Expand Up @@ -495,11 +547,16 @@ export const Slider = React.forwardRef((props, ref) => {
sliderMax={max}
values={currentValues}
orientation={orientation}
{...trackProps}
/>
{tickMarkArea}
</Box>
{maxValueLabel && (
<Box as='span' className='iui-slider-max'>
<Box
as='span'
{...maxProps}
className={cx('iui-slider-max', maxProps?.className)}
>
{maxValueLabel}
</Box>
)}
Expand Down
14 changes: 11 additions & 3 deletions packages/itwinui-react/src/core/Slider/Track.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import * as React from 'react';
import cx from 'classnames';
import { Box } from '../utils/index.js';
import type { SliderProps, TrackDisplayMode } from './Slider.js';

Expand Down Expand Up @@ -48,14 +49,21 @@ export type TrackProps = {
sliderMax: number;
values: number[];
orientation: SliderProps['orientation'];
};
} & React.HTMLAttributes<HTMLDivElement>;

/**
* Track displays color segments above Rail. Which, if any, segments that are
* colorized is based on `trackDisplayMode`.
*/
export const Track = (props: TrackProps) => {
const { trackDisplayMode, sliderMin, sliderMax, values, orientation } = props;
const {
className,
trackDisplayMode,
sliderMin,
sliderMax,
values,
orientation,
} = props;
const [segments, setSegments] = React.useState(() =>
generateSegments(values, sliderMin, sliderMax),
);
Expand All @@ -81,7 +89,7 @@ export const Track = (props: TrackProps) => {
<React.Fragment key={index}>
{shouldDisplaySegment(index, trackDisplayMode) ? (
<Box
className='iui-slider-track'
className={cx('iui-slider-track', className)}
style={{
...(orientation === 'horizontal'
? {
Expand Down

0 comments on commit c83bd5e

Please sign in to comment.