Skip to content

Commit

Permalink
feat(client): add ToggleSlider horizontal variant and handle duration…
Browse files Browse the repository at this point in the history
… prop for loading animation
  • Loading branch information
Jozwiaczek committed Oct 30, 2021
1 parent 186f958 commit c5322b9
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const infoBoxZoomInOut = keyframes`
}
`;

export const keyIconTick = keyframes`
export const verticalKeyIconTick = keyframes`
0% {
transform: rotate(90deg);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const SLIDER_HEIGHT = 300;
export const SLIDER_WIDTH = 100;
export const DEFAULT_THUMB_Y = 0;
export const INITIAL_THUMB_POSITION = 0;
export const SLIDER_TARGET_SIZE = 80;
export const SLIDE_PROGRESS_MIN = 0;
export const SLIDE_PROGRESS_MAX = 100;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ const Template: Story<ToggleSliderProps> = (args) => {

export const Default = Template.bind({});
Default.args = {
orientation: 'horizontal',
onToggle: () => console.log('toggled'),
};
45 changes: 30 additions & 15 deletions packages/client/src/elements/ToggleSlider/ToggleSlider.styled.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import styled, { css } from 'styled-components';

import { DetailedKeyIcon } from '../../icons';
import { PulseCircle } from './components/PulsatingCircles/PulsatingCircles.styled';
import { hidePulsatingCircles, infoBoxZoomInOut, keyIconTick } from './ToggleSlider.animations';
import {
hidePulsatingCircles,
infoBoxZoomInOut,
verticalKeyIconTick,
} from './ToggleSlider.animations';
import {
ARROW_UP_BORDER_SIZE,
COMPLETED_TOGGLING_ANIMATION_DURATION,
Expand All @@ -12,6 +17,7 @@ import {
} from './ToggleSlider.constants';
import {
ArrowUpProps,
BaseSliderStylesProps,
InfoBoxLabelProps,
InfoBoxProps,
SliderThumbProps,
Expand Down Expand Up @@ -58,29 +64,30 @@ export const InfoBoxLabel = styled.p<InfoBoxLabelProps>(
`,
);

export const SliderTarget = styled.div(
({ theme: { palette } }) => css`
export const SliderTarget = styled.div<BaseSliderStylesProps>(
({ theme: { palette }, isHorizontal }) => css`
background: ${palette.background.paperHover};
border-radius: 100%;
color: ${palette.background.paper};
height: ${SLIDER_TARGET_SIZE}px;
width: ${SLIDER_TARGET_SIZE}px;
display: flex;
margin-top: 10px;
margin: ${isHorizontal ? '0 10px 0 0' : '10px 0 0 0'};
justify-content: center;
align-items: center;
position: relative;
`,
);

export const ArrowUp = styled.div<ArrowUpProps>(
({ isDragging, theme: { palette } }) => css`
export const HintArrow = styled.div<ArrowUpProps>(
({ isDragging, isHorizontal, theme: { palette } }) => css`
width: 30px;
height: 30px;
box-sizing: border-box;
position: absolute;
top: 30px;
transform: rotate(-45deg);
top: ${isHorizontal ? '26px' : '30px'};
left: ${isHorizontal ? '20px' : 'none'};
transform: rotate(${isHorizontal ? '45deg' : '-45deg'});
&::before {
content: '';
Expand Down Expand Up @@ -141,7 +148,7 @@ export const ThumbCircle = styled.div<ThumbCircleProps>(
${isToggled &&
css`
animation: ${keyIconTick} ${COMPLETED_TOGGLING_ANIMATION_DURATION}ms 1 ease-in-out;
animation: ${verticalKeyIconTick} ${COMPLETED_TOGGLING_ANIMATION_DURATION}ms 1 ease-in-out;
`}
${isSnapped
Expand Down Expand Up @@ -177,17 +184,25 @@ export const SliderThumb = styled.div<SliderThumbProps>(
`,
);

export const Slider = styled.div(
({ theme: { palette } }) => css`
export const Slider = styled.div<BaseSliderStylesProps>(
({ theme: { palette }, isHorizontal }) => css`
background: ${palette.background.paper};
width: ${SLIDER_WIDTH}px;
height: ${SLIDER_HEIGHT}px;
border-radius: ${SLIDER_WIDTH / 2}px;
width: ${isHorizontal ? SLIDER_HEIGHT : SLIDER_WIDTH}px;
height: ${isHorizontal ? SLIDER_WIDTH : SLIDER_HEIGHT}px;
border-radius: ${(isHorizontal ? SLIDER_HEIGHT : SLIDER_WIDTH) / 2}px;
display: flex;
flex-direction: column;
flex-direction: ${isHorizontal ? 'row-reverse' : 'column'};
position: relative;
align-items: center;
justify-content: space-between;
box-shadow: ${palette.boxShadow.default};
`,
);

export const StyledDetailedKeyIcon = styled(DetailedKeyIcon)<BaseSliderStylesProps>(
({ isHorizontal }) =>
isHorizontal &&
css`
transform: scale(-1, 1) rotate(90deg);
`,
);
15 changes: 12 additions & 3 deletions packages/client/src/elements/ToggleSlider/ToggleSlider.types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,19 @@ interface SliderThumbProps {
disabledPulsing: boolean;
}

interface ArrowUpProps {
interface ArrowUpProps extends BaseSliderStylesProps {
isDragging: boolean;
}

type ToggleSliderOrientation = 'vertical' | 'horizontal';

interface ToggleSliderProps {
onToggle: () => void;
orientation?: ToggleSliderOrientation;
}

interface BaseSliderStylesProps {
isHorizontal: boolean;
}

type InfoBoxState = 'default' | 'success';
Expand All @@ -31,11 +38,13 @@ interface InfoBoxLabelProps {

interface UseTogglingProgressProps {
onComplete: () => unknown;
duration?: number;
}

interface UseResetSliderProps {
thumbYPosition: number;
setThumbYPosition: Dispatch<SetStateAction<number>>;
isHorizontal: boolean;
thumbPosition: number;
setThumbPosition: Dispatch<SetStateAction<number>>;
slideProgress: number;
setSlideProgress: Dispatch<SetStateAction<number>>;
onComplete: () => unknown;
Expand Down
28 changes: 21 additions & 7 deletions packages/client/src/elements/ToggleSlider/hooks/useResetSlider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { useCallback, useEffect, useState } from 'react';
import { useInterval } from '../../../hooks';
import {
COMPLETED_TOGGLING_ANIMATION_DURATION,
DEFAULT_THUMB_Y,
INITIAL_THUMB_POSITION,
SLIDE_PROGRESS_MIN,
} from '../ToggleSlider.constants';
import { UseResetSliderProps } from '../ToggleSlider.types';

const useResetSlider = ({
thumbYPosition,
setThumbYPosition,
isHorizontal,
thumbPosition,
setThumbPosition,
slideProgress,
setSlideProgress,
onComplete,
Expand All @@ -28,18 +29,31 @@ const useResetSlider = ({
}, []);

useEffect(() => {
if (thumbYPosition >= DEFAULT_THUMB_Y && isRun) {
if (!isRun) {
return;
}

if (
isHorizontal
? thumbPosition <= INITIAL_THUMB_POSITION
: thumbPosition >= INITIAL_THUMB_POSITION
) {
setIsRun(false);
setThumbYPosition(DEFAULT_THUMB_Y);
setThumbPosition(INITIAL_THUMB_POSITION);
setSlideProgress(SLIDE_PROGRESS_MIN);
onComplete();
}
}, [isRun, onComplete, setSlideProgress, setThumbYPosition, thumbYPosition]);
}, [isHorizontal, isRun, onComplete, setSlideProgress, setThumbPosition, thumbPosition]);

useInterval({
callback: () => {
thumbYPosition < DEFAULT_THUMB_Y && setThumbYPosition((prevState) => prevState + 10);
slideProgress > SLIDE_PROGRESS_MIN && setSlideProgress((prevState) => prevState - 10);

if (isHorizontal) {
thumbPosition > INITIAL_THUMB_POSITION && setThumbPosition((prevState) => prevState - 10);
} else {
thumbPosition < INITIAL_THUMB_POSITION && setThumbPosition((prevState) => prevState + 10);
}
},
delay: 10,
initDelay,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,47 @@ import { useCallback, useEffect, useState } from 'react';
import { useInterval } from '../../../hooks';
import { UseTogglingProgressProps } from '../ToggleSlider.types';

const delay = 3;
const initValue = 0;
const targetValue = 100;
const INIT_VALUE = 0;
const TARGET_VALUE = 100;
const FPS = 60;

const useToggleLoading = ({ onComplete }: UseTogglingProgressProps) => {
const useToggleLoading = ({ onComplete, duration = 250 }: UseTogglingProgressProps) => {
const [isRun, setIsRun] = useState(false);
const [progress, setProgress] = useState(initValue);
const [progress, setProgress] = useState(INIT_VALUE);
const [isCompleted, setIsCompleted] = useState(false);

const run = useCallback(() => {
setIsCompleted(false);
setProgress(initValue);
setProgress(INIT_VALUE);
setIsRun(true);
}, []);

useEffect(() => {
if (progress >= targetValue && isRun) {
if (progress >= TARGET_VALUE && isRun) {
setIsCompleted(true);
setIsRun(false);
onComplete();
}
}, [isRun, onComplete, progress]);

const increaseValueRate = TARGET_VALUE / (FPS * (duration / 1000));
const intervalDelay = 1000 / FPS;

useInterval({
callback: () => {
progress < targetValue && setProgress((prevState) => prevState + 1);
if (progress >= TARGET_VALUE) {
return;
}

setProgress((prevState) => {
const newProgressValue = prevState + increaseValueRate;
if (newProgressValue >= TARGET_VALUE) {
return TARGET_VALUE;
}
return newProgressValue;
});
},
delay,
delay: intervalDelay,
initDelay: 0,
disabled: !isRun,
});
Expand Down
Loading

0 comments on commit c5322b9

Please sign in to comment.