๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿฟ Project

[Side PJ] airdnd 2๋ถ€ - ์ƒํƒœ์— ๋”ฐ๋ฅธ CSS ๋ณ€ํ™” (์ƒํƒœ์ง€์˜ฅ State)

by Tamii 2021. 6. 5.
๋ฐ˜์‘ํ˜•

์ด๋ฒˆ์—๋Š” ์™œ ์•ˆ์ฐพ์•„์˜ค๋‚˜ ์‹ถ์—ˆ๋˜ ์ƒํƒœ๊ด€๋ฆฌ์˜ ํ˜ผ๋ž€์ด ๋‹ค์‹œ๊ธˆ ์ฐพ์•„์™”๋‹ค.๐Ÿ˜ต


 

๐Ÿ“Œ ๋‚ ์งœ data  state๋ฅผ ์ด์šฉํ•œ CSS ๋ณ€ํ™”

 

โ– ์ƒํ™ฉ

์ฒดํฌ์ธ๊ณผ ์ฒดํฌ์•„์›ƒ ๋œ๋‚ ์งœ์™€ ๊ทธ ์‚ฌ์ด๋ฅผ CSS ๋กœ ํ‘œ์‹œํ•˜๊ธฐ 

์บ˜๋ฆฐ๋”๋ฅผ ๋งŒ๋“ค๊ณ  ํด๋ฆญ์„ ๋ˆ„๋ฅด๋ฉด  ํ•ด๋‹น dataset์„ ๋ฐ›์•„  ContextAPI๋กœ ๊ด€๋ฆฌํ•˜๋Š” CheckIn, CheckOut ์— ๋ฐ˜์˜์‹œ์ผฐ๋‹ค.

 

click ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ  ๊ทธ ๊ฐ€๋Šฅ์„ฑ์„ ์กฐ๊ฑด๋ฌธ์œผ๋กœ ๋น„๊ตํ•˜์—ฌ  CheckIn, CheckOut ์— ๋ฐ˜์˜ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ dataํ๋ฆ„์„ ์งฐ๋Š”๋ฐ 

 

์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๋Š” ํด๋ฆญ๋œ ๋‚ ์งœ์˜ ์ƒํƒœ๊ด€๋ฆฌ๋‹ค.

CheckIn, CheckOut  data๋Š”  ์ „์—ญ๊ด€๋ฆฌ๊ฐ€ ๋˜๊ณ  ์žˆ๋Š”๋ฐ 

clickedData๋Š” click์ด๋ฒคํŠธ (handleTdBtnClick )์•ˆ์—์„œ๋งŒ ๊ด€๋ฆฌ๋˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—  

rendering์‹œ์— ํ•ด๋‹น ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๊ฒƒ์ด๋‹ค.

์—ฌ๊ธฐ์„œ ๋‚ด๊ฐ€ ๋‚ด๋ฆฐ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์€ ํฌ๊ฒŒ ๋‘๊ฐ€์ง€

 

1)  clickedData๋ฅผ useState๋กœ ๊ด€๋ฆฌํ•˜์ž 

 ์žฅ์ : ์ „์—ญ์ƒํƒœ์˜ ์ตœ์†Œํ™”

2) clikedData๋ฅผ ์ „์—ญ์ƒํƒœ์— ์ถ”๊ฐ€ํ•˜์ž

์žฅ์ : ์ผ๊ด€๋œ ๋‚ ์งœ data๊ด€๋ฆฌ 

---> ๋‹ค ์•„๋‹ˆ์—ˆ๋‹ค. ์ •๋‹ต์€  ์ƒˆ๋กœ์šด ์†์„ฑ์„ ๋ถ€์—ฌํ•˜์—ฌ ์กฐ๊ฑด์œผ๋กœ ๋น„๊ตํ•˜๋ฉฐ ๋ Œ๋”๋ง!


 

 

1) useState ์‹œ๋„ 

1)๋ฒˆ ๋ฐฉ๋ฒ•์ด ์ „์—ญ์ƒํƒœ๋ฅผ ์ตœ์†Œํ™” ํ•˜๋Š” ๋ฐฉํ–ฅ ๊ฐ™์•„ ์ง„ํ–‰ํ–‡์ง€๋งŒ 

baseball๊ณผ ๋น„์Šทํ•œ ๋ฌธ์ œ๋กœ ์‹คํŒจํ–ˆ๋‹ค.

 

