Skip to content

Commit

Permalink
feat: slide 버튼 윈도우 사이즈에 맞게 반응형 디자인 되도록 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
steven-yn committed Feb 18, 2024
1 parent 550a208 commit be37f31
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 10 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-markdown": "^9.0.1",
"react-responsive": "^9.0.2",
"react-slick": "^0.30.1",
"slick-carousel": "^1.8.1"
},
Expand Down
33 changes: 33 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions src/components/NormalProject/NormalProject.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,21 @@ export const buttonVariants = styleVariants({
buttonStyle,
buttonAnimationStyle,
{
left: 'calc(-2.5rem + -12.5rem)',
// left: '-15rem',
left: '0',
},
],
'slick-next': [
buttonStyle,
buttonAnimationStyle,
{
right: 'calc(-2.5rem + -12.5rem)',
// right: '-15rem',
right: '0',
// '@media': {
// [ODSBreakpointTokenVariables['breakpoint-xl']]: {
// right: '0',
// },
// },
},
],
});
Expand Down
59 changes: 57 additions & 2 deletions src/components/NormalProject/NormalProject.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,18 @@ import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';

import classNames from 'classnames';
import React, { CSSProperties, MouseEventHandler } from 'react';
import React, {
CSSProperties,
MouseEventHandler,
useEffect,
useLayoutEffect,
useRef,
} from 'react';
import Slider from 'react-slick';
import CommonIcon from '@/composable/Icon/CommonIcon';
import { useODSBreakPoints } from '@/hook/useODSBreakPoints';
import { useWindowResize } from '@/hook/useWindowResize';
import { getButtonPositionWithBreakPoints } from './getButtonPositionWithBreakPoints';
import {
buttonVariants,
iconVariants,
Expand Down Expand Up @@ -58,13 +67,59 @@ interface ButtonBoxProps {

const ButtonBox = (props: ButtonBoxProps) => {
const { className, style, onClick } = props;
const buttonRef = useRef<HTMLButtonElement>(null);
const windowSize = useWindowResize();
const breakPoints = useODSBreakPoints();

const shiftValue = getButtonPositionWithBreakPoints(breakPoints);

const direction =
(className?.split(' ')[1] as 'slick-prev' | 'slick-next') || 'slick-prev';

const enablePrevPosition = buttonRef.current && direction === 'slick-prev';
const enableNextPosition = buttonRef.current && direction === 'slick-next';

const $p = buttonRef.current?.parentElement;
const $pp = $p?.parentElement;

const buttonLeftPosition = enablePrevPosition
? -($pp as HTMLElement).getBoundingClientRect().left + shiftValue
: '';

const buttonRightPosition = enableNextPosition
? -windowSize.width +
($pp as HTMLElement).getBoundingClientRect().right +
shiftValue
: '';

useLayoutEffect(() => {
const button = buttonRef.current as HTMLButtonElement;
const $p = button.parentElement as HTMLElement;
const $pp = $p.parentElement as HTMLElement;

const DOMRect = $pp.getBoundingClientRect();

const { left, right } = DOMRect;

if (direction === 'slick-prev') {
const windowStartPoint = -left;
button.style.left = `${windowStartPoint + shiftValue}px`;
} else if (direction === 'slick-next') {
const windowEndPoint = -windowSize.width + right;
button.style.right = `${windowEndPoint + shiftValue}px`;
}
}, [buttonRef]);

return (
<button
className={classNames(className, buttonVariants[direction])}
style={{ ...style, display: 'flex' }}
ref={buttonRef}
style={{
...style,
display: 'flex',
left: buttonLeftPosition,
right: buttonRightPosition,
}}
onClick={onClick}
>
<CommonIcon
Expand Down
19 changes: 19 additions & 0 deletions src/components/NormalProject/getButtonPositionWithBreakPoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { getCurrentBreakPoints } from '../../utils/layout/getCurrentBreakPoints';

export const getButtonPositionWithBreakPoints = (
breakPoints: BreakPointsBoolean,
) => {
const currentBreakPoints = getCurrentBreakPoints(breakPoints);
switch (currentBreakPoints) {
case 'breakpoint-m':
return 38;
case 'breakpoint-l':
return 48;
case 'breakpoint-xl':
return 60;
case 'breakpoint-xxl':
return 60;
default:
return 80;
}
};
15 changes: 14 additions & 1 deletion src/const/breakpoints/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
export const ODSBreakpointTokenVariables = {
export const ODSBreakpointTokenVariables: BreakPointsTokenInterface = {
'breakpoint-s': 'screen and (max-width: 599px)',
'breakpoint-m': 'screen and (max-width: 839px)',
'breakpoint-l': 'screen and (max-width: 1023px)',
'breakpoint-xl': 'screen and (max-width: 1280px)',
'breakpoint-xxl': 'screen and (max-width: 1535px)',
'breakpoint-FHD': 'screen and (max-width: 1919px)',
};

export const ODSBreakpointTokenVariablesArray: BreakPointsToken[] = Object.keys(
ODSBreakpointTokenVariables,
) as BreakPointsToken[];

export const ODSBreakPointTokenKeyVariables = Object.assign(
{},
...ODSBreakpointTokenVariablesArray.map((key) => ({ [key]: key })),
) as {
[key in BreakPointsToken]: BreakPointsToken;
};
19 changes: 19 additions & 0 deletions src/hook/useODSBreakPoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useMediaQuery } from 'react-responsive';

export const useODSBreakPoints = (): BreakPointsBoolean => {
const breakpointS = useMediaQuery({ query: '(max-width: 599px)' });
const breakpointM = useMediaQuery({ query: '(max-width: 839px)' });
const breakpointL = useMediaQuery({ query: '(max-width: 1023px)' });
const breakpointXL = useMediaQuery({ query: '(max-width: 1280px)' });
const breakpointXXL = useMediaQuery({ query: '(max-width: 1535px)' });
const breakpointFHD = useMediaQuery({ query: '(max-width: 1919px)' });

return {
breakpointS,
breakpointM,
breakpointL,
breakpointXL,
breakpointXXL,
breakpointFHD,
};
};
20 changes: 20 additions & 0 deletions src/hook/useWindowResize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useEffect, useState } from 'react';

export const useWindowResize = () => {
const [windowSize, setWindowSize] = useState<WindowBasedPoints>({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
const handleResize = () => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
};

window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return windowSize;
};
17 changes: 12 additions & 5 deletions src/types/designToken/BreakPoints.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,17 @@ interface BreakPointsTokenInterface {
'breakpoint-m': 'screen and (max-width: 839px)';
'breakpoint-l': 'screen and (max-width: 1023px)';
'breakpoint-xl': 'screen and (max-width: 1280px)';
'breakpoint-xxl': 'screen and (max-width: 1535px)';
'breakpoint-FHD': 'screen and (max-width: 1919px)';
}

type BreakPointsToken =
| 'breakpoint-s'
| 'breakpoint-m'
| 'breakpoint-l'
| 'breakpoint-xl';
type BreakPointsToken = keyof BreakPointsTokenInterface;

interface BreakPointsBoolean {
breakpointS: boolean;
breakpointM: boolean;
breakpointL: boolean;
breakpointXL: boolean;
breakpointXXL: boolean;
breakpointFHD: boolean;
}
4 changes: 4 additions & 0 deletions src/types/utils/Hooks.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface WindowBasedPoints {
width: number;
height: number;
}
17 changes: 17 additions & 0 deletions src/utils/layout/getCurrentBreakPoints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ODSBreakPointTokenKeyVariables } from '@/const/breakpoints';

export const getCurrentBreakPoints = (
breakPoints: BreakPointsBoolean,
): BreakPointsToken => {
if (breakPoints.breakpointS)
return ODSBreakPointTokenKeyVariables['breakpoint-s'];
if (breakPoints.breakpointM)
return ODSBreakPointTokenKeyVariables['breakpoint-m'];
if (breakPoints.breakpointL)
return ODSBreakPointTokenKeyVariables['breakpoint-l'];
if (breakPoints.breakpointXL)
return ODSBreakPointTokenKeyVariables['breakpoint-xl'];
if (breakPoints.breakpointXXL)
return ODSBreakPointTokenKeyVariables['breakpoint-xxl'];
return 'breakpoint-FHD';
};

0 comments on commit be37f31

Please sign in to comment.