Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/#499 등록 ui 개선 및 등록 페이지 리팩터링 #508

Merged
merged 98 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from 87 commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
10bd732
feat: waveScrubber ui 구현
ukkodeveloper Oct 10, 2023
7d55392
refactor: wave ui 별도의 컴포넌트로 분리
ukkodeveloper Oct 10, 2023
c973da2
refactor: useDebounceEffect deps 인자 타입 배열로 수정
ukkodeveloper Oct 10, 2023
6be7ada
refactor: WaveScrubber 이벤트 핸들러 등 리팩터링
ukkodeveloper Oct 10, 2023
436abdb
fix: PlayerState enum 제거
ukkodeveloper Oct 10, 2023
9e2cfd5
feat: 킬링파트 interval 5~15초로 변경
ukkodeveloper Oct 10, 2023
913e23b
design: 슬라이더 디자인 수정
ukkodeveloper Oct 10, 2023
f08767c
design: ios 환경을 고려하여 100vh 적용을 위해 layout 수정
ukkodeveloper Oct 10, 2023
b2af6e2
design: Thumbnail size sm 추가
ukkodeveloper Oct 10, 2023
3e58646
design: Collecting Page 전반적인 디자인 수정
ukkodeveloper Oct 10, 2023
aa0b9a7
feat: badge component 구현
ukkodeveloper Oct 11, 2023
905d31e
feat: progress bar 수정 및 전체 재생 progress bar 구현
ukkodeveloper Oct 11, 2023
be1a18a
design: VoteInterface 상하 간격 조정
ukkodeveloper Oct 11, 2023
228ceac
design: 버튼 및 scrubber 사용 시 디자인 추가
ukkodeveloper Oct 11, 2023
6b939c5
feat: 각종 등록 관련 제어 태그 추가
ukkodeveloper Oct 11, 2023
2e1795b
fix: WaveScrubber 정지 오류 및 터치 시 재생 오류 수정
ukkodeveloper Oct 11, 2023
0cd252e
design: body background black으로 하여 스크롤 끝에 흰색 나오지 않도록 수정
ukkodeveloper Oct 11, 2023
607ec8f
design: register 버튼 디자인 수정
ukkodeveloper Oct 11, 2023
e054219
fix: 파트 등록 페이지에 AuthLayout 재적용
ukkodeveloper Oct 11, 2023
e00119b
refactor: 시작, 정지 버튼 별도의 컴포넌트로 분리
ukkodeveloper Oct 14, 2023
eb8e960
refactor: Flex 컴포넌트 사용하여 WaveScrubber 리팩터링
ukkodeveloper Oct 14, 2023
709cdd5
feat: 킬링파트 등록하는 페이지 반응형 구현
ukkodeveloper Oct 14, 2023
bd956bd
feat: 유튜브 재생 effect 의존성 배열에 플레이어 상태 추가
ukkodeveloper Oct 14, 2023
8db7a4c
design: 사용하지 않는 속성 제거 및 css 속성 수정
ukkodeveloper Oct 14, 2023
8b2ff86
style: styled lint 적용
ukkodeveloper Oct 14, 2023
251865d
refactor: WaveScrubber 구현에 있어 필요없는 컴포넌트 삭제 및 한 데 두기
ukkodeveloper Oct 14, 2023
3be1447
refactor: video 재생 관련 badge 정보들 컴포넌트로 뭉치기
ukkodeveloper Oct 14, 2023
271da9a
refactor: 구간 초 설정하는 컴포넌트 반복 제거 및 스타일 수정
ukkodeveloper Oct 14, 2023
0d83fa9
refactor: 페이지 파트 정하기 안내 메세지 컴포넌트로 분리
ukkodeveloper Oct 14, 2023
b85f8b8
refactor: 등록 요청하는 컴포넌트 분리
ukkodeveloper Oct 14, 2023
dfa6528
refactor: 앨범 자켓, 가수, 제목 컨텐츠를 컴포넌트로 분리
ukkodeveloper Oct 14, 2023
ed1a762
refactor: 비디어를 제어하고 파트를 고르는 컴포넌트 분리
ukkodeveloper Oct 14, 2023
7ec406c
feat: 페이지 단에서 컴포넌트 위계가 보이도록 수정
ukkodeveloper Oct 14, 2023
7780231
design: 데스크탑 사이즈에서 버튼 하단에 오도록 수정
ukkodeveloper Oct 15, 2023
598fe13
design: flex 및 컴포넌트 container 디자인 세부 수정
ukkodeveloper Oct 15, 2023
20e8cdf
design: 긴 글자 올 경우 대비하여 수정
ukkodeveloper Oct 15, 2023
71f5453
chore: 사용하지 않는 컴포넌트 삭제
ukkodeveloper Oct 15, 2023
318b79b
refactor: hook 정리 및 이름 변경
ukkodeveloper Oct 15, 2023
f4f6145
feat: 웹 접근성 및 시멘틱 태그 적용
ukkodeveloper Oct 15, 2023
ac59d22
fix: 등록 공유 url 수정
ukkodeveloper Oct 15, 2023
bd026d0
design: theme에 마젠타 색 팔레트 추가 및 적용
ukkodeveloper Oct 15, 2023
225a688
refactor: Player 상태 enum값 적용 및 관련 함수명 변경
ukkodeveloper Oct 15, 2023
df40820
style: style lint 적용
ukkodeveloper Oct 15, 2023
a1f8881
refactor: Flex suffix로 통일
ukkodeveloper Oct 15, 2023
c32c44d
refactor: color theme 적용
ukkodeveloper Oct 15, 2023
676ad40
fix: 컴포넌트 레이아웃 유튜브, 컨트롤러 부분 속성 변경
ukkodeveloper Oct 16, 2023
b9f75b9
feat: 프로그레스 바 부드럽게 사용할 수 있도록 수정
ukkodeveloper Oct 16, 2023
192451b
fix: 재생, 정지버튼 계속 깜빡거리는 문제 해결
ukkodeveloper Oct 16, 2023
1f72890
fix: Fragment에 key 추가
ukkodeveloper Oct 16, 2023
78eead5
design: HeaderSpacing 추가 및 페이지 패딩 수정
ukkodeveloper Oct 16, 2023
3784a9a
chore: 파트 등록 관련 모듈 킬링파트 디렉터리로 이동
ukkodeveloper Oct 16, 2023
adf5d4c
refactor: interval 상태변경 훅 코드 개선
ukkodeveloper Oct 16, 2023
b63c47e
design: desktop 기준 padding 16px 적용
ukkodeveloper Oct 16, 2023
ee81ed7
refactor: useDebounceEffect 훅으로 변경
ukkodeveloper Oct 16, 2023
f681587
fix: page translateY 제거
ukkodeveloper Oct 16, 2023
ce3d7c1
fix: 전체듣기 toggle 해제 시에 구간 첫 시작으로 이동
ukkodeveloper Oct 16, 2023
9800dca
fix: 10초뒤에 자동시작되는 현상
ukkodeveloper Oct 17, 2023
7c4d0d7
feat: 마우스 휠로 scrubber 탐색할 수 있도록 이벤트 추가
ukkodeveloper Oct 17, 2023
22c605f
fix: 너비에 맞게 시간 초 계산할 수 있도록 수정
ukkodeveloper Oct 17, 2023
d15f4bf
feat: 구간 길이에 따라서 progress bar 길이 변경
ukkodeveloper Oct 17, 2023
f7b923f
feat: Youtube 조작 여부 props로 추가 및 적용
ukkodeveloper Oct 17, 2023
4225145
feat: 데스크탑 환경에서 소제목 제공
ukkodeveloper Oct 17, 2023
482ca98
feat: waveScrubber 드래그 이동 추가
ukkodeveloper Oct 17, 2023
33e8f6a
design: 전반적인 페이지 내 폰트 크기 등 디자인 수정
ukkodeveloper Oct 17, 2023
c6df2b8
feat: wave interaction 추가. 사용성 개선
ukkodeveloper Oct 17, 2023
92e7542
fix: waveScrubber interval 조절 시 시작점 스크롤 문제 해결
ukkodeveloper Oct 17, 2023
ef4142e
feat: 변경된 명세 반영
ukkodeveloper Oct 17, 2023
a4f1934
design: 소제목 폰트 사이즈 변경
ukkodeveloper Oct 17, 2023
dcd0b5e
design: 데스크탑 환경에서 waveScrubber 높이 증가하여 변경
ukkodeveloper Oct 18, 2023
c1dfbb1
refactor: useWave 훅 분리
ukkodeveloper Oct 18, 2023
6505614
design: stepper 버튼 크기 조절 및 스크롤 디자인 수정
ukkodeveloper Oct 18, 2023
f1a42ff
feat: song 조회 명세 변경에 따른 변경
ukkodeveloper Oct 18, 2023
9a490d8
chore: 페이지 내에서 사용될 svg 파일 추가
ukkodeveloper Oct 18, 2023
dd52fc7
fix: 영상 끊김 현상으로 인해 debounce 길이 연장
ukkodeveloper Oct 18, 2023
92afe46
feat: 등록 시간 임시 저장할 수 있도록 pin 기능 추가
ukkodeveloper Oct 18, 2023
c3711ba
refactor: pin 관련 상태 네이밍 변경
ukkodeveloper Oct 18, 2023
89b2b9c
design: 상하 간격 추가
ukkodeveloper Oct 18, 2023
69e4614
fix: 핀 active 상태를 데이터 중심으로 변경
ukkodeveloper Oct 18, 2023
ad9a407
refactor: usePin 분리
ukkodeveloper Oct 18, 2023
44fd17a
feat: 등록 시에 이전 페이지 이동 및 모달 수정
ukkodeveloper Oct 18, 2023
1f22eca
design: pin 디자인 수정
ukkodeveloper Oct 18, 2023
7251648
fix: pin 변경 시 스크롤 연동되지 않는 현상 수정
ukkodeveloper Oct 19, 2023
d119c11
design: 안내 메세지 삭제로 인한 전반적인 높이 수정
ukkodeveloper Oct 19, 2023
e77d50a
refactor: soundwave active 높이변경 함수의 이름 변경
ukkodeveloper Oct 19, 2023
7065662
style: styled lint 적용
ukkodeveloper Oct 19, 2023
615cb57
style: 사용하지 않는 css 속성 제거
ukkodeveloper Oct 19, 2023
f21a517
refactor: ref 이름 명확하게 변경
ukkodeveloper Oct 19, 2023
c4c16f1
Merge branch 'main' into feat/#499
ukkodeveloper Oct 19, 2023
572d1b8
fix: useDebounceEffect 변경사항 적용
ukkodeveloper Oct 19, 2023
07bb3a1
refactor: 조기 리턴으로 로직 변경
ukkodeveloper Oct 19, 2023
6825ec0
fix: 내 파트 등록 시에 비디오 정지되도록 수정
ukkodeveloper Oct 19, 2023
63a8bcc
style: WaveWrapper props 순서 변경
ukkodeveloper Oct 19, 2023
f2baad4
style: SoundWave ref lint 에러 수정
ukkodeveloper Oct 19, 2023
50b2a2e
Merge branch 'main' into feat/#499
ukkodeveloper Oct 19, 2023
955b6d3
feat: pin 및 SoundWave 사용성 개선
ukkodeveloper Oct 19, 2023
5b8d48b
feat: SoundWave 이동 시에 pin 클릭 이벤트 방지
ukkodeveloper Oct 19, 2023
2634432
feat: 스크롤 중 유튜브 재생 정지 방지
ukkodeveloper Oct 19, 2023
0e55af8
Merge branch 'main' into feat/#499
ukkodeveloper Oct 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/src/assets/icon/pin.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions frontend/src/assets/icon/play-stream.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions frontend/src/assets/icon/remove.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
128 changes: 128 additions & 0 deletions frontend/src/features/killingParts/components/RegisterPart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';
import { useAuthContext } from '@/features/auth/components/AuthProvider';
import useCollectingPartContext from '@/features/killingParts/hooks/useCollectingPartContext';
import { usePostKillingPart } from '@/features/killingParts/remotes/usePostKillingPart';
import useVideoPlayerContext from '@/features/youtube/hooks/useVideoPlayerContext';
import useModal from '@/shared/components/Modal/hooks/useModal';
import Modal from '@/shared/components/Modal/Modal';
import Spacing from '@/shared/components/Spacing';
import { toPlayingTimeText } from '@/shared/utils/convertTime';

