@uniai-fe/uds-primitives 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -5
- package/dist/styles.css +236 -279
- package/package.json +4 -4
- package/src/components/badge/markup/Badge.tsx +10 -0
- package/src/components/badge/styles/index.scss +2 -2
- package/src/components/badge/types/index.ts +1 -1
- package/src/components/button/index.scss +3 -1
- package/src/components/button/index.tsx +9 -1
- package/src/components/button/markup/ButtonDefault.tsx +162 -0
- package/src/components/button/markup/ButtonRounded.tsx +48 -0
- package/src/components/button/markup/ButtonText.tsx +49 -0
- package/src/components/button/markup/index.ts +3 -0
- package/src/components/button/styles/{index.scss → button.scss} +148 -362
- package/src/components/button/styles/round-button.scss +56 -0
- package/src/components/button/styles/text-button.scss +96 -0
- package/src/components/button/types/index.ts +110 -35
- package/src/components/button/types/templates.ts +33 -0
- package/src/components/button/utils/index.ts +19 -19
- package/src/components/checkbox/markup/Checkbox.tsx +20 -2
- package/src/components/checkbox/types/checkbox.ts +16 -0
- package/src/components/chip/markup/Chip.tsx +8 -0
- package/src/components/dialog/markup/{confirm-dialog.tsx → ConfirmDialog.tsx} +23 -0
- package/src/components/dialog/markup/{notice-dialog.tsx → NoticeDialog.tsx} +18 -0
- package/src/components/dialog/markup/index.tsx +2 -2
- package/src/components/dialog/types/index.ts +43 -0
- package/src/components/drawer/markup/{drawer.tsx → Drawer.tsx} +58 -0
- package/src/components/drawer/markup/index.tsx +1 -1
- package/src/components/drawer/types/index.ts +24 -0
- package/src/components/input/markup/text/Base.tsx +32 -3
- package/src/components/input/markup/text/Identification.tsx +15 -2
- package/src/components/input/markup/text/Password.tsx +35 -2
- package/src/components/input/markup/text/Phone.tsx +38 -2
- package/src/components/input/markup/text/Search.tsx +30 -1
- package/src/components/input/styles/index.scss +6 -6
- package/src/components/input/types/index.ts +22 -1
- package/src/components/input/utils/index.ts +6 -0
- package/src/components/navigation/markup/mobile/BottomNavigation.tsx +11 -0
- package/src/components/navigation/types/index.ts +22 -0
- package/src/components/pagination/markup/Carousel.tsx +1 -0
- package/src/components/pagination/markup/Count.tsx +1 -0
- package/src/components/pagination/markup/Pagination.tsx +2 -0
- package/src/components/radio/markup/Radio.tsx +16 -2
- package/src/components/radio/markup/RadioCard.tsx +8 -0
- package/src/components/radio/markup/RadioCardGroup.tsx +8 -0
- package/src/components/radio/types/radio.ts +39 -0
- package/src/components/segmented-control/markup/SegmentedControl.tsx +12 -0
- package/src/components/segmented-control/types/index.ts +16 -0
- package/src/components/tab/markup/TabContent.tsx +5 -0
- package/src/components/tab/markup/TabList.tsx +19 -2
- package/src/components/tab/markup/TabRoot.tsx +50 -4
- package/src/components/tab/markup/TabTrigger.tsx +9 -1
- package/src/components/tab/styles/index.scss +28 -10
- package/src/components/tab/types/index.ts +10 -0
- package/src/components/tab/utils/tab-context.ts +8 -2
- package/src/components/button/markup/Button.tsx +0 -175
- package/src/components/button/markup/index.tsx +0 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
@use "@uniai-fe/uds-foundation/css";
|
|
2
|
+
|
|
3
|
+
.button.button-template-round {
|
|
4
|
+
min-width: auto;
|
|
5
|
+
padding-block: var(
|
|
6
|
+
--theme-button-round-padding-block,
|
|
7
|
+
var(--spacing-padding-2, 4px)
|
|
8
|
+
);
|
|
9
|
+
padding-inline: var(
|
|
10
|
+
--theme-button-round-padding-inline-medium,
|
|
11
|
+
var(--spacing-padding-6, 16px)
|
|
12
|
+
);
|
|
13
|
+
gap: var(--spacing-gap-2, 8px);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.button.button-template-round-size-small {
|
|
17
|
+
min-height: var(
|
|
18
|
+
--theme-button-round-min-height-small,
|
|
19
|
+
var(--theme-size-small-2, 24px)
|
|
20
|
+
);
|
|
21
|
+
padding-inline: var(
|
|
22
|
+
--theme-button-round-padding-inline-small,
|
|
23
|
+
var(--spacing-padding-5, 12px)
|
|
24
|
+
);
|
|
25
|
+
border-radius: var(
|
|
26
|
+
--theme-button-round-radius-small,
|
|
27
|
+
var(--theme-radius-xlarge-2, 16px)
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.button.button-template-round-size-medium {
|
|
32
|
+
min-height: var(
|
|
33
|
+
--theme-button-round-min-height-medium,
|
|
34
|
+
var(--theme-size-small-3, 32px)
|
|
35
|
+
);
|
|
36
|
+
padding-inline: var(
|
|
37
|
+
--theme-button-round-padding-inline-medium,
|
|
38
|
+
var(--spacing-padding-6, 16px)
|
|
39
|
+
);
|
|
40
|
+
border-radius: var(
|
|
41
|
+
--theme-button-round-radius-medium,
|
|
42
|
+
var(--theme-radius-xlarge-2, 16px)
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.button.button-template-round-size-large {
|
|
47
|
+
min-height: var(
|
|
48
|
+
--theme-button-round-min-height-large,
|
|
49
|
+
var(--theme-size-medium-1, 40px)
|
|
50
|
+
);
|
|
51
|
+
padding-inline: var(
|
|
52
|
+
--theme-button-round-padding-inline-large,
|
|
53
|
+
var(--spacing-padding-7, 20px)
|
|
54
|
+
);
|
|
55
|
+
border-radius: var(--theme-button-round-radius-large, 30px);
|
|
56
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
@use "@uniai-fe/uds-foundation/css";
|
|
2
|
+
|
|
3
|
+
.button.button-template-text {
|
|
4
|
+
min-width: auto;
|
|
5
|
+
border-color: transparent;
|
|
6
|
+
background-color: transparent;
|
|
7
|
+
padding-block: var(
|
|
8
|
+
--theme-button-text-padding-block,
|
|
9
|
+
var(--spacing-padding-4, 8px)
|
|
10
|
+
);
|
|
11
|
+
padding-inline: var(
|
|
12
|
+
--theme-button-text-padding-inline-small,
|
|
13
|
+
var(--spacing-padding-4, 8px)
|
|
14
|
+
);
|
|
15
|
+
border-width: 0;
|
|
16
|
+
gap: var(--spacing-gap-1, 4px);
|
|
17
|
+
border-radius: var(
|
|
18
|
+
--theme-button-text-radius,
|
|
19
|
+
var(--theme-radius-small, 4px)
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.button.button-template-text-size-small {
|
|
24
|
+
min-height: var(
|
|
25
|
+
--theme-button-text-min-height-small,
|
|
26
|
+
var(--theme-size-small-1, 20px)
|
|
27
|
+
);
|
|
28
|
+
padding-inline: var(
|
|
29
|
+
--theme-button-text-padding-inline-small,
|
|
30
|
+
var(--spacing-padding-4, 8px)
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.button.button-template-text-size-medium {
|
|
35
|
+
min-height: var(
|
|
36
|
+
--theme-button-text-min-height-medium,
|
|
37
|
+
var(--theme-size-small-2, 24px)
|
|
38
|
+
);
|
|
39
|
+
padding-inline: var(
|
|
40
|
+
--theme-button-text-padding-inline-medium,
|
|
41
|
+
var(--spacing-padding-5, 12px)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.button.button-template-text-size-large {
|
|
46
|
+
min-height: var(
|
|
47
|
+
--theme-button-text-min-height-large,
|
|
48
|
+
var(--theme-size-small-3, 32px)
|
|
49
|
+
);
|
|
50
|
+
padding-inline: var(
|
|
51
|
+
--theme-button-text-padding-inline-large,
|
|
52
|
+
var(--spacing-padding-5, 12px)
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.button.button-template-text:disabled {
|
|
57
|
+
background-color: transparent;
|
|
58
|
+
border-color: transparent;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.button.button-template-text.button-priority-secondary {
|
|
62
|
+
color: var(
|
|
63
|
+
--theme-button-color-primary-default,
|
|
64
|
+
var(--color-primary-default)
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
&:hover:not(:disabled),
|
|
68
|
+
&[data-user-action="hover"]:not(:disabled) {
|
|
69
|
+
background-color: var(
|
|
70
|
+
--color-bg-alternative-cool-gray,
|
|
71
|
+
var(--color-cool-gray-95)
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
&:active:not(:disabled),
|
|
76
|
+
&[data-user-action="pressed"]:not(:disabled) {
|
|
77
|
+
background-color: var(--color-secondary-strong, var(--color-blue-90));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.button.button-template-text.button-priority-tertiary {
|
|
82
|
+
color: var(--theme-button-color-cool-gray-10, var(--color-cool-gray-10));
|
|
83
|
+
|
|
84
|
+
&:hover:not(:disabled),
|
|
85
|
+
&[data-user-action="hover"]:not(:disabled) {
|
|
86
|
+
background-color: var(
|
|
87
|
+
--color-bg-alternative-cool-gray,
|
|
88
|
+
var(--color-cool-gray-95)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
&:active:not(:disabled),
|
|
93
|
+
&[data-user-action="pressed"]:not(:disabled) {
|
|
94
|
+
background-color: var(--color-bg-surface-strong, var(--color-cool-gray-20));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -1,49 +1,116 @@
|
|
|
1
|
-
import type { ComponentPropsWithoutRef,
|
|
1
|
+
import type { ComponentPropsWithoutRef, ElementType, ReactNode } from "react";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
|
|
4
|
+
* 지원하는 priority 축. semantic color 세트를 결정할 때 사용한다.
|
|
5
|
+
*/
|
|
6
|
+
export const BUTTON_PRIORITIES = ["primary", "secondary", "tertiary"] as const;
|
|
7
|
+
/**
|
|
8
|
+
* scale은 fill/size 조합을 묶어 버튼 spacing/height/타이포를 설정한다.
|
|
9
|
+
*/
|
|
10
|
+
export const BUTTON_SCALES = [
|
|
11
|
+
"solid-xlarge",
|
|
12
|
+
"solid-large",
|
|
13
|
+
"solid-medium",
|
|
14
|
+
"solid-small",
|
|
15
|
+
"outlined-xlarge",
|
|
16
|
+
"outlined-large",
|
|
17
|
+
"outlined-medium",
|
|
18
|
+
"outlined-small",
|
|
19
|
+
] as const;
|
|
20
|
+
/**
|
|
21
|
+
* state는 디자인 토큰에서 정의한 3단계만 노출한다.
|
|
6
22
|
*/
|
|
7
|
-
export const BUTTON_VARIANTS = ["solid", "outlined", "text-button"] as const;
|
|
8
|
-
export const BUTTON_INTENTS = ["primary", "secondary", "teritary"] as const;
|
|
9
|
-
export const BUTTON_SIZES = ["xlarge", "large", "medium", "small"] as const;
|
|
10
|
-
export const BUTTON_SHAPES = ["default", "round"] as const;
|
|
11
23
|
export const BUTTON_STATES = ["default", "readonly", "disabled"] as const;
|
|
12
|
-
|
|
24
|
+
/**
|
|
25
|
+
* data-user-action attribute로 강제 표현할 수 있는 상호작용 모드.
|
|
26
|
+
*/
|
|
27
|
+
export const BUTTON_USER_ACTIONS = ["hover", "pressed"] as const;
|
|
13
28
|
|
|
14
|
-
export type
|
|
15
|
-
export type
|
|
16
|
-
export type ButtonSize = (typeof BUTTON_SIZES)[number];
|
|
17
|
-
export type ButtonShape = (typeof BUTTON_SHAPES)[number];
|
|
29
|
+
export type ButtonPriority = (typeof BUTTON_PRIORITIES)[number];
|
|
30
|
+
export type ButtonScale = (typeof BUTTON_SCALES)[number];
|
|
18
31
|
export type ButtonState = (typeof BUTTON_STATES)[number];
|
|
19
|
-
export type
|
|
32
|
+
export type ButtonUserAction = (typeof BUTTON_USER_ACTIONS)[number];
|
|
20
33
|
export type ButtonIconSlot = "none" | "left" | "right";
|
|
21
34
|
|
|
35
|
+
export type ButtonFill = "solid" | "outlined";
|
|
36
|
+
export type ButtonSize = "xlarge" | "large" | "medium" | "small";
|
|
37
|
+
export type ButtonScaleGroup = ButtonFill;
|
|
38
|
+
|
|
39
|
+
type ButtonScaleConfig = {
|
|
40
|
+
fill: ButtonFill;
|
|
41
|
+
group: ButtonScaleGroup;
|
|
42
|
+
size: ButtonSize;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const createScaleConfig = (
|
|
46
|
+
fill: ButtonFill,
|
|
47
|
+
size: ButtonSize,
|
|
48
|
+
group: ButtonScaleGroup,
|
|
49
|
+
): ButtonScaleConfig => ({
|
|
50
|
+
fill,
|
|
51
|
+
size,
|
|
52
|
+
group,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* scale 별 fill/size/group 메타데이터. className이나 slot 로직이 동일한 source를 참고할 수 있다.
|
|
57
|
+
*/
|
|
58
|
+
export const BUTTON_SCALE_CONFIG: Record<ButtonScale, ButtonScaleConfig> = {
|
|
59
|
+
"solid-xlarge": createScaleConfig("solid", "xlarge", "solid"),
|
|
60
|
+
"solid-large": createScaleConfig("solid", "large", "solid"),
|
|
61
|
+
"solid-medium": createScaleConfig("solid", "medium", "solid"),
|
|
62
|
+
"solid-small": createScaleConfig("solid", "small", "solid"),
|
|
63
|
+
"outlined-xlarge": createScaleConfig("outlined", "xlarge", "outlined"),
|
|
64
|
+
"outlined-large": createScaleConfig("outlined", "large", "outlined"),
|
|
65
|
+
"outlined-medium": createScaleConfig("outlined", "medium", "outlined"),
|
|
66
|
+
"outlined-small": createScaleConfig("outlined", "small", "outlined"),
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* 인터랙션 제약을 위해 fill 축으로 scale을 그룹화한 매핑.
|
|
71
|
+
*/
|
|
72
|
+
export const BUTTON_SCALE_GROUPS: Record<ButtonScaleGroup, ButtonScale[]> = {
|
|
73
|
+
solid: ["solid-xlarge", "solid-large", "solid-medium", "solid-small"],
|
|
74
|
+
outlined: [
|
|
75
|
+
"outlined-xlarge",
|
|
76
|
+
"outlined-large",
|
|
77
|
+
"outlined-medium",
|
|
78
|
+
"outlined-small",
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 우선순위 default. (primary)
|
|
84
|
+
*/
|
|
85
|
+
export const DEFAULT_BUTTON_PRIORITY: ButtonPriority = "primary";
|
|
86
|
+
/**
|
|
87
|
+
* scale default. (solid-medium)
|
|
88
|
+
*/
|
|
89
|
+
export const DEFAULT_BUTTON_SCALE: ButtonScale = "solid-medium";
|
|
90
|
+
|
|
22
91
|
type NativeButtonProps = ComponentPropsWithoutRef<"button">;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
*/
|
|
30
|
-
children?: ReactNode;
|
|
92
|
+
type AnchorProps = ComponentPropsWithoutRef<"a">;
|
|
93
|
+
|
|
94
|
+
type SharedElementProps = Omit<NativeButtonProps, "children"> &
|
|
95
|
+
Omit<AnchorProps, "children">;
|
|
96
|
+
|
|
97
|
+
export interface ButtonProps extends SharedElementProps {
|
|
31
98
|
/**
|
|
32
|
-
*
|
|
99
|
+
* 렌더링할 요소. 기본값은 button.
|
|
33
100
|
*/
|
|
34
|
-
|
|
101
|
+
as?: ElementType;
|
|
35
102
|
/**
|
|
36
|
-
*
|
|
103
|
+
* 주 버튼 내용. 문자열이면 `<span class="button-label">`로 자동 감싼다.
|
|
37
104
|
*/
|
|
38
|
-
|
|
105
|
+
children?: ReactNode;
|
|
39
106
|
/**
|
|
40
|
-
*
|
|
107
|
+
* 레이아웃/spacing 집합. 예) `solid-large`, `outlined-medium`.
|
|
41
108
|
*/
|
|
42
|
-
|
|
109
|
+
scale?: ButtonScale;
|
|
43
110
|
/**
|
|
44
|
-
*
|
|
111
|
+
* semantic color priority.
|
|
45
112
|
*/
|
|
46
|
-
|
|
113
|
+
priority?: ButtonPriority;
|
|
47
114
|
/**
|
|
48
115
|
* UI state: readonly/disabled 를 명시적으로 설정할 수 있다.
|
|
49
116
|
*/
|
|
@@ -65,15 +132,23 @@ export interface ButtonProps extends Omit<
|
|
|
65
132
|
*/
|
|
66
133
|
icon?: ReactNode;
|
|
67
134
|
/**
|
|
68
|
-
* 라벨
|
|
135
|
+
* 라벨 왼쪽에 표시할 슬롯.
|
|
69
136
|
*/
|
|
70
|
-
|
|
137
|
+
left?: ReactNode;
|
|
71
138
|
/**
|
|
72
|
-
* 라벨
|
|
139
|
+
* 라벨 오른쪽에 표시할 슬롯.
|
|
73
140
|
*/
|
|
74
|
-
|
|
141
|
+
right?: ReactNode;
|
|
75
142
|
/**
|
|
76
|
-
* Storybook
|
|
143
|
+
* Storybook 등에서 hover/pressed 상태를 강제로 보여줄 때 사용하는 data attribute.
|
|
77
144
|
*/
|
|
78
|
-
"data-
|
|
145
|
+
"data-user-action"?: ButtonUserAction;
|
|
79
146
|
}
|
|
147
|
+
|
|
148
|
+
export type {
|
|
149
|
+
TextButtonProps,
|
|
150
|
+
TextButtonPriority,
|
|
151
|
+
TextButtonSize,
|
|
152
|
+
RoundButtonProps,
|
|
153
|
+
RoundButtonSize,
|
|
154
|
+
} from "./templates";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ButtonPriority, ButtonProps } from ".";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TextButton 컴포넌트에서 허용하는 size 축.
|
|
5
|
+
*/
|
|
6
|
+
export type TextButtonSize = "small" | "medium" | "large";
|
|
7
|
+
/**
|
|
8
|
+
* TextButton은 secondary/tertiary priority만 허용한다.
|
|
9
|
+
*/
|
|
10
|
+
export type TextButtonPriority = Exclude<ButtonPriority, "primary">;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* TextButton 템플릿 props. scale/priority는 템플릿에서 내부적으로 제어하므로 제거했다.
|
|
14
|
+
*/
|
|
15
|
+
export interface TextButtonProps extends Omit<
|
|
16
|
+
ButtonProps,
|
|
17
|
+
"scale" | "priority"
|
|
18
|
+
> {
|
|
19
|
+
size?: TextButtonSize;
|
|
20
|
+
priority?: TextButtonPriority;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* RoundButton 컴포넌트에서 지원하는 size 축.
|
|
25
|
+
*/
|
|
26
|
+
export type RoundButtonSize = "small" | "medium" | "large";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* RoundButton 템플릿 props. scale은 템플릿 안에서 size에 따라 파생된다.
|
|
30
|
+
*/
|
|
31
|
+
export interface RoundButtonProps extends Omit<ButtonProps, "scale"> {
|
|
32
|
+
size?: RoundButtonSize;
|
|
33
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import clsx from "clsx";
|
|
2
2
|
import type {
|
|
3
|
+
ButtonFill,
|
|
3
4
|
ButtonIconSlot,
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
ButtonPriority,
|
|
6
|
+
ButtonScale,
|
|
6
7
|
ButtonSize,
|
|
7
8
|
ButtonState,
|
|
8
|
-
ButtonVariant,
|
|
9
9
|
} from "../types";
|
|
10
10
|
|
|
11
11
|
type ButtonClassNameOptions = {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
scale: ButtonScale;
|
|
13
|
+
fill: ButtonFill;
|
|
14
|
+
priority: ButtonPriority;
|
|
14
15
|
size: ButtonSize;
|
|
15
|
-
shape: ButtonShape;
|
|
16
16
|
block: boolean;
|
|
17
17
|
loading: boolean;
|
|
18
18
|
iconSlot: ButtonIconSlot;
|
|
@@ -24,13 +24,13 @@ type ButtonClassNameOptions = {
|
|
|
24
24
|
const BUTTON_CLASSNAME = "button";
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* 버튼 클래스 조합 helper:
|
|
27
|
+
* 버튼 클래스 조합 helper: scale/fill/priority/size 별 modifier를 한 곳에서 관리한다.
|
|
28
28
|
*/
|
|
29
29
|
const composeButtonClassName = ({
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
scale,
|
|
31
|
+
fill,
|
|
32
|
+
priority,
|
|
32
33
|
size,
|
|
33
|
-
shape,
|
|
34
34
|
block,
|
|
35
35
|
loading,
|
|
36
36
|
iconSlot,
|
|
@@ -40,16 +40,16 @@ const composeButtonClassName = ({
|
|
|
40
40
|
}: ButtonClassNameOptions) =>
|
|
41
41
|
clsx(
|
|
42
42
|
BUTTON_CLASSNAME,
|
|
43
|
-
`${BUTTON_CLASSNAME}
|
|
44
|
-
`${BUTTON_CLASSNAME}
|
|
45
|
-
`${BUTTON_CLASSNAME}
|
|
46
|
-
`${BUTTON_CLASSNAME}
|
|
43
|
+
`${BUTTON_CLASSNAME}-scale-${scale}`,
|
|
44
|
+
`${BUTTON_CLASSNAME}-fill-${fill}`,
|
|
45
|
+
`${BUTTON_CLASSNAME}-priority-${priority}`,
|
|
46
|
+
`${BUTTON_CLASSNAME}-size-${size}`,
|
|
47
47
|
{
|
|
48
|
-
[`${BUTTON_CLASSNAME}
|
|
49
|
-
[`${BUTTON_CLASSNAME}
|
|
50
|
-
[`${BUTTON_CLASSNAME}
|
|
51
|
-
[`${BUTTON_CLASSNAME}
|
|
52
|
-
[`${BUTTON_CLASSNAME}
|
|
48
|
+
[`${BUTTON_CLASSNAME}-state-${state}`]: state !== "default",
|
|
49
|
+
[`${BUTTON_CLASSNAME}-block`]: block,
|
|
50
|
+
[`${BUTTON_CLASSNAME}-loading`]: loading,
|
|
51
|
+
[`${BUTTON_CLASSNAME}-icon-${iconSlot}`]: iconSlot !== "none",
|
|
52
|
+
[`${BUTTON_CLASSNAME}-icon-only`]: iconOnly,
|
|
53
53
|
},
|
|
54
54
|
className,
|
|
55
55
|
);
|
|
@@ -19,7 +19,14 @@ const getIndicatorIcon = (size: CheckboxSize) =>
|
|
|
19
19
|
* 체크박스 컴포넌트; Radix Checkbox thin wrapper
|
|
20
20
|
* @component
|
|
21
21
|
* @param {CheckboxProps} props
|
|
22
|
-
* @param {
|
|
22
|
+
* @param {"medium" | "large"} [props.size="medium"] indicator/label spacing 크기.
|
|
23
|
+
* @param {boolean} [props.checked] 제어형 체크 상태.
|
|
24
|
+
* @param {boolean} [props.defaultChecked] 비제어 초기 체크 상태.
|
|
25
|
+
* @param {boolean} [props.disabled] disabled 상태.
|
|
26
|
+
* @param {(checked: CheckboxPrimitive.CheckedState) => void} [props.onCheckedChange]
|
|
27
|
+
* 체크 상태 변경 핸들러.
|
|
28
|
+
* @param {string} [props.className] root className.
|
|
29
|
+
* @param {string} [props.name] form name.
|
|
23
30
|
* @example
|
|
24
31
|
* <Checkbox size="medium" checked />
|
|
25
32
|
*/
|
|
@@ -51,7 +58,18 @@ export const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(
|
|
|
51
58
|
* 체크박스 필드 컴포넌트; label/helper 텍스트 래퍼
|
|
52
59
|
* @component
|
|
53
60
|
* @param {CheckboxFieldProps} props
|
|
54
|
-
* @param {
|
|
61
|
+
* @param {"medium" | "large"} [props.size="medium"] indicator 크기.
|
|
62
|
+
* @param {React.ReactNode} [props.label] `<label>` 텍스트/노드.
|
|
63
|
+
* @param {React.ReactNode} [props.helperText] helper 텍스트.
|
|
64
|
+
* @param {ComponentPropsWithoutRef<"label">} [props.labelProps] label attr.
|
|
65
|
+
* @param {ComponentPropsWithoutRef<"p">} [props.helperTextProps] helper attr.
|
|
66
|
+
* @param {string} [props.fieldClassName] `.checkbox-field` className.
|
|
67
|
+
* @param {string} [props.labelWrapperClassName] 라벨 wrapper className.
|
|
68
|
+
* @param {boolean} [props.checked] 제어형 체크 상태.
|
|
69
|
+
* @param {boolean} [props.defaultChecked] 비제어 초기 체크 상태.
|
|
70
|
+
* @param {(checked: CheckboxPrimitive.CheckedState) => void} [props.onCheckedChange]
|
|
71
|
+
* 체크 상태 변경 핸들러.
|
|
72
|
+
* @param {boolean} [props.disabled] disabled 상태.
|
|
55
73
|
* @example
|
|
56
74
|
* <CheckboxField label="약관 동의" helperText="필수" checked />
|
|
57
75
|
*/
|
|
@@ -1,16 +1,32 @@
|
|
|
1
1
|
import type { ComponentPropsWithoutRef, ReactNode } from "react";
|
|
2
2
|
import type * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* 지원하는 checkbox 사이즈. medium/large 두 단계.
|
|
6
|
+
*/
|
|
4
7
|
export type CheckboxSize = "medium" | "large";
|
|
5
8
|
|
|
6
9
|
export type CheckboxPrimitiveProps = ComponentPropsWithoutRef<
|
|
7
10
|
typeof CheckboxPrimitive.Root
|
|
8
11
|
>;
|
|
9
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Radix Checkbox Root에 size/className 확장을 더한 props.
|
|
15
|
+
* @property {"medium" | "large"} [size="medium"] indicator/box 크기.
|
|
16
|
+
*/
|
|
10
17
|
export interface CheckboxProps extends CheckboxPrimitiveProps {
|
|
11
18
|
size?: CheckboxSize;
|
|
12
19
|
}
|
|
13
20
|
|
|
21
|
+
/**
|
|
22
|
+
* label/helperText 등을 포함하는 CheckboxField 래퍼 props.
|
|
23
|
+
* @property {React.ReactNode} [label] `<label>`로 연결되는 텍스트/노드.
|
|
24
|
+
* @property {React.ReactNode} [helperText] label 하단 추가 설명.
|
|
25
|
+
* @property {ComponentPropsWithoutRef<"p">} [helperTextProps] helper container attr.
|
|
26
|
+
* @property {ComponentPropsWithoutRef<"label">} [labelProps] label attr.
|
|
27
|
+
* @property {string} [fieldClassName] `.checkbox-field` className override.
|
|
28
|
+
* @property {string} [labelWrapperClassName] label wrapper className.
|
|
29
|
+
*/
|
|
14
30
|
export interface CheckboxFieldProps extends CheckboxProps {
|
|
15
31
|
label?: ReactNode;
|
|
16
32
|
helperText?: ReactNode;
|
|
@@ -14,6 +14,14 @@ const isChipInputProps = (props: ChipProps): props is ChipInputProps =>
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Chip 종류별로 interactive/input 구조가 달라 별도 분기한다.
|
|
17
|
+
* @component
|
|
18
|
+
* @param {ChipProps} props
|
|
19
|
+
* @param {"filter" | "filter-rounded" | "assist" | "input"} [props.kind="filter"] chip kind.
|
|
20
|
+
* @param {boolean} [props.selected] 선택 상태. filter 계열에서 aria-pressed로 노출.
|
|
21
|
+
* @param {React.ReactNode} [props.leading] assist kind 전용 leading slot.
|
|
22
|
+
* @param {string} [props.removeButtonLabel="선택 항목 삭제"] input kind 제거 버튼 라벨.
|
|
23
|
+
* @param {(event: MouseEvent<HTMLButtonElement>) => void} [props.onRemove] input kind 제거 핸들러.
|
|
24
|
+
* @param {string} [props.className] root className.
|
|
17
25
|
*/
|
|
18
26
|
const Chip = forwardRef<HTMLElement, ChipProps>((props, ref) => {
|
|
19
27
|
if (isChipInputProps(props)) {
|
|
@@ -36,6 +36,9 @@ const useConfirmDialogInternalContext = () => {
|
|
|
36
36
|
* ConfirmDialogRoot; AlertDialog 루트
|
|
37
37
|
* @component
|
|
38
38
|
* @param {ConfirmDialogRootProps} props
|
|
39
|
+
* @param {boolean} [props.open] 제어형 open 상태.
|
|
40
|
+
* @param {boolean} [props.defaultOpen] 비제어 초기 open 상태.
|
|
41
|
+
* @param {(open: boolean) => void} [props.onOpenChange] open 변경 콜백.
|
|
39
42
|
*/
|
|
40
43
|
const ConfirmDialogRoot = ({
|
|
41
44
|
open: openProp,
|
|
@@ -80,6 +83,8 @@ const ConfirmDialogPortal = AlertDialogPrimitive.Portal;
|
|
|
80
83
|
* ConfirmDialogOverlay; 취소 성격의 바깥 dim
|
|
81
84
|
* @component
|
|
82
85
|
* @param {ConfirmDialogOverlayProps} props
|
|
86
|
+
* @param {string} [props.className] overlay className.
|
|
87
|
+
* @param {boolean} [props.disableOutsideClose=false] dim 클릭으로 닫힘 방지 여부.
|
|
83
88
|
*/
|
|
84
89
|
const ConfirmDialogOverlay = forwardRef<
|
|
85
90
|
HTMLDivElement,
|
|
@@ -120,6 +125,8 @@ ConfirmDialogOverlay.displayName = "ConfirmDialogOverlay";
|
|
|
120
125
|
* ConfirmDialogContent; AlertDialog 패널
|
|
121
126
|
* @component
|
|
122
127
|
* @param {ConfirmDialogContentProps} props
|
|
128
|
+
* @param {string} [props.className] content className.
|
|
129
|
+
* @param {React.ReactNode} [props.children] 패널 내용.
|
|
123
130
|
*/
|
|
124
131
|
const ConfirmDialogContent = forwardRef<
|
|
125
132
|
HTMLDivElement,
|
|
@@ -141,6 +148,9 @@ ConfirmDialogContent.displayName = "ConfirmDialogContent";
|
|
|
141
148
|
* ConfirmDialogTitle; AlertDialog 제목
|
|
142
149
|
* @component
|
|
143
150
|
* @param {ConfirmDialogTitleProps} props
|
|
151
|
+
* @param {string} [props.className] title className.
|
|
152
|
+
* @param {boolean} [props.visuallyHidden=false] 제목 시각적 숨김 여부.
|
|
153
|
+
* @param {React.ReactNode} [props.children] 제목 텍스트.
|
|
144
154
|
*/
|
|
145
155
|
const ConfirmDialogTitle = forwardRef<
|
|
146
156
|
HTMLHeadingElement,
|
|
@@ -170,6 +180,9 @@ ConfirmDialogTitle.displayName = "ConfirmDialogTitle";
|
|
|
170
180
|
* ConfirmDialogDescription; AlertDialog 설명
|
|
171
181
|
* @component
|
|
172
182
|
* @param {ConfirmDialogDescriptionProps} props
|
|
183
|
+
* @param {string} [props.className] description className.
|
|
184
|
+
* @param {boolean} [props.visuallyHidden=false] 설명 시각적 숨김 여부.
|
|
185
|
+
* @param {React.ReactNode} [props.children] 설명 텍스트.
|
|
173
186
|
*/
|
|
174
187
|
const ConfirmDialogDescription = forwardRef<
|
|
175
188
|
HTMLParagraphElement,
|
|
@@ -202,6 +215,8 @@ ConfirmDialogDescription.displayName = "ConfirmDialogDescription";
|
|
|
202
215
|
* ConfirmDialogHeader; 헤더 영역
|
|
203
216
|
* @component
|
|
204
217
|
* @param {ConfirmDialogSectionProps} props
|
|
218
|
+
* @param {string} [props.className] 섹션 className.
|
|
219
|
+
* @param {React.ReactNode} [props.children] 헤더 콘텐츠.
|
|
205
220
|
*/
|
|
206
221
|
const ConfirmDialogHeader = forwardRef<
|
|
207
222
|
HTMLDivElement,
|
|
@@ -221,6 +236,8 @@ ConfirmDialogHeader.displayName = "ConfirmDialogHeader";
|
|
|
221
236
|
* ConfirmDialogBody; 본문 영역
|
|
222
237
|
* @component
|
|
223
238
|
* @param {ConfirmDialogSectionProps} props
|
|
239
|
+
* @param {string} [props.className] 섹션 className.
|
|
240
|
+
* @param {React.ReactNode} [props.children] 본문 콘텐츠.
|
|
224
241
|
*/
|
|
225
242
|
const ConfirmDialogBody = forwardRef<HTMLDivElement, ConfirmDialogSectionProps>(
|
|
226
243
|
({ className, ...props }, forwardedRef) => (
|
|
@@ -239,6 +256,8 @@ ConfirmDialogBody.displayName = "ConfirmDialogBody";
|
|
|
239
256
|
* ConfirmDialogActions; 버튼 영역
|
|
240
257
|
* @component
|
|
241
258
|
* @param {ConfirmDialogSectionProps} props
|
|
259
|
+
* @param {string} [props.className] 섹션 className.
|
|
260
|
+
* @param {React.ReactNode} [props.children] 버튼 콘텐츠.
|
|
242
261
|
*/
|
|
243
262
|
const ConfirmDialogActions = forwardRef<
|
|
244
263
|
HTMLDivElement,
|
|
@@ -258,6 +277,8 @@ ConfirmDialogActions.displayName = "ConfirmDialogActions";
|
|
|
258
277
|
* ConfirmDialogCancelButton; AlertDialog Cancel wrapper
|
|
259
278
|
* @component
|
|
260
279
|
* @param {ConfirmDialogCancelProps} props
|
|
280
|
+
* @param {string} [props.className] button className.
|
|
281
|
+
* @param {boolean} [props.asChild=false] slot mode 사용 여부.
|
|
261
282
|
*/
|
|
262
283
|
const ConfirmDialogCancel = forwardRef<
|
|
263
284
|
HTMLButtonElement,
|
|
@@ -281,6 +302,8 @@ ConfirmDialogCancel.displayName = "ConfirmDialogCancel";
|
|
|
281
302
|
* ConfirmDialogActionButton; AlertDialog Action wrapper
|
|
282
303
|
* @component
|
|
283
304
|
* @param {ConfirmDialogActionProps} props
|
|
305
|
+
* @param {string} [props.className] button className.
|
|
306
|
+
* @param {boolean} [props.asChild=false] slot mode 사용 여부.
|
|
284
307
|
*/
|
|
285
308
|
const ConfirmDialogAction = forwardRef<
|
|
286
309
|
HTMLButtonElement,
|
|
@@ -14,6 +14,9 @@ import type {
|
|
|
14
14
|
* NoticeDialogRoot; 공통 Dialog 상태 제어 루트
|
|
15
15
|
* @component
|
|
16
16
|
* @param {NoticeDialogRootProps} props
|
|
17
|
+
* @param {boolean} [props.open] 제어형 open 상태.
|
|
18
|
+
* @param {boolean} [props.defaultOpen] 비제어 초기 open 상태.
|
|
19
|
+
* @param {(open: boolean) => void} [props.onOpenChange] open 변경 콜백.
|
|
17
20
|
*/
|
|
18
21
|
const NoticeDialogRoot = DialogPrimitive.Root;
|
|
19
22
|
const NoticeDialogTrigger = DialogPrimitive.Trigger;
|
|
@@ -24,6 +27,7 @@ const NoticeDialogClose = DialogPrimitive.Close;
|
|
|
24
27
|
* NoticeDialogOverlay; dim 영역
|
|
25
28
|
* @component
|
|
26
29
|
* @param {NoticeDialogOverlayProps} props
|
|
30
|
+
* @param {string} [props.className] overlay className.
|
|
27
31
|
*/
|
|
28
32
|
const NoticeDialogOverlay = forwardRef<
|
|
29
33
|
HTMLDivElement,
|
|
@@ -43,6 +47,8 @@ NoticeDialogOverlay.displayName = "NoticeDialogOverlay";
|
|
|
43
47
|
* NoticeDialogContent; 콘텐츠 패널
|
|
44
48
|
* @component
|
|
45
49
|
* @param {NoticeDialogContentProps} props
|
|
50
|
+
* @param {string} [props.className] content className.
|
|
51
|
+
* @param {React.ReactNode} [props.children] panel 내용.
|
|
46
52
|
*/
|
|
47
53
|
const NoticeDialogContent = forwardRef<
|
|
48
54
|
HTMLDivElement,
|
|
@@ -64,6 +70,9 @@ NoticeDialogContent.displayName = "NoticeDialogContent";
|
|
|
64
70
|
* NoticeDialogTitle; Dialog 제목
|
|
65
71
|
* @component
|
|
66
72
|
* @param {NoticeDialogTitleProps} props
|
|
73
|
+
* @param {string} [props.className] title className.
|
|
74
|
+
* @param {boolean} [props.visuallyHidden=false] 제목을 시각적으로 숨길지 여부.
|
|
75
|
+
* @param {React.ReactNode} [props.children] 제목 텍스트.
|
|
67
76
|
*/
|
|
68
77
|
const NoticeDialogTitle = forwardRef<
|
|
69
78
|
HTMLHeadingElement,
|
|
@@ -93,6 +102,9 @@ NoticeDialogTitle.displayName = "NoticeDialogTitle";
|
|
|
93
102
|
* NoticeDialogDescription; Dialog 설명
|
|
94
103
|
* @component
|
|
95
104
|
* @param {NoticeDialogDescriptionProps} props
|
|
105
|
+
* @param {string} [props.className] description className.
|
|
106
|
+
* @param {boolean} [props.visuallyHidden=false] 설명을 시각적으로 숨길지 여부.
|
|
107
|
+
* @param {React.ReactNode} [props.children] 설명 텍스트.
|
|
96
108
|
*/
|
|
97
109
|
const NoticeDialogDescription = forwardRef<
|
|
98
110
|
HTMLParagraphElement,
|
|
@@ -125,6 +137,8 @@ NoticeDialogDescription.displayName = "NoticeDialogDescription";
|
|
|
125
137
|
* NoticeDialogHeader; 헤더 레이아웃
|
|
126
138
|
* @component
|
|
127
139
|
* @param {NoticeDialogSectionProps} props
|
|
140
|
+
* @param {string} [props.className] 섹션 className.
|
|
141
|
+
* @param {React.HTMLAttributes<HTMLDivElement>["children"]} [props.children] 헤더 콘텐츠.
|
|
128
142
|
*/
|
|
129
143
|
const NoticeDialogHeader = forwardRef<HTMLDivElement, NoticeDialogSectionProps>(
|
|
130
144
|
({ className, ...props }, forwardedRef) => (
|
|
@@ -143,6 +157,8 @@ NoticeDialogHeader.displayName = "NoticeDialogHeader";
|
|
|
143
157
|
* NoticeDialogBody; 본문 영역
|
|
144
158
|
* @component
|
|
145
159
|
* @param {NoticeDialogSectionProps} props
|
|
160
|
+
* @param {string} [props.className] 섹션 className.
|
|
161
|
+
* @param {React.ReactNode} [props.children] 본문 콘텐츠.
|
|
146
162
|
*/
|
|
147
163
|
const NoticeDialogBody = forwardRef<HTMLDivElement, NoticeDialogSectionProps>(
|
|
148
164
|
({ className, ...props }, forwardedRef) => (
|
|
@@ -161,6 +177,8 @@ NoticeDialogBody.displayName = "NoticeDialogBody";
|
|
|
161
177
|
* NoticeDialogActions; 버튼 영역
|
|
162
178
|
* @component
|
|
163
179
|
* @param {NoticeDialogSectionProps} props
|
|
180
|
+
* @param {string} [props.className] 섹션 className.
|
|
181
|
+
* @param {React.ReactNode} [props.children] 버튼 콘텐츠.
|
|
164
182
|
*/
|
|
165
183
|
const NoticeDialogActions = forwardRef<
|
|
166
184
|
HTMLDivElement,
|