clicke ์ด๋ฒคํŠธ

 const handleTdBtnClick = (e) => {
 
    const [clickedYear, clickedMonth, clickedDay] = e.target.dataset.day
      .split('-')
      .map(Number); 
      
    setSelectedDay(new Date(clickedYear, clickedMonth, clickedDay));
    
    //...์ค‘๋žต

Component ๋ Œ๋”๋ง ๋ถ€๋ถ„ 

return (
                <DayTd key={idx}>
                  <DayTdButton
                    data-day={`${year}-${month}-${day}`}
                    onClick={(e) => handleTdBtnClick(e)}
                    dayCliked={selectCheckInDay === selectedDay}
                  >

ํด๋ฆญ์‹œ  -> clickedData ๊ฐฑ์‹  -> checkInData ๊ฐฑ์‹   

์ด ์ˆœ์œผ๋กœ ๋กœ์ง์„ ์งœ๋ฉด ๋ Œ๋”๋ง ์‹œ ์ ์šฉ๋  ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ–ˆ๋Š”๋ฐ,

 

ํด๋ฆญ๋˜๋Š” ์ˆœ๊ฐ„ ๋ Œ๋”๋ง์€ ์ง„ํ–‰๋˜๊ณ  -> useState์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ˜์˜๋˜๊ธฐ ์ „์— ๋ Œ๋”๋ง์ด ํ•œ์ฐจ๋ก€ ์™„๋ฃŒ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์—  -> ํ™”๋ฉด์— ํ‘œํ˜„ํ•œ CSS๋Š” ๋‚˜ํƒ€๋‚˜์ง€ ์•Š๋Š”๋‹ค.

 

 

2) selectorContext ์— clickeddata ์ถ”๊ฐ€

  const [calendarData, calDispatch] = useReducer(calendarReducer, {
    checkIn: { year: 0, month: 0, day: 0 },
    checkOut: { year: 0, month: 0, day: 0 },
  });
  const [calendarData, calDispatch] = useReducer(calendarReducer, {
    checkIn: { year: 0, month: 0, day: 0 },
    checkOut: { year: 0, month: 0, day: 0 },
    clicked: { year: 0, month: 0, day: 0 },
    
  });

์ด๋ ‡๊ฒŒ ์ƒํƒœ data๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค .

ํ•˜์ง€๋งŒ ์‚ฌ์‹ค ์ด ๋ฐฉ๋ฒ•๋„  useState์™€ ๊ฐ™์€ ์˜๋ฏธ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™์€ ํ˜„์ƒ์œผ๋กœ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•˜๋‹ค.

 

 

3) ๋ Œ๋”๋ง ๋‹น์‹œ์˜ dataset๊ณผ  ๋น„๊ต

Component ๋ Œ๋”๋ง ๋ถ€๋ถ„  (์ „)

  return (
    <SingleCalDiv>
      <tbody>
        {monthArr?.map((week, idx) => (
          <DayTr key={idx}>
            {week?.map((day, idx) => (
              <DayTd key={idx}>{day}</DayTd>
            ))}
          </DayTr>
        ))}
      </tbody>
    </SingleCalDiv>
  );
};

Component ๋ Œ๋”๋ง ๋ถ€๋ถ„  (ํ›„)

return (
    <SingleCalDiv>
      <tbody>
        {monthArr?.map((week, idx) => (
          <DayTr key={idx}>
            {week?.map((day, idx) => {
              const checkInTime = checkInDate.getTime();
              const checkOutTime = checkOutDate.getTime();
              const clickedTime = new Date(year, month, day).getTime();
              return (
                <DayTd
                  key={idx}
                  day={day}
                  dayInterval={
                    checkInTime <= clickedTime && clickedTime <= checkOutTime
                  }
                >
                  <DayTdButton
                    disabled={handleDisabled(day)}
                    day={day}
                    data-day={`${year}-${month}-${day}`}
                    onClick={(e) => handleTdBtnClick(e)}
                    dayClicked={
                      checkInTime === clickedTime ||
                      checkOutTime === clickedTime
                    }
                  >
                    {day}
                  </DayTdButton>
                </DayTd>
              );
            })}
          </DayTr>
        ))}
      </tbody>
    </SingleCalDiv>
  );
};

styled-components

const DayTd = styled.td`

  background: ${({ day, dayInterval }) =>
    dayInterval && day !== ' ' ? '#f2f2f2' : 'none'};
  box-shadow: ${({ day, dayInterval }) =>
    dayInterval && day !== ' '
      ? '0 0 4px 0 #F2F2F2, 4px 0 4px 0 #F2F2F2'
      : 'none'};
`;