const RegisterPart = () => {
const { isOpen, openModal, closeModal } = useModal();
const { user } = useAuthContext();
const { interval, partStartTime, songId } = useCollectingPartContext();
const video = useVideoPlayerContext();
const { createKillingPart } = usePostKillingPart();
const navigate = useNavigate();

// 현재 useMutation 훅이 response 객체를 리턴하지 않고 내부적으로 처리합니다.
// 때문에 컴포넌트 단에서 createKillingPart 성공 여부에 따라 등록 완료 만료를 처리를 할 수 없어요!
// 현재 비로그인 시에 등록을 누르면 두 개의 모달이 뜹니다.정
const submitKillingPart = async () => {
video.pause();
await createKillingPart(songId, { startSecond: partStartTime, length: interval });
navigate(-1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💬 -1 은 뒤로가기의 의미이니 '듣기 페이지로 이동' 이라는 의미를 조금 더 확실히 해주면 어떨까요?
💬 추가로 -1은 어떤 페이지에서 접속하든 이전 히스토리로 이동하기 때문에, 이에대한 이슈도 있을 것 같아요.

songId도 사용할 수 있으니 명시해도 좋을 것 같아요.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

장르는 ALL 때릴생각을 하고 이야기했었는데, 우코의 생각이 더 좋은것 같아요! ㅎㅎ
대화를 통해 해결했습니다~

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[대화 정리]

  • 특정 장르에서 노래를 듣다가 내 파트 등록 페이지로 갑니다.
  • 등록 완료 후에는 이전에 사용하던 맥락으로 돌아가야하기 때문에 history 기록을 pop합니다.

};

const voteTimeText = toPlayingTimeText(partStartTime, partStartTime + interval);

return (
<>
<RegisterButton type="submit" onClick={openModal}>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이제 이 버튼을 누르면 비디오 퍼즈 + 모달이 열려야 자연스러울듯 해요.

현재는 -1로 이동하기전 노래를 끄는 함수가 실행됩니당

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영완료!

등록
</RegisterButton>
<Modal isOpen={isOpen} closeModal={closeModal}>
<ModalTitle>
<TitleColumn>{user?.nickname}님의 파트 저장</TitleColumn>
</ModalTitle>
<ModalContent>
<Message>
<Part>{voteTimeText}</Part>
</Message>
<Spacing direction="vertical" size={6} />
<Message>나만의 파트로 등록하시겠습니까?</Message>
</ModalContent>
<ButtonContainer>
<Confirm type="button" onClick={closeModal}>
취소
</Confirm>
<Share type="button" onClick={submitKillingPart}>
등록
</Share>
</ButtonContainer>
</Modal>
</>
);
};

export default RegisterPart;

const RegisterButton = styled.button`
width: 100%;
margin-top: auto;
padding: 8px 11px;

font-weight: 700;
color: ${({ theme: { color } }) => color.white};
letter-spacing: 6px;

background-color: ${({ theme: { color } }) => color.primary};
border-radius: 6px;

@media (min-width: ${({ theme }) => theme.breakPoints.md}) {
padding: 11px 15px;

font-size: 18px;
}
`;

const ModalTitle = styled.h3``;

const TitleColumn = styled.div`
text-align: center;
`;

const ModalContent = styled.div`
padding: 16px 0;

font-size: 16px;
color: #b5b3bc;
text-align: center;
white-space: pre-line;
`;

const Message = styled.div``;

const Button = styled.button`
height: 36px;
color: ${({ theme: { color } }) => color.white};
border-radius: 10px;
`;

const Confirm = styled(Button)`
flex: 1;
background-color: ${({ theme: { color } }) => color.secondary};
`;

const Share = styled(Button)`
flex: 1;
background-color: ${({ theme: { color } }) => color.primary};
`;

const ButtonContainer = styled.div`
display: flex;
gap: 16px;
width: 100%;
`;

const Part = styled.span`
padding: 6px 11px;

color: white;
letter-spacing: 1px;

background-color: ${({ theme: { color } }) => color.disabled};
border-radius: 10px;
`;
63 changes: 63 additions & 0 deletions frontend/src/features/killingParts/components/SoundWave.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React, { forwardRef } from 'react';
import styled from 'styled-components';

interface SoundWaveProps {
length: number;
progressWidth: number;
}
// eslint-disable-next-line react/display-name
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💬 SoundWave.displayName =SoundWave
추가하면 warning이 사라지지 않던가용?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SoundWave.displayName = 'SoundWave'; 적용완료

const SoundWave = forwardRef<HTMLDivElement, SoundWaveProps>(
({ length, progressWidth }, boxRef) => {
const stretchWaveHeight =
(activeHeight: string, inactiveHeight: string) => (dom: HTMLDivElement | null) => {
if (!dom || !boxRef || typeof boxRef === 'function') return;
if (boxRef.current?.scrollLeft) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💬 제약되는 상황이 아니라면 얼리리턴으로 댑스를 줄여도 좋겠네요!

const boxPos =
boxRef.current?.scrollLeft + boxRef.current?.clientWidth / 2 - progressWidth / 2;

const containerRightEdge = boxPos + progressWidth;
const itemRightEdge = dom.offsetLeft;

if (itemRightEdge >= boxPos && itemRightEdge <= containerRightEdge) {
dom.style.height = activeHeight;
} else {
dom.style.height = inactiveHeight;
}
}
};

return Array.from({ length }, (_, index) => (
<React.Fragment key={index}>
<LongBar ref={stretchWaveHeight('25px', '20px')} />
<ShortBar ref={stretchWaveHeight('17px', '12px')} />
</React.Fragment>
));
}
);

