-
Notifications
You must be signed in to change notification settings - Fork 0
[FEAT] Table 컴포넌트 제작 #72
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
Changes from 4 commits
653a29f
6976ae7
8456ee4
099944d
8c20ac5
27a99fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,73 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { Meta, StoryObj } from '@storybook/react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from './index'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const PrimitiveMeta = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: 'Components/Table', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| component: Table, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tags: ['autodocs'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parameters: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| docs: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| component: '기본적인 Table 레이아웃 구성 요소 세트입니다. ', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } satisfies Meta<typeof Table>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default PrimitiveMeta; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const data = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| scoreCategory: '동아리 활동 보고서', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reason: '2회차 활동보고서', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| amount: 4.615, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| createdAt: '2025-03-31 15:42:26', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| scoreCategory: '동아리 활동 보고서', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reason: '2회차 활동보고서', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| amount: 0.001, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| createdAt: '2025-03-31 16:02:31', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| scoreCategory: '전동대회', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reason: '3월 전동대회 참여', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| amount: 1.0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| createdAt: '2025-04-01 11:40:36', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| scoreCategory: '전동대회', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reason: '4월 전동대회 참여', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| amount: 1.0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| createdAt: '2025-04-28 19:44:04', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| scoreCategory: '동아리 활동 보고서', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reason: '3회차 활동보고서', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| amount: 4.615, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| createdAt: '2025-04-30 14:56:26', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const Basic: StoryObj<typeof PrimitiveMeta> = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| render: () => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Table> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <TableHeader> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <TableRow> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <TableHead>날짜</TableHead> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <TableHead>카테고리</TableHead> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <TableHead>점수</TableHead> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </TableRow> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </TableHeader> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <TableBody> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {data.map((row, i) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <TableRow key={i}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial 배열 인덱스를 key로 사용하고 있습니다. 정적 데모 데이터의 경우 허용되지만, 안정적인 고유 식별자를 key로 사용하는 것이 더 좋은 관행입니다. 예를 들어, - {data.map((row, i) => (
- <TableRow key={i}>
+ {data.map((row) => (
+ <TableRow key={`${row.createdAt}-${row.scoreCategory}`}>🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <TableCell>{row.createdAt}</TableCell> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <TableCell>{row.scoreCategory}</TableCell> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <TableCell>{row.amount.toFixed(3)}점</TableCell> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </TableRow> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ))} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </TableBody> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Table> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+52
to
+73
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial 스토리를 더 인터랙티브하게 만들 수 있습니다. 현재 Basic 스토리는 render 함수에 데이터가 하드코딩되어 있어 Storybook의 Controls 패널을 통해 수정할 수 없습니다. 데이터를 args로 받도록 하면 사용자가 다양한 데이터 조합을 테스트할 수 있습니다. 다음과 같이 개선할 수 있습니다: +type StoryArgs = {
+ data: typeof data;
+};
+
-export const Basic: StoryObj<typeof PrimitiveMeta> = {
+export const Basic: StoryObj<StoryArgs> = {
+ args: {
+ data,
+ },
- render: () => (
+ render: ({ data }) => (
<Table>
<TableHeader>
<TableRow>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import * as React from 'react'; | ||
|
|
||
| import { cn } from '@/shared/lib/core'; | ||
|
|
||
| export type Props = React.HTMLAttributes<HTMLTableElement> & { | ||
| /** | ||
| * Optional custom className for additional styling. | ||
| */ | ||
| className?: string; | ||
|
|
||
| /** | ||
| * Table content, usually composed of `<TableHeader>`, `<TableBody>`, etc. | ||
| */ | ||
| children?: React.ReactNode; | ||
| }; | ||
| export function Table({ className, children, ...props }: Props) { | ||
| return ( | ||
| <div | ||
| className={cn('no-scrollbar relative w-full overflow-auto rounded-md border border-gray-100')} | ||
| > | ||
| <table className={cn('w-full table-fixed border-collapse text-sm', className)} {...props}> | ||
| {children} | ||
| </table> | ||
| </div> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import * as React from 'react'; | ||
|
|
||
| import { cn } from '@/shared/lib/core'; | ||
|
|
||
| export type Props = React.HTMLAttributes<HTMLTableSectionElement> & { | ||
| className?: string; | ||
| children?: React.ReactNode; | ||
| }; | ||
|
|
||
| export function TableBody({ className, children, ...props }: Props) { | ||
| return ( | ||
| <tbody className={cn('bg-white', className)} {...props}> | ||
| {children} | ||
| </tbody> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,20 @@ | ||||||||||||||||||||||||||||||||||||||
| import * as React from 'react'; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import { cn } from '@/shared/lib/core'; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import { Body2 } from '../Typography'; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| export type Props = React.TdHTMLAttributes<HTMLTableCellElement> & { | ||||||||||||||||||||||||||||||||||||||
| className?: string; | ||||||||||||||||||||||||||||||||||||||
| children?: React.ReactNode; | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| export function TableCell({ className, children, ...props }: Props) { | ||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||
| <td className={cn('px-4 py-2 align-middle md:px-4', className)} {...props}> | ||||||||||||||||||||||||||||||||||||||
| <Body2 className="whitespace-pre-wrap text-gray-400" weight="normal"> | ||||||||||||||||||||||||||||||||||||||
| {children} | ||||||||||||||||||||||||||||||||||||||
| </Body2> | ||||||||||||||||||||||||||||||||||||||
| </td> | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+12
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial 중복된
참고: Body2에서 패딩을 제거하여 이전 리뷰의 중복 패딩 문제가 해결된 점은 좋습니다. 다음과 같이 수정하여 중복을 제거하세요: - <td className={cn('px-4 py-2 align-middle md:px-4', className)} {...props}>
+ <td className={cn('px-4 py-2 align-middle', className)} {...props}>만약 모바일과 데스크톱에서 다른 패딩을 의도했다면, 다음과 같은 패턴을 사용하세요: - <td className={cn('px-4 py-2 align-middle md:px-4', className)} {...props}>
+ <td className={cn('px-2 py-2 align-middle md:px-4', className)} {...props}>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import * as React from 'react'; | ||
|
|
||
| import { cn } from '@/shared/lib/core'; | ||
|
|
||
| import { Body2 } from '../Typography'; | ||
|
|
||
| export type Props = React.ThHTMLAttributes<HTMLTableCellElement> & { | ||
| className?: string; | ||
| children?: React.ReactNode; | ||
| }; | ||
|
|
||
| export function TableHead({ className, children, ...props }: Props) { | ||
| return ( | ||
| <th | ||
| className={cn('h-10 px-4 py-2 text-left align-middle whitespace-nowrap', className)} | ||
| {...props} | ||
| > | ||
| <Body2 className="text-gray-700">{children}</Body2> | ||
| </th> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import * as React from 'react'; | ||
|
|
||
| import { cn } from '@/shared/lib/core'; | ||
|
|
||
| export type Props = React.HTMLAttributes<HTMLTableSectionElement> & { | ||
| className?: string; | ||
| children?: React.ReactNode; | ||
| }; | ||
|
|
||
| export function TableHeader({ className, children, ...props }: Props) { | ||
| return ( | ||
| <thead className={cn('bg-gray-50', className)} {...props}> | ||
| {children} | ||
| </thead> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import * as React from 'react'; | ||
|
|
||
| import { cn } from '@/shared/lib/core'; | ||
|
|
||
| export type Props = React.HTMLAttributes<HTMLTableRowElement> & { | ||
| className?: string; | ||
| children?: React.ReactNode; | ||
| }; | ||
|
|
||
| export function TableRow({ className, children, ...props }: Props) { | ||
| return ( | ||
| <tr className={cn('border-b border-gray-200 last:border-0', className)} {...props}> | ||
| {children} | ||
| </tr> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| export { Table } from './Table'; | ||
| export { TableHeader } from './TableHeader'; | ||
| export { TableBody } from './TableBody'; | ||
| export { TableRow } from './TableRow'; | ||
| export { TableHead } from './TableHead'; | ||
| export { TableCell } from './TableCell'; |
Uh oh!
There was an error while loading. Please reload this page.