Skip to content

Commit

Permalink
✨ feat: Tabs 컴포넌트 및 스토리북 작성 (#25)
Browse files Browse the repository at this point in the history
* 📦 chore: @radix-ui/react-tabs 설치

* ✨ feat: Tabs 컴포넌트 작성

* ✨ feat: Tabs 스토리북 작성

* 💄 design: 테두리가 피그마와 달라보이는 문제 수정
  • Loading branch information
bbearcookie authored Jan 25, 2024
1 parent 642cdbd commit f26b328
Show file tree
Hide file tree
Showing 5 changed files with 270 additions and 13 deletions.
69 changes: 56 additions & 13 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@emotion/styled": "^11.11.0",
"@hookform/resolvers": "^3.3.4",
"@mui/material": "^5.15.5",
"@radix-ui/react-tabs": "^1.0.4",
"@tanstack/react-query": "^5.17.12",
"axios": "^1.6.5",
"clsx": "^2.1.0",
Expand Down
108 changes: 108 additions & 0 deletions src/components/Tabs/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { css } from '@emotion/react';
import Tabs from './';

const meta = {
title: 'Components/Tabs',
component: Tabs,
tags: ['autodocs'],
argTypes: {},
} satisfies Meta<typeof Tabs>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Primary: Story = {
render: (args) => (
<div
css={css`
padding: 1.25rem;
background-color: #8acef5;
`}
>
<Tabs {...args} />
</div>
),
args: {
defaultValue: 'tab2',
variant: 'primary',
tabItems: [
{
key: 'tab1',
label: 'One',
content: 'Tab one content',
},
{
key: 'tab2',
label: 'Two',
content: 'Tab two content',
},
{
key: 'tab3',
label: 'Three',
content: 'Tab three content',
},
],
},
};

const 보관함Components = {
Content: ({ children }: React.PropsWithChildren) => {
return (
<div
css={css`
display: flex;
flex-direction: column;
gap: 1rem;
margin-top: 1rem;
`}
>
{children}
</div>
);
},
};

export const 보관함: Story = {
render: (args) => (
<div
css={css`
padding: 1.25rem;
background-color: #8acef5;
`}
>
<Tabs {...args} />
</div>
),
args: {
variant: 'primary',
tabItems: [
{
key: '1',
label: '보관한 편지',
content: (
<보관함Components.Content>
{Array.from({ length: 5 }).map((_, i) => (
<div key={i}>from. 낯선 고양이.... 보관한 편지 내용... {i}</div>
))}
</보관함Components.Content>
),
},
{
key: '2',
label: '내가 보낸 편지',
content: (
<보관함Components.Content>
{Array.from({ length: 5 }).map((_, i) => (
<div key={i}>
from. 낯선 고양이.... 내가 보낸 편지 내용... {i}
</div>
))}
</보관함Components.Content>
),
},
],
},
};
45 changes: 45 additions & 0 deletions src/components/Tabs/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import * as T from '@radix-ui/react-tabs';
import styles, { type TabsVariant } from './styles';

interface TabsProps {
/** 탭의 배경 색상과 스타일 등 테마를 지정합니다. */
variant?: TabsVariant;
/** 기본으로 활성화 되어 있을 탭 아이템의 key를 지정합니다. */
defaultValue?: string;
/** 탭 아이템의 목록을 지정합니다. */
tabItems: {
key: string;
label: React.ReactNode;
content: React.ReactNode;
}[];
}

const Tabs = ({ variant = 'primary', defaultValue, tabItems }: TabsProps) => {
defaultValue = defaultValue ?? tabItems[0].key;

return (
<T.Root defaultValue={defaultValue}>
<T.List css={styles.list(variant)} aria-label="Tabs">
{tabItems.map((tabItem) => (
<T.Trigger
css={styles.trigger(variant)}
key={tabItem.key}
value={tabItem.key}
>
{tabItem.label}
</T.Trigger>
))}
</T.List>

{tabItems.map((tabItem) => (
<T.Content key={tabItem.key} value={tabItem.key}>
{tabItem.content}
</T.Content>
))}
</T.Root>
);
};

export default Tabs;
export { default as tabsStyles } from './styles';
Loading

0 comments on commit f26b328

Please sign in to comment.