export default SoundWave;

const LongBar = styled.div`
z-index: 2;
left: 50%;

width: 4px;
height: 24px;

background-color: ${({ theme: { color } }) => color.white};
border-radius: 5px;

transition: height 0.2s ease;
`;

const ShortBar = styled.div`
z-index: 2;

width: 4px;
height: 15px;

background-color: ${({ theme: { color } }) => color.white};
border-radius: 5px;

transition: height 0.2s ease;
`;
182 changes: 182 additions & 0 deletions frontend/src/features/killingParts/components/VideoBadges.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import styled, { css, keyframes } from 'styled-components';
import playIcon from '@/assets/icon/fill-play.svg';
import pauseIcon from '@/assets/icon/pause.svg';
import pinIcon from '@/assets/icon/pin.svg';
import playStreamIcon from '@/assets/icon/play-stream.svg';
import removeIcon from '@/assets/icon/remove.svg';
import useCollectingPartContext from '@/features/killingParts/hooks/useCollectingPartContext';
import usePin from '@/features/killingParts/hooks/usePin';
import useVideoPlayerContext from '@/features/youtube/hooks/useVideoPlayerContext';
import Flex from '@/shared/components/Flex/Flex';
import { toMinSecText } from '@/shared/utils/convertTime';

const VideoBadges = () => {
const { partStartTime, isPlayingEntire, toggleEntirePlaying } = useCollectingPartContext();
const {
pinList,
isPinListEmpty,
activePinIndex,
pinContainerRef,
pinAnimationRef,
addPin,
deletePin,
playPin,
} = usePin();
const video = useVideoPlayerContext();

const partStartTimeText = toMinSecText(partStartTime);
const isPaused = video.playerState === YT.PlayerState.PAUSED;
const videoPlay = () => {
if (isPlayingEntire) {
video.play();
} else {
video.seekTo(partStartTime);
}
};

const videoPause = () => {
video.pause();
};

return (
<>
<Flex $gap={14} $justify="flex-end">
<StartBadge>
<img src={playStreamIcon} style={{ marginRight: '4px' }} alt="" />
{partStartTimeText}
</StartBadge>
<Badge as="button" onClick={addPin} $isActive={!isPinListEmpty}>
<img src={pinIcon} alt="나만의 파트 임시 저장" />
</Badge>
<Badge as="button" type="button" onClick={isPaused ? videoPlay : videoPause}>
<img src={isPaused ? playIcon : pauseIcon} alt={'재생 혹은 정지'} />
</Badge>
<Badge as="button" type="button" $isActive={isPlayingEntire} onClick={toggleEntirePlaying}>
전체 듣기
</Badge>
</Flex>
<PinFlex $gap={4} ref={pinContainerRef}>
{!isPinListEmpty && (
<DeleteBadge as="button" onClick={deletePin}>
<img src={removeIcon} alt="나만의 파트 임시 저장 삭제하기" />
</DeleteBadge>
)}
<PinInner $gap={4} ref={pinContainerRef}>
{pinList.map((pin, index) => (
<PinBadge
key={pin.text + pinAnimationRef.current}
as="button"
onClick={playPin(pin.partStartTime, pin.interval)}
$isActive={index === activePinIndex}
$isNew={index === 0 && index === activePinIndex}
>
{pin.text}
</PinBadge>
))}
</PinInner>
</PinFlex>
</>
);
};
export default VideoBadges;