const DayTdButton = styled.button`
 
  background-color: ${({ dayClicked }) => (dayClicked ? '#333' : 'none')};
  color: ${({ dayClicked }) => (dayClicked ? '#fff' : 'none')};
  :hover {
    box-shadow: ${({ day }) => (day !== ' ' ? '0 0 0 1px #333 inset' : 'none')};
    cursor: ${({ day, disabled }) =>
      day === ' ' || disabled ? 'default' : 'pointer'};
  }
`;

์ฒดํฌ์ธ, ์ฒดํฌ์•„์›ƒ๊ณผ ๋ Œ๋”๋ง ๋˜๋Š” DayTdButton์— dayClicked ์†์„ฑ์„ ์ฃผ๊ณ 

ํ•ด๋‹น ์†์„ฑ์ด true์ด๋ฉด ๊ฒ€์ •์ƒ‰์ƒ์ด ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๊ฒŒ  styledComponents์—์„œ ์กฐ์ •ํ–ˆ๋‹ค.

 


๐Ÿ“Œ table์˜  border ์†์„ฑ

 

hover ์‹œ border๋ฅผ ์ฃผ๋Š” ๊ณผ์ •์—์„œ ์‚ฌ์†Œํ•œ ํ—คํ”„๋‹์ด ์žˆ์–ด๋Š”๋ฐ 

๋ถ„๋ช… box-sizing: border-box๋ฅผ ์ฃผ๋Š”๋ฐ๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์šฐ๊ธ€๊ฑฐ๋ฆฌ๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.

padding์„ ์ค˜์„œ ํ™•์ธํ•ด๋ณด๋‹ˆ box-sizing์ด ์•ˆ๋จน๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค.  

table์˜ td์—๋Š” box-sizing์ด ์•ˆ๋จน์—ˆ๋‹ค ......  (์—„์ฒญ๋‚˜๊ฒŒ๊ณ ์ƒํ•จ 

 

<- ๋‚ด์šฉ์ด ๋‹ค ์ฑ„์›Œ์ž‡์„ ๋•Œ ๋ฌธ์ œ ์—†๋Š” ๋ชจ์Šต

const DayTdButton = styled.button`

  background-color: ${({ dayClicked }) => (dayClicked ? '#333' : 'none')};
  color: ${({ dayClicked }) => (dayClicked ? '#fff' : 'none')};
  :hover {
    box-shadow: ${({ day }) => (day !== ' ' ? '0 0 0 1px #333 inset' : 'none')};
    cursor: ${({ day, disabled }) =>
      day === ' ' || disabled ? 'default' : 'pointer'};
  }
`;

 

 

๋‹ฌ๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค ๋•Œ ๊ณต๊ฐ„์„ ์ฐจ์ง€ํ•ด์•ผ ํ•ด์„œ " " ๊ณต๋ฐฑ์œผ๋กœ ๋„ฃ์–ด์คฌ๋˜ ๋ถ€๋ถ„์ด

<td> ๋‚ด์šฉ์ด ์—†์–ด ์–ด๊ธ‹๋‚œ ๊ฒƒ์ด์—ˆ๋‹ค .

hover ์‹œ border ๊ฐ€ ์•„๋‹Œ box-shadow๋ฅผ ๋„ฃ์Œ์œผ๋กœ์จ ํ•ด๊ฒฐํ–ˆ๋‹ค.

 

๐Ÿ’Œํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š”๋ฐ ๋„์›€์„ ์ค€ Raccon๊ณผ DD์—๊ฒŒ ๊ฐ์‚ฌ์˜ ๋ง์”€์„ ..

 


 

๐Ÿ“Œ  Canves๋ฅผ ์ด์šฉํ•œ ์š”๊ธˆ Slider 

์š”๊ธˆ ์Šฌ๋ผ์ด๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ๋Š” Jenny๊ฐ€ ๋งŽ์€ ๊ณต์„ ์„ธ์› ๋‹ค.โšฝ๏ธ๐Ÿ€..

 

ํ•ด๋‹น ๋ถ€๋ถ„์€ ๊ธธ์ด ๊ธ€์–ด์งˆ ๊ฒƒ๊ฐ™์•„ ๋‹ค๋ฅธ ๊ฒŒ์‹œ๊ธ€๋กœ ์ •๋ฆฌํ–ˆ๋‹ค. 

 

https://rrecoder.tistory.com/145

 

 

 

 

 

๋Œ“๊ธ€