Skip to content

Commit eaf99ef

Browse files
authored
Merge pull request #94 from SOPT-36-NINEDOT/feat/#92/todoBox
[Feature]: TodoBox 컴포넌트 구현
2 parents aade309 + 29e4a0d commit eaf99ef

File tree

8 files changed

+174
-25
lines changed

8 files changed

+174
-25
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@tanstack/react-query": "^5.81.5",
2424
"@vanilla-extract/recipes": "^0.5.7",
2525
"axios": "^1.10.0",
26+
"clsx": "^2.1.1",
2627
"openapi-typescript": "^7.8.0",
2728
"react": "^19.1.0",
2829
"react-dom": "^19.1.0",

pnpm-lock.yaml

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/page/home/Home.tsx

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,7 @@
1-
import { useState } from 'react';
2-
3-
import { CycleChip } from '../todo/myTodo/component/CycleChip';
4-
import type { CycleType } from '../todo/myTodo/component/CycleChip';
5-
6-
const CYCLE_LIST: CycleType[] = ['매일', '매주', '한번'];
7-
81
const Home = () => {
9-
const [selectedCycle, setSelectedCycle] = useState<CycleType>('매일');
10-
112
return (
12-
<div style={{ padding: '2rem' }}>
3+
<div>
134
<h1></h1>
14-
<h2>CycleChip 테스트</h2>
15-
<div style={{ display: 'flex', gap: '1rem', marginBottom: '2rem' }}>
16-
{CYCLE_LIST.map((cycle) => (
17-
<CycleChip
18-
key={cycle}
19-
type="selector"
20-
value={cycle}
21-
selected={selectedCycle === cycle}
22-
onClick={setSelectedCycle}
23-
/>
24-
))}
25-
</div>
26-
<div style={{ display: 'flex', gap: '1rem' }}>
27-
<CycleChip type="display" value={selectedCycle} />
28-
</div>
295
</div>
306
);
317
};
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { style, styleVariants } from '@vanilla-extract/css';
2+
3+
import { colors } from '@/style/token/color.css';
4+
import { fonts } from '@/style/token/typography.css';
5+
6+
export const todoBoxContainer = styleVariants({
7+
recommend: {
8+
display: 'flex',
9+
flexDirection: 'column',
10+
justifyContent: 'center',
11+
alignItems: 'center',
12+
gap: '1rem',
13+
background: colors.grey4,
14+
borderRadius: '10px',
15+
width: '40.6rem',
16+
padding: '2.4rem 2rem',
17+
},
18+
todo: {
19+
display: 'flex',
20+
justifyContent: 'center',
21+
alignItems: 'center',
22+
background: colors.grey4,
23+
borderRadius: '8px',
24+
width: '43.6rem',
25+
padding: '1.4rem 2rem',
26+
},
27+
});
28+
29+
export const todoItemContainer = styleVariants({
30+
recommend: {
31+
display: 'flex',
32+
justifyContent: 'space-between',
33+
alignItems: 'center',
34+
alignSelf: 'stretch',
35+
},
36+
todo: {
37+
display: 'flex',
38+
justifyContent: 'space-between',
39+
alignItems: 'center',
40+
flex: '1 0 0',
41+
},
42+
});
43+
44+
export const todoText = styleVariants({
45+
recommend: {
46+
width: '33.3rem',
47+
whiteSpace: 'nowrap',
48+
overflow: 'hidden',
49+
textOverflow: 'ellipsis',
50+
color: colors.white01,
51+
...fonts.subtitle05,
52+
},
53+
todo: {
54+
color: colors.grey10,
55+
textAlign: 'center',
56+
...fonts.subtitle02,
57+
},
58+
});
59+
60+
export const checkboxButton = style({
61+
display: 'flex',
62+
alignItems: 'center',
63+
justifyContent: 'center',
64+
width: '2.4rem',
65+
height: '2.4rem',
66+
background: 'none',
67+
border: 'none',
68+
padding: 0,
69+
cursor: 'pointer',
70+
});
71+
72+
export const checkboxIcon = style({
73+
width: '2.4rem',
74+
height: '2.4rem',
75+
});
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import clsx from 'clsx';
2+
3+
import {
4+
todoBoxContainer,
5+
todoItemContainer,
6+
todoText,
7+
checkboxButton,
8+
checkboxIcon,
9+
} from './TodoBox.css';
10+
11+
import { IcCheckboxChecked, IcCheckboxDefault } from '@/assets/svg';
12+
13+
interface TodoBoxProps {
14+
type: 'recommend' | 'todo';
15+
items: TodoItemProps[];
16+
onItemClick?: (item: TodoItemProps) => void;
17+
className?: string;
18+
}
19+
20+
interface TodoItemProps {
21+
id: string;
22+
content: string;
23+
completed?: boolean;
24+
}
25+
26+
const TodoBox = ({ type, items, onItemClick, className }: TodoBoxProps) => (
27+
<div className={clsx(todoBoxContainer[type], className)}>
28+
{items.map((item) => (
29+
<TodoItem key={item.id} item={item} type={type} onItemClick={onItemClick} />
30+
))}
31+
</div>
32+
);
33+
34+
const TodoItem = ({
35+
item,
36+
type,
37+
onItemClick,
38+
}: {
39+
item: TodoItemProps;
40+
type: 'recommend' | 'todo';
41+
onItemClick?: (item: TodoItemProps) => void;
42+
}) => {
43+
const handleClick = () => {
44+
onItemClick?.(item);
45+
};
46+
return (
47+
<div className={todoItemContainer[type]}>
48+
<span className={todoText[type]}>{item.content}</span>
49+
<button
50+
className={checkboxButton}
51+
onClick={handleClick}
52+
aria-label={item.completed ? '완료 취소하기' : '완료하기'}
53+
>
54+
{(() => {
55+
const CheckIcon = item.completed ? IcCheckboxChecked : IcCheckboxDefault;
56+
return <CheckIcon className={checkboxIcon} />;
57+
})()}
58+
</button>
59+
</div>
60+
);
61+
};
62+
63+
export default TodoBox;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export type TodoModeTypes = 'recommend' | 'todo';
2+
3+
export interface TodoItemTypes {
4+
id: string;
5+
content: string;
6+
completed?: boolean;
7+
isRecommended?: boolean;
8+
}
9+
10+
export interface TodoBoxProps {
11+
type: 'recommend' | 'todo';
12+
items: TodoItemTypes[];
13+
onItemClick?: (item: TodoItemTypes) => void;
14+
className?: string;
15+
}
16+
17+
export interface TodoItemProps {
18+
item: TodoItemTypes;
19+
type: TodoModeTypes;
20+
onItemClick?: (item: TodoItemTypes) => void;
21+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default } from './TodoBox';
2+
export type { TodoBoxProps, TodoItemTypes } from './TodoBox.types';
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as TodoBox } from './TodoBox';
2+
export type { TodoBoxProps, TodoItemTypes } from './TodoBox/TodoBox.types';

0 commit comments

Comments
 (0)