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] 필터칩 추가 #34

Merged
merged 3 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
48 changes: 48 additions & 0 deletions src/components/common/FilterChips/FilterChip.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
.filterChip {
display: inline-flex;
flex-direction: row;
align-items: center;
padding: 2px 6px 2px 10px;
border-radius: 100px;
margin: 5px;
}

.label {
font-family: "Pretendard";
font-style: normal;
font-weight: 500;
font-size: 14px;
line-height: 20px;
color: #000000;
margin-right: 6px;
}

.close {
cursor: pointer;
width: 18px;
height: 18px;
display: flex;
align-items: center;
justify-content: center;
color: #73777f;
border-radius: 50%;
}

.resetLabel {
font-family: "Pretendard";
font-style: normal;
font-weight: 500;
font-size: 14px;
line-height: 20px;
color: #ba1a1a;
margin-right: 6px;
margin-left: 3px;
}

.resetIcon {
width: 18px;
height: 18px;
display: flex;
align-items: center;
justify-content: center;
}
43 changes: 43 additions & 0 deletions src/components/common/FilterChips/FilterChip.story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from "react";
import type { Meta, StoryObj } from "@storybook/react";
import { FilterChip } from "./FilterChip";

const meta = {
title: "Components/FilterChip",
component: FilterChip,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
argTypes: {},
args: {
label: "",
onRemove: () => {},
},
} satisfies Meta<typeof FilterChip>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
label: "2024",
onRemove: () => {},
},
render: (args) => (
<>
<FilterChip {...args} label="2024" />
<FilterChip {...args} label="연구실" />
<FilterChip {...args} label="웹/어플리케이션" />
</>
),
};

export const Reset: Story = {
args: {
label: "전체해제",
onRemove: () => {},
isReset: true,
},
render: (args) => <FilterChip {...args} />,
};
30 changes: 30 additions & 0 deletions src/components/common/FilterChips/FilterChip.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";
import { render, screen, fireEvent } from "@/utils/test-utils";
import { FilterChip } from "./FilterChip";
import "@testing-library/jest-dom";

describe("FilterChip component", () => {
it("renders correctly with the given label", () => {
render(<FilterChip label="2024" onRemove={() => {}} />);
expect(screen.getByText("2024")).toBeInTheDocument();
});

it("calls onRemove when close button is clicked", () => {
const onRemove = jest.fn();
render(<FilterChip label="2024" onRemove={onRemove} />);
fireEvent.click(screen.getByText("X"));
expect(onRemove).toHaveBeenCalled();
});
});

describe("FilterChipReset component", () => {
it("renders correctly", () => {
render(<FilterChip label="전체해제" onRemove={() => {}} isReset />);
expect(screen.getByText("전체해제")).toBeInTheDocument();
});

it("does not show the close button", () => {
render(<FilterChip label="전체해제" onRemove={() => {}} isReset />);
expect(screen.queryByText("X")).toBeNull();
});
});
41 changes: 41 additions & 0 deletions src/components/common/FilterChips/FilterChip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React, { useEffect, useState } from "react";
import ResetIcon from "./ResetIcon";
import classes from "./FilterChip.module.css";

type FilterChipProps = {
label: string;
onRemove: () => void;
isReset?: boolean;
};

const randomBackgroundColor = () => {
const colors = ["#DFE2EB", "#D1E4FF", "#F3DAFF"];
return colors[Math.floor(Math.random() * colors.length)];
Copy link
Contributor

Choose a reason for hiding this comment

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

backgroundColor와 color를 FilterChip의 props로 받아오게 하면 좋을 것 같아요!

클립 색상을 어떻게 설정해야 하는지는 추후 논의가 필요할 것 같네요..! 노션에 올려두겠습니다 :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

요건 그냥 랜덤으로 되게 두었습니다

};

export function FilterChip({ label, onRemove, isReset = false }: FilterChipProps) {
const [bgColor, setBgColor] = useState<string>("");

useEffect(() => {
if (!isReset) {
setBgColor(randomBackgroundColor());
}
}, [isReset]);

return (
<div className={classes.filterChip} style={{ backgroundColor: isReset ? "#DFE2EB" : bgColor }}>
{!isReset && <span className={classes.label}>{label}</span>}
{!isReset && (
Copy link
Contributor

Choose a reason for hiding this comment

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

{ !isReset && (
  <>
    ...
  </>
)}

위와 같이 처리해도 괜찮을 것 같습니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

tabler icon 적용하였고 resetchip class 새로 만들어 나누어 리턴하는 방식으로 수정했습니다

<span className={classes.close} onClick={onRemove}>
X
</span>
)}
{isReset && (
<>
<ResetIcon />
Copy link
Contributor

Choose a reason for hiding this comment

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

ResetIcon에 hover 했을 때 cursor: pointer로 모양 바꾼다면 좋을 것 같습니다!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

반영했습니다

<span className={classes.resetLabel}>{label}</span>
</>
)}
</div>
);
}
21 changes: 21 additions & 0 deletions src/components/common/FilterChips/ResetIcon.tsx
Copy link
Contributor

@chunzhi23 chunzhi23 Jul 24, 2024

Choose a reason for hiding this comment

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

Tabler Icons를 사용하면 관리가 편할 것 같습니다!

Copy link
Contributor

Choose a reason for hiding this comment

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

Tabler Icons를 적용하는 데에 여기를 참고해 작업해주시면 좋겠습니다!

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";

const ResetIcon = () => (
<svg
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
border-radius="50%"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M10.5 11.25L7.5 14.25L10.5 17.25" stroke="#BA1A1A" />
<path
d="M4.45337 11.625C3.85857 10.5948 3.63128 9.39308 3.80875 8.21679C3.98622 7.0405 4.55791 5.95936 5.43018 5.15047C6.30245 4.34158 7.42357 3.85291 8.60989 3.76451C9.7962 3.67612 10.9774 3.99324 11.9599 4.66392C12.9424 5.3346 13.668 6.31908 14.0178 7.45608C14.3677 8.59308 14.321 9.81518 13.8855 10.9222C13.4499 12.0292 12.6513 12.9554 11.6205 13.5492C10.5897 14.143 9.38777 14.3691 8.21166 14.1905"
stroke="#BA1A1A"
stroke-linecap="round"
/>
</svg>
);

export default ResetIcon;
Loading