Skip to content

Commit 8847991

Browse files
committed
design: Tag 컴포넌트 구현
1 parent 6da0d97 commit 8847991

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

src/components/tag/Tag.styles.ts

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import styled, { type DefaultTheme, css } from "styled-components";
2+
3+
const getVariantStyle = (theme: DefaultTheme) => ({
4+
outline: css`
5+
background-color: ${theme.color.white};
6+
color: ${theme.color.percentOrange};
7+
`,
8+
});
9+
10+
const getRadiusStyle = () => ({
11+
rectangle: css`
12+
border-radius: 8px;
13+
`,
14+
pill: css`
15+
border-radius: 20px;
16+
`,
17+
});
18+
19+
type ButtonProps = {
20+
variant: "outline";
21+
$isTextOnly: boolean;
22+
radius: "rectangle" | "pill";
23+
};
24+
25+
export const StyledTag = styled.button.withConfig({
26+
shouldForwardProp: (prop) => !["variant", "radius"].includes(prop),
27+
})<ButtonProps>`
28+
display: inline-flex;
29+
align-items: center;
30+
gap: 4px;
31+
padding: 0.35rem 0.5rem;
32+
33+
${({ theme }) => theme.typo.caption4};
34+
35+
border: 1px solid ${({ theme }) => theme.color.percentOrange};
36+
37+
${({ theme, variant }) => getVariantStyle(theme)[variant]};
38+
${({ radius }) => getRadiusStyle()[radius]};
39+
40+
aspect-ratio: ${({ $isTextOnly }) => ($isTextOnly ? "1/1" : "auto")}};
41+
`;
42+
43+
export const StyledIcon = styled.span`
44+
display: inline-flex;
45+
align-items: center;
46+
justify-content: center;
47+
`;

src/components/tag/Tag.tsx

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import type { ButtonHTMLAttributes, PropsWithChildren } from "react";
2+
3+
import { StyledIcon, StyledTag } from "./Tag.styles";
4+
5+
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
6+
tag?: "span" | "button";
7+
icon?: boolean;
8+
variant?: "outline";
9+
radius?: "rectangle" | "pill";
10+
}
11+
12+
const Tag = ({
13+
children,
14+
tag = "span",
15+
icon = true,
16+
variant = "outline",
17+
radius = "pill",
18+
...props
19+
}: PropsWithChildren<ButtonProps>) => {
20+
const contentProps = {
21+
icon,
22+
children,
23+
};
24+
25+
return (
26+
<StyledTag
27+
as={tag}
28+
variant={variant}
29+
radius={radius}
30+
$isTextOnly={!icon}
31+
{...props}
32+
>
33+
<ButtonContent {...contentProps} />
34+
</StyledTag>
35+
);
36+
};
37+
38+
type ButtonContentProps = Pick<ButtonProps, "icon" | "children">;
39+
40+
const ButtonContent = (props: ButtonContentProps) => {
41+
const { icon, children } = props;
42+
43+
return (
44+
<>
45+
{icon && <StyledIcon>#</StyledIcon>}
46+
{children}
47+
</>
48+
);
49+
};
50+
51+
export default Tag;

0 commit comments

Comments
 (0)