Skip to content

Commit 504689c

Browse files
committed
feat: 스크롤 버튼 커스텀
1 parent bb8f977 commit 504689c

File tree

3 files changed

+19
-53
lines changed

3 files changed

+19
-53
lines changed

packages/design-system/src/components/textarea/testarea.stories.tsx

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ const meta: Meta<typeof Textarea> = {
1313
description: {
1414
component:
1515
'고정 크기 **h-[12rem] / w-[24.8rem]** · 기본 **500자** 제한 · 내용 초과 시 내부 스크롤이 나타나는 텍스트영역입니다. ' +
16-
'`maxLength`로 글자수 제한을 변경할 수 있고, `aria-invalid`를 통해 에러 상태 스타일을 적용할 수 있습니다.',
16+
'`maxLength`로 글자수 제한을 변경할 수 있습니다.',
1717
},
1818
},
1919
},
2020
argTypes: {
21-
className: { table: { disable: true } }, // 구현 상세 prop 숨김
21+
className: { table: { disable: true } },
2222
maxLength: { control: { type: 'number', min: 1 } },
2323
placeholder: { control: 'text' },
2424
defaultValue: { control: 'text' },
@@ -43,35 +43,20 @@ export const Basic: Story = {
4343
};
4444

4545
export const WithMaxLength100: Story = {
46-
name: 'MaxLength=100',
47-
args: { maxLength: 100, placeholder: '최대 100자' },
48-
render: (args) => <Textarea {...args} />,
49-
};
50-
51-
export const InvalidState: Story = {
52-
name: 'Invalid (aria-invalid)',
53-
args: {
54-
'aria-invalid': true,
55-
defaultValue: '형식이 올바르지 않습니다.',
56-
},
57-
render: (args) => <Textarea {...args} />,
58-
};
59-
60-
export const Disabled: Story = {
61-
args: { disabled: true, placeholder: '비활성화 상태' },
46+
name: 'MaxLength=500',
47+
args: { maxLength: 500, placeholder: '최대 500자' },
6248
render: (args) => <Textarea {...args} />,
6349
};
6450

6551
export const ScrollableOverflow: Story = {
6652
name: '넘치면 스크롤',
6753
args: {
68-
defaultValue: 'o '.repeat(400), // 내용 과다로 스크롤 유도
54+
defaultValue: 'o '.repeat(400),
6955
},
7056
render: (args) => <Textarea {...args} />,
7157
play: async ({ canvasElement }) => {
7258
const canvas = within(canvasElement);
7359
const ta = (await canvas.findByRole('textbox')) as HTMLTextAreaElement;
74-
// scrollHeight가 clientHeight보다 크면 내부 스크롤 조건 충족
7560
await expect(ta.scrollHeight).toBeGreaterThan(ta.clientHeight);
7661
},
7762
};

packages/design-system/src/components/textarea/textarea.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ function Textarea({
1818
className={cn(
1919
'h-[12rem] w-[24.8rem]',
2020
'resize-none overflow-y-auto',
21-
'body3-r border-gray200 bg-white-bg text-font-gray-3 rounded-[0.4rem] border px-[0.8rem] py-[1.2rem]',
21+
'body3-r border-gray200 bg-white-bg text-font-gray-3 rounded-[0.4rem] border px-[0.8rem] py-[1.2rem] pr-[1.4rem]',
2222
'focus:border-input outline-none focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0',
23+
'ds-scrollbar',
2324
className
2425
)}
2526
style={{ scrollbarGutter: 'stable' }}
Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,17 @@
1-
/* 스크롤바: 이 Textarea에만 적용 (data-slot + 클래스 스코프) */
2-
:where([data-slot='textarea']).ds-scrollbar {
3-
/* Firefox */
4-
scrollbar-width: thin;
5-
scrollbar-color: color-mix(in oklab, currentColor 35%, transparent)
6-
color-mix(in oklab, currentColor 10%, transparent);
7-
/* 레이아웃 점프 방지용 여유 공간 확보(지원 브라우저에서만) */
8-
scrollbar-gutter: stable;
1+
/* 공통 스크롤바: ds-scrollbar 클래스가 붙은 요소 */
2+
:where(.ds-scrollbar) {
3+
/* Firefox: thumb 색, track 투명 */
4+
scrollbar-color: var(--gray100, #e5e7eb) transparent;
95
}
106

11-
/* WebKit (Chrome, Edge, Safari) */
12-
:where([data-slot='textarea']).ds-scrollbar::-webkit-scrollbar {
13-
width: 8px;
7+
/* WebKit (Chrome/Edge/Safari 일부) */
8+
:where(.ds-scrollbar)::-webkit-scrollbar {
9+
width: 0.4rem; /* 세로 스크롤 폭 */
10+
height: 0.4rem; /* 가로 스크롤 높이 */
1411
}
15-
:where([data-slot='textarea']).ds-scrollbar::-webkit-scrollbar-track {
16-
background: transparent; /* 또는 color-mix(in oklab, currentColor 10%, transparent) */
12+
:where(.ds-scrollbar)::-webkit-scrollbar-track {
13+
background: transparent; /* 배경 제거 */
1714
}
18-
:where([data-slot='textarea']).ds-scrollbar::-webkit-scrollbar-thumb {
19-
background: color-mix(in oklab, currentColor 35%, transparent);
20-
border-radius: 9999px;
21-
border: 2px solid transparent; /* 안쪽만 색이 보이게 */
22-
background-clip: padding-box;
23-
}
24-
:where([data-slot='textarea']).ds-scrollbar::-webkit-scrollbar-thumb:hover {
25-
background: color-mix(in oklab, currentColor 55%, transparent);
26-
}
27-
:where([data-slot='textarea']).ds-scrollbar::-webkit-scrollbar-corner {
28-
background: transparent;
29-
}
30-
31-
/* 다크 모드 톤 보정 (선택) */
32-
@media (prefers-color-scheme: dark) {
33-
:where([data-slot='textarea']).ds-scrollbar {
34-
scrollbar-color: color-mix(in oklab, currentColor 50%, transparent)
35-
color-mix(in oklab, currentColor 20%, transparent);
36-
}
15+
:where(.ds-scrollbar)::-webkit-scrollbar-thumb {
16+
background: var(--gray100, #e5e7eb); /* 토큰 없으면 fallback */
3717
}

0 commit comments

Comments
 (0)