const PinFlex = styled(Flex)`
width: 100%;
`;

const PinInner = styled(Flex)`
overflow-x: scroll;
width: calc(100% - 44px);
`;

const Badge = styled.span<{ $isActive?: boolean }>`
display: flex;
align-items: center;
justify-content: center;

min-width: 40px;
height: 30px;
padding: 0 10px;

font-size: 14px;
color: ${({ theme: { color } }) => color.white};
text-align: center;

background-color: ${({ theme: { color }, $isActive }) =>
$isActive ? color.magenta700 : color.disabled};
border-radius: 40px;

transition:
background-color 0.2s ease-in,
box-shadow 0.2s ease;

&:active {
box-shadow: 0 0 0 1px inset white;
}

@media (min-width: ${({ theme }) => theme.breakPoints.md}) {
font-size: 16px;
}
`;

const StartBadge = styled(Badge)`
margin-right: auto;
letter-spacing: 1px;
`;

const slideFirstItem = keyframes`
from {
opacity: 0;
transform: translateX(-30px);

}
to {
opacity: 1;
transform: translateX(0);
}
`;

const slideRestItems = keyframes`
from {
transform: translateX(-15px);
}
to {
transform: translateX(0);
}
`;

const PinBadge = styled(Badge)<{ $isActive?: boolean; $isNew?: boolean }>`
z-index: ${({ $isActive }) => ($isActive ? 1 : 0)};

width: 50px;
margin-right: 4px;

font-size: 12px;
color: black;
white-space: nowrap;

opacity: ${({ $isActive }) => ($isActive ? 1 : 0.5)};
background-color: ${({ theme: { color }, $isActive }) =>
$isActive ? color.magenta700 : color.disabledBackground};
border: none;
border-radius: 4px;

transition: background-color 0.5s ease-in-out;
animation: ${({ $isNew }) =>
$isNew
? css`
${slideFirstItem} 1s forwards
`
: css`
${slideRestItems} 0.5s forwards
`};
`;

const DeleteBadge = styled(Badge)`
min-width: 30px;
height: 30px;
margin-right: 10px;
padding: 0;

border-radius: 50%;
`;
Loading
Loading