Skip to content

Commit

Permalink
Add Basic Slider component
Browse files Browse the repository at this point in the history
* Add slider mix max props
  • Loading branch information
anitnilay20 committed Dec 5, 2021
1 parent 7e2c469 commit 873271d
Show file tree
Hide file tree
Showing 11 changed files with 212 additions and 113 deletions.
2 changes: 1 addition & 1 deletion __tests__/components/Breadcrumb/Breadcrumb.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe('Breadcrumb', () => {

expect(breadcrumb[2].innerHTML).toBe('<a href="#">Breadcrumb</a>');
expect(breadcrumb[2].children[0]).toHaveStyle(`
color: rgb(48, 48, 48);
color: rgb(114, 114, 114);
`);
});

Expand Down
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,8 @@
"csstips": "^1.2.0",
"debounce": "^1.2.0",
"rc-slider": "^9.6.2",
"rc-tooltip": "^4.2.1",
"react-popper": "^2.2.5",
"react-pose": "^4.0.10",
"react-pose-text": "^3.1.0",
"rxjs": "^6.6.2"
},
"devDependencies": {
Expand Down
64 changes: 34 additions & 30 deletions src/components/Slider/Slider.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,50 @@
import React from 'react';
import { Story, Meta } from '@storybook/react';

import { Slider, SliderProps, Range as SlRange, RangeProps, SliderHandle } from './Slider';
import { Text } from '../Text';
import { SliderTooltip } from 'rc-slider';
import { Slider, SliderProps } from './Slider';

export default {
title: 'Inputs/Slider',
component: Slider,
subcomponents: {
Range: SlRange,
},
argTypes: {
// backgroundColor: { control: 'color' },
},
} as Meta;

export const Basic: Story<SliderProps> = (args) => <Slider {...args} />;

export const Verticle: Story<SliderProps> = (args) => (
<div style={{ height: '400px' }}>
<Slider vertical {...args} />
</div>
);

export const Range: Story<RangeProps> = (args) => <SlRange {...args} />;

export const Marks = Basic.bind({});
Marks.args = {
marks: {
0: '0 KM',
10: '10 KM',
50: <Text color="red">50</Text>,
100: '100 KM',
},
Basic.args = {
value: 50,
};

export const WithTooltip: Story<SliderProps> = (args) => {
const handle = ({ value, dragging, ...rest }: { value: number; dragging?: boolean }) => (
<SliderTooltip visible={dragging} prefixCls="rc-slider-tooltip" overlay={`${value} KM`} placement="top">
<SliderHandle value={value} {...rest} />
</SliderTooltip>
);
return <Slider {...args} handle={handle} />;
export const MaxAndMin = Basic.bind({});
MaxAndMin.args = {
min: 20,
max: 80,
};

// export const Verticle: Story<SliderProps> = (args) => (
// <div style={{ height: '400px' }}>
// <Slider vertical {...args} />
// </div>
// );

// export const Range: Story<RangeProps> = (args) => <SlRange {...args} />;

// export const Marks = Basic.bind({});
// Marks.args = {
// marks: {
// 0: '0 KM',
// 10: '10 KM',
// 50: <Text color="red">50</Text>,
// 100: '100 KM',
// },
// };

// export const WithTooltip: Story<SliderProps> = (args) => {
// const handle = ({ value, dragging, ...rest }: { value: number; dragging?: boolean }) => (
// <SliderTooltip visible={dragging} prefixCls="rc-slider-tooltip" overlay={`${value} KM`} placement="top">
// <SliderHandle value={value} {...rest} />
// </SliderTooltip>
// );
// return <Slider {...args} handle={handle} />;
// };
123 changes: 100 additions & 23 deletions src/components/Slider/Slider.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,111 @@
import React from 'react';
import { Global, css } from '@emotion/react';
import RcSlider, { Range as RcRange, Handle, SliderTooltip } from 'rc-slider';
import React, { useRef, useState } from 'react';
import { classes } from '../../helpers';
import { elevationCss } from '../../helpers/elevations';
import { marginCss } from '../../helpers/margin';
import { paddingCss } from '../../helpers/padding';
import { useTheme } from '../Theme/Theme';
import { rcSliderStyle } from './style';
import { RangeProps } from 'rc-slider/lib/Range';
import { SliderProps } from 'rc-slider/lib/Slider';
import { HandleProps } from 'rc-slider/lib/Handle';
import { style } from './style';

export const Slider: React.FC<SliderProps> = (props) => {
const theme = useTheme();
rcSliderStyle(theme);
const railRef = useRef<HTMLDivElement>();
const handleRef = useRef<HTMLDivElement>();

return (
<>
<Global styles={css(rcSliderStyle(theme))} />
<RcSlider {...props} />
</>
);
};
const { min = 0, max = 100 } = props;
const [value, updateValue] = useState(props.value || min);

export const Range: React.FC<RangeProps> = (props) => {
const theme = useTheme();
rcSliderStyle(theme);
const [dragActive, updateDragActive] = useState(false);
const css = style(theme, dragActive);

const computeValue = (value: number) => {
// console.log(value);
// return (value * (max - min)) / 100;
return value;
};

const handleOnRailClick = (e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>) => {
const rect = railRef.current?.getBoundingClientRect();
let value = 0;
if (e.type === 'touchstart') {
value = (((e as React.TouchEvent).touches[0].clientX - rect.left) * 100) / rect.width;
} else {
value = (((e as React.MouseEvent).clientX - rect.left) * 100) / rect.width;
}
value = computeValue(value);
if (value >= min && value <= max) {
props.onChange(value);
updateValue(value);
}
updateDragActive(true);

document.addEventListener('mousemove', drag);
document.addEventListener('mouseup', dragEnd);
document.addEventListener('touchmove', drag);
document.addEventListener('touchend', dragEnd);
};

const dragEnd = () => {
updateDragActive(false);
document.removeEventListener('mousemove', drag);
document.removeEventListener('mouseup', dragEnd);
document.removeEventListener('touchmove', drag);
document.removeEventListener('touchend', dragEnd);
};

const drag = (e: MouseEvent | TouchEvent) => {
e.preventDefault();

const rect = railRef.current?.getBoundingClientRect();

let value = 0;
if (e.type === 'touchstart') {
value = (((e as TouchEvent).touches[0].clientX - rect.left) * 100) / rect.width;
} else {
value = (((e as MouseEvent).clientX - rect.left) * 100) / rect.width;
}

value = computeValue(value);

if (value >= min && value <= max) {
props.onChange(value);
updateValue(value);
}
};

return (
<>
<Global styles={css(rcSliderStyle(theme))} />
<RcRange {...props} />
</>
<div
className={classes('sha-el-slider', css.slider, marginCss(2))}
onTouchStart={handleOnRailClick}
onMouseDown={handleOnRailClick}
>
<div className={classes('sha-el-slider-rail')} ref={railRef} />
<div className={classes('sha-el-slider-track')} style={{ width: value + '%' }} />
<div className={classes('sha-el-slider-handle')} style={{ left: value + '%' }} ref={handleRef} />
<div
className={classes('sha-el-slider-tooltip', elevationCss(4), paddingCss([5, 0]))}
style={{ left: `calc(${value}% - 20px)` }}
>
{value}
</div>
</div>
);
};

export { RangeProps, SliderProps, HandleProps, Handle as SliderHandle, SliderTooltip };
export interface SliderProps {
/**
* Value of slider.
*/
value?: number;
/**
* onChange event handler.
*/
onChange?: (value: number) => void;
/**
* Min value of slider.
*/
min?: number;
/**
* Max value of slider.
*/
max?: number;
}
2 changes: 1 addition & 1 deletion src/components/Slider/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { Slider, SliderTooltip, Range, SliderHandle } from './Slider';
export { Slider } from './Slider';
69 changes: 69 additions & 0 deletions src/components/Slider/style.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,76 @@
import { css } from '@emotion/css';
import Color from 'color';
import { colorShades } from '../../helpers/color';
import { shadow } from '../../helpers/style';
import { zLayoutPopUp } from '../../helpers/zIndex';
import { Theme } from '../Theme/Theme';

export const style = (theme: Theme, active: boolean) => {
const [, , borderColor, handleColor, railColor] = colorShades(theme.primary);

return {
slider: css({
position: 'relative',
boxSizing: 'border-box',
width: '100%',
cursor: 'pointer',
'& .sha-el-slider-rail': {
width: '100%',
height: '5px',
borderRadius: '2.5px',
background: railColor,
cursor: 'pointer',
},
'& .sha-el-slider-track': {
position: 'absolute',
height: '5px',
borderRadius: '2.5px',
background: theme.primary,
top: 0,
},
'& .sha-el-slider-handle': {
width: '14px',
height: '14px',
position: 'absolute',
background: theme.background,
border: `2px solid ${borderColor}`,
transform: 'translateX(-50%)',
borderRadius: '100%',
marginTop: '-9px',
boxSizing: 'border-box',
...(active
? {
scale: '1.3',
background: handleColor,
}
: {}),
'&:hover': {
scale: '1.3',
background: handleColor,
'& ~ .sha-el-slider-tooltip': {
opacity: 1,
},
},
'&:active': {
boxShadow: shadow('2X', theme),
},
},
'& .sha-el-slider-tooltip': {
position: 'absolute',
top: '-40px',
textAlign: 'center',
width: '40px',
boxSizing: 'border-box',
opacity: active ? 1 : 0,
backgroundColor: colorShades(Color(theme.background).negate().toString())[4],
color: theme.background,
borderRadius: '4px',
zIndex: zLayoutPopUp,
},
}),
};
};

export const rcSliderStyle = (theme: Theme) => {
const railColor = colorShades(theme.primary)[4];

Expand Down
4 changes: 2 additions & 2 deletions src/helpers/border.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const initBorders = (theme: Theme) => {
let values = '';
const color = Color(theme.bodyBg);

const shadows: string[] = color.lightness() < 0.7 ? lightThemeShadows(theme) : darkThemeShadows(theme);
const shadows: string[] = color.lightness() < 70 ? lightThemeShadows(theme) : darkThemeShadows(theme);

shadows.forEach((shadow, index) => {
values += `
Expand All @@ -40,7 +40,7 @@ export const initBorders = (theme: Theme) => {
};

export const getBorders = (theme: Theme, value: number) => {
const shadows: string[] = Color(theme.bodyBg).lightness() < 0.7 ? lightThemeShadows(theme) : darkThemeShadows(theme);
const shadows: string[] = Color(theme.bodyBg).lightness() < 70 ? lightThemeShadows(theme) : darkThemeShadows(theme);
return shadows[value];
};

Expand Down
4 changes: 2 additions & 2 deletions src/helpers/color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export const buttonColor = (
};

export const colorShades = (color: string) => {
if (Color(color).lightness() > 0.6) {
if (Color(color).lightness() > 70) {
return [
Color(color).darken(0.05).toString(),
Color(color).darken(0.08).toString(),
Expand All @@ -113,7 +113,7 @@ export const colorShades = (color: string) => {
Color(color).lighten(0.05).toString(),
Color(color).lighten(0.08).toString(),
Color(color).lighten(0.1).toString(),
Color(color).lighten(0.13).toString(),
Color(color).lighten(0.15).toString(),
Color(color).lighten(0.2).toString(),
];
};
2 changes: 1 addition & 1 deletion src/helpers/elevations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const initElevations = (theme: Theme) => {
let values = '';
const color = Color(theme.bodyBg);

const shadows: string[] = color.lightness() < 0.7 ? lightThemeShadows : darkThemeShadows;
const shadows: string[] = color.lightness() < 70 ? lightThemeShadows : darkThemeShadows;

shadows.forEach((shadow, index) => {
values += `
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ export { List, ListItem, CollapsibleList } from './components/List';
export { Tooltip } from './components/Tooltip';
export { Text } from './components/Text';
export { Upload } from './components/Upload';
export { Slider, Range, SliderHandle } from './components/Slider';
export { Slider } from './components/Slider';
export { Step, Stepper } from './components/Stepper';
export { Portal } from './components/Portal';
Loading

0 comments on commit 873271d

Please sign in to comment.