@uniai-fe/uds-primitives 0.3.18 → 0.3.19

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.
Files changed (65) hide show
  1. package/dist/styles.css +57 -27
  2. package/package.json +1 -1
  3. package/src/components/badge/markup/Badge.tsx +3 -5
  4. package/src/components/badge/styles/index.scss +2 -1
  5. package/src/components/button/index.tsx +7 -1
  6. package/src/components/button/markup/Base.tsx +5 -10
  7. package/src/components/button/markup/Label.tsx +23 -0
  8. package/src/components/button/markup/index.ts +1 -0
  9. package/src/components/button/types/index.ts +1 -0
  10. package/src/components/button/types/label.ts +9 -0
  11. package/src/components/checkbox/markup/Checkbox.tsx +9 -4
  12. package/src/components/checkbox/styles/index.scss +6 -4
  13. package/src/components/chip/index.tsx +1 -2
  14. package/src/components/chip/markup/Chip.tsx +36 -24
  15. package/src/components/chip/markup/DefaultStyle.tsx +34 -19
  16. package/src/components/chip/markup/InputStyle.tsx +17 -7
  17. package/src/components/chip/markup/Label.tsx +15 -0
  18. package/src/components/chip/markup/ListRoot.tsx +88 -0
  19. package/src/components/chip/markup/RemoveButton.tsx +4 -1
  20. package/src/components/chip/markup/index.tsx +13 -1
  21. package/src/components/chip/styles/chip.scss +43 -15
  22. package/src/components/chip/types/options.ts +22 -14
  23. package/src/components/chip/types/props-internal.ts +9 -5
  24. package/src/components/chip/types/props.ts +127 -46
  25. package/src/components/chip/utils/index.ts +1 -1
  26. package/src/components/form/markup/form-field/Header.tsx +3 -1
  27. package/src/components/input/markup/file/UploadedChip.tsx +5 -5
  28. package/src/components/input/types/file.ts +1 -1
  29. package/src/components/radio/markup/Radio.tsx +9 -4
  30. package/src/components/radio/styles/index.scss +6 -4
  31. package/src/components/segmented-control/markup/Label.tsx +22 -0
  32. package/src/components/segmented-control/markup/List.tsx +2 -3
  33. package/src/components/segmented-control/markup/index.ts +1 -0
  34. package/src/components/segmented-control/styles/index.scss +4 -4
  35. package/src/components/segmented-control/types/index.ts +9 -0
  36. package/src/components/select/markup/foundation/Base.tsx +3 -8
  37. package/src/components/select/markup/foundation/Selected.tsx +3 -2
  38. package/src/components/slot/index.tsx +2 -6
  39. package/src/components/slot/markup/Text.tsx +34 -0
  40. package/src/components/slot/markup/index.tsx +7 -0
  41. package/src/components/slot/types/index.ts +2 -0
  42. package/src/components/slot/types/text.ts +24 -0
  43. package/src/components/table/markup/foundation/Cell.tsx +4 -12
  44. package/src/components/table/markup/foundation/Td.tsx +4 -7
  45. package/src/components/table/markup/foundation/Text.tsx +16 -0
  46. package/src/components/table/markup/foundation/Th.tsx +4 -7
  47. package/src/components/table/markup/foundation/index.tsx +2 -0
  48. package/src/components/table/types/foundation.ts +9 -0
  49. package/src/components/tooltip/markup/Message.tsx +3 -1
  50. package/src/components/tooltip/markup/Text.tsx +21 -0
  51. package/src/components/tooltip/markup/index.tsx +3 -0
  52. package/src/components/tooltip/types/index.ts +1 -0
  53. package/src/components/tooltip/types/text.ts +9 -0
  54. package/src/index.scss +0 -1
  55. package/src/index.tsx +0 -1
  56. package/src/components/chip/utils/class-name.ts +0 -36
  57. package/src/components/label/hooks/index.ts +0 -4
  58. package/src/components/label/img/.gitkeep +0 -0
  59. package/src/components/label/index.scss +0 -1
  60. package/src/components/label/index.tsx +0 -4
  61. package/src/components/label/markup/index.tsx +0 -4
  62. package/src/components/label/styles/index.scss +0 -0
  63. package/src/components/label/types/index.ts +0 -4
  64. package/src/components/label/utils/index.ts +0 -4
  65. /package/src/components/slot/markup/{Component.tsx → Base.tsx} +0 -0
package/dist/styles.css CHANGED
@@ -7,7 +7,7 @@
7
7
  --theme-badge-radius: var(--theme-radius-medium-1, 6px);
8
8
  --theme-badge-font-family: var(--font-caption-medium-family, inherit);
9
9
  --theme-badge-font-size: var(--font-caption-medium-size, 11px);
10
- --theme-badge-font-weight: var(--font-caption-medium-weight, 400);
10
+ --theme-badge-font-weight: 400;
11
11
  --theme-badge-line-height: var(--font-caption-medium-line-height, 1.5);
12
12
  --theme-badge-letter-spacing: var(--font-caption-medium-letter-spacing, 0);
13
13
  --theme-badge-dot-size: var(--spacing-gap-3, 8px);
@@ -188,6 +188,7 @@
188
188
  --theme-checkbox-surface-selected-disabled: rgba(26, 106, 255, 0.28);
189
189
  --theme-checkbox-label-color: var(--color-label-strong);
190
190
  --theme-checkbox-label-disabled: var(--color-label-disabled);
191
+ --theme-checkbox-label-font-weight: 400;
191
192
  --theme-checkbox-helper-color: var(--color-label-neutral);
192
193
  --theme-checkbox-helper-disabled: var(--color-label-disabled);
193
194
  --theme-checkbox-icon-default: transparent;
@@ -439,6 +440,7 @@
439
440
  --theme-radio-disabled-selected-fill: var(--color-primary-default);
440
441
  --theme-radio-label-color: var(--color-label-strong);
441
442
  --theme-radio-label-disabled: var(--color-label-disabled);
443
+ --theme-radio-label-font-weight: 400;
442
444
  --theme-radio-helper-color: var(--color-label-neutral);
443
445
  --theme-radio-helper-disabled: var(--color-label-disabled);
444
446
  --theme-radio-card-background: var(--color-common-100);
@@ -1723,17 +1725,17 @@
1723
1725
  cursor: not-allowed;
1724
1726
  }
1725
1727
 
1726
- .checkbox-label-text {
1727
- font-weight: var(--font-body-medium-weight);
1728
+ .checkbox-label {
1729
+ font-weight: var(--theme-checkbox-label-font-weight);
1728
1730
  user-select: none;
1729
1731
  }
1730
1732
 
1731
- .checkbox-field[data-size=medium] .checkbox-label-text {
1733
+ .checkbox-field[data-size=medium] .checkbox-label {
1732
1734
  font-size: var(--font-body-xsmall-size);
1733
1735
  line-height: var(--font-body-xsmall-line-height);
1734
1736
  }
1735
1737
 
1736
- .checkbox-field[data-size=large] .checkbox-label-text {
1738
+ .checkbox-field[data-size=large] .checkbox-label {
1737
1739
  font-size: var(--font-body-medium-size);
1738
1740
  line-height: var(--font-body-medium-line-height);
1739
1741
  }
@@ -1754,6 +1756,7 @@
1754
1756
 
1755
1757
 
1756
1758
  .chip {
1759
+ --chip-current-height: var(--theme-chip-height);
1757
1760
  --chip-gap: var(--theme-chip-gap);
1758
1761
  --chip-bg: transparent;
1759
1762
  --chip-border-color: transparent;
@@ -1762,7 +1765,7 @@
1762
1765
  align-items: center;
1763
1766
  justify-content: center;
1764
1767
  gap: var(--chip-gap);
1765
- height: var(--theme-chip-height);
1768
+ height: var(--chip-current-height);
1766
1769
  padding-left: var(--theme-chip-padding-horizontal);
1767
1770
  padding-right: var(--theme-chip-padding-horizontal);
1768
1771
  padding-block: 0;
@@ -1796,35 +1799,47 @@ figure.chip {
1796
1799
  outline-offset: 2px;
1797
1800
  }
1798
1801
 
1799
- .chip:where([data-kind=filter]),
1800
- .chip:where([data-kind=filter-rounded]) {
1802
+ .chip:where([data-style=filter][data-fill=solid]) {
1801
1803
  --chip-bg: var(--color-surface-standard);
1802
1804
  --chip-label-color: var(--color-label-neutral);
1803
1805
  --chip-border-color: transparent;
1804
1806
  }
1805
1807
 
1806
- .chip:where([data-kind=filter][data-selected=true]),
1807
- .chip:where([data-kind=filter-rounded][data-selected=true]) {
1808
+ .chip:where([data-style=filter][data-fill=outlined]) {
1809
+ --chip-bg: var(--color-common-100);
1810
+ --chip-label-color: var(--color-label-neutral);
1811
+ --chip-border-color: var(--color-border-standard-cool-gray);
1812
+ }
1813
+
1814
+ .chip:where([data-style=filter][data-selected=true]) {
1808
1815
  --chip-bg: var(--color-surface-heavy);
1809
1816
  --chip-label-color: var(--color-common-100);
1817
+ --chip-border-color: transparent;
1810
1818
  }
1811
1819
 
1812
- .chip:where([data-kind=filter-rounded]) {
1813
- border-radius: var(--theme-chip-rounded-radius);
1820
+ .chip:where([data-style][data-rounded=true]) {
1821
+ border-radius: calc(var(--chip-current-height) / 2);
1814
1822
  }
1815
1823
 
1816
- .chip:where([data-kind=assist]) {
1824
+ .chip:where([data-style=assist][data-fill=solid]) {
1817
1825
  --chip-bg: var(--color-surface-static-neutral);
1818
1826
  --chip-label-color: var(--color-label-strong);
1819
1827
  --chip-gap: var(--theme-chip-assist-gap);
1820
1828
  --chip-border-color: transparent;
1821
1829
  }
1822
1830
 
1823
- .chip:where([data-kind=assist][data-selected=true]) {
1831
+ .chip:where([data-style=assist][data-fill=outlined]) {
1832
+ --chip-bg: var(--color-common-100);
1833
+ --chip-label-color: var(--color-label-strong);
1834
+ --chip-gap: var(--theme-chip-assist-gap);
1835
+ --chip-border-color: var(--color-border-standard-cool-gray);
1836
+ }
1837
+
1838
+ .chip:where([data-style=assist][data-selected=true]) {
1824
1839
  --chip-label-color: var(--color-primary-default);
1825
1840
  }
1826
1841
 
1827
- .chip:where([data-kind=input]) {
1842
+ .chip:where([data-style=input]) {
1828
1843
  --chip-gap: var(--theme-chip-input-gap);
1829
1844
  --chip-bg: var(--color-common-100);
1830
1845
  --chip-label-color: var(--color-label-standard);
@@ -1833,12 +1848,13 @@ figure.chip {
1833
1848
  padding-right: var(--theme-chip-input-padding-right);
1834
1849
  }
1835
1850
 
1836
- .chip:where([data-kind=input][data-removable=false]) {
1851
+ .chip:where([data-style=input][data-removable=false]) {
1837
1852
  padding-left: var(--theme-chip-padding-horizontal);
1838
1853
  padding-right: var(--theme-chip-padding-horizontal);
1839
1854
  }
1840
1855
 
1841
1856
  .chip:where([data-size=table]) {
1857
+ --chip-current-height: var(--theme-chip-height-table);
1842
1858
  height: var(--theme-chip-height-table);
1843
1859
  padding-left: var(--theme-chip-padding-horizontal-table);
1844
1860
  padding-right: var(--theme-chip-padding-horizontal-table);
@@ -1854,22 +1870,22 @@ figure.chip {
1854
1870
  line-height: var(--theme-chip-line-height-table);
1855
1871
  }
1856
1872
 
1857
- .chip:where([data-size=table][data-kind=input]) {
1873
+ .chip:where([data-size=table][data-style=input]) {
1858
1874
  padding-left: var(--theme-chip-padding-left-table);
1859
1875
  padding-right: var(--theme-chip-padding-right-table);
1860
1876
  }
1861
1877
 
1862
- .chip:where([data-size=table][data-kind=input][data-removable=false]) {
1878
+ .chip:where([data-size=table][data-style=input][data-removable=false]) {
1863
1879
  padding-left: var(--theme-chip-padding-horizontal-table);
1864
1880
  padding-right: var(--theme-chip-padding-horizontal-table);
1865
1881
  }
1866
1882
 
1867
- .chip:where([data-size=table][data-kind=input]) .chip-remove-button {
1883
+ .chip:where([data-size=table][data-style=input]) .chip-remove-button {
1868
1884
  width: fit-content;
1869
1885
  height: fit-content;
1870
1886
  }
1871
1887
 
1872
- .chip:where([data-kind=input][data-selected=true]) {
1888
+ .chip:where([data-style=input][data-selected=true]) {
1873
1889
  --chip-border-color: var(--color-border-standard-blue);
1874
1890
  }
1875
1891
 
@@ -1916,6 +1932,20 @@ figure.chip {
1916
1932
  height: 100%;
1917
1933
  }
1918
1934
 
1935
+ .chip-list {
1936
+ display: flex;
1937
+ flex-wrap: wrap;
1938
+ align-items: center;
1939
+ gap: var(--spacing-gap-2);
1940
+ margin: 0;
1941
+ padding: 0;
1942
+ list-style: none;
1943
+ }
1944
+
1945
+ .chip-list-item {
1946
+ display: flex;
1947
+ }
1948
+
1919
1949
  /* Divider 토큰도 전역 :root 범위에 선언한다. */
1920
1950
 
1921
1951
 
@@ -3396,17 +3426,17 @@ figure.chip {
3396
3426
  cursor: not-allowed;
3397
3427
  }
3398
3428
 
3399
- .radio-label-text {
3400
- font-weight: var(--font-body-medium-weight);
3429
+ .radio-label {
3430
+ font-weight: var(--theme-radio-label-font-weight);
3401
3431
  user-select: none;
3402
3432
  }
3403
3433
 
3404
- .radio-field[data-size=medium] .radio-label-text {
3434
+ .radio-field[data-size=medium] .radio-label {
3405
3435
  font-size: var(--font-body-xsmall-size);
3406
3436
  line-height: var(--font-body-xsmall-line-height);
3407
3437
  }
3408
3438
 
3409
- .radio-field[data-size=large] .radio-label-text {
3439
+ .radio-field[data-size=large] .radio-label {
3410
3440
  font-size: var(--font-body-medium-size);
3411
3441
  line-height: var(--font-body-medium-line-height);
3412
3442
  }
@@ -3537,7 +3567,7 @@ figure.chip {
3537
3567
  --segmented-item-padding-x: 22px;
3538
3568
  --segmented-item-padding-y: 4px;
3539
3569
  --segmented-item-font-size: var(--font-heading-xxsmall-size, 15px);
3540
- --segmented-item-font-weight: var(--font-heading-xxsmall-weight, 500);
3570
+ --segmented-item-font-weight: 500;
3541
3571
  --segmented-item-line-height: var(--font-heading-xxsmall-line-height, 1.5);
3542
3572
  position: relative;
3543
3573
  display: block;
@@ -3618,7 +3648,7 @@ figure.chip {
3618
3648
  outline-offset: 2px;
3619
3649
  }
3620
3650
 
3621
- .segmented-control-button-label {
3651
+ .segmented-control-label {
3622
3652
  display: flex;
3623
3653
  align-items: center;
3624
3654
  justify-content: center;
@@ -3630,7 +3660,7 @@ figure.chip {
3630
3660
  transition: color 0.2s ease;
3631
3661
  }
3632
3662
 
3633
- .segmented-control-button:where([data-state=on]) .segmented-control-button-label {
3663
+ .segmented-control-button:where([data-state=on]) .segmented-control-label {
3634
3664
  color: var(--segmented-label-active-color);
3635
3665
  }
3636
3666
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniai-fe/uds-primitives",
3
- "version": "0.3.18",
3
+ "version": "0.3.19",
4
4
  "description": "UNIAI Design System; Primitives Components Package",
5
5
  "type": "module",
6
6
  "private": false,
@@ -1,6 +1,7 @@
1
1
  import { forwardRef } from "react";
2
2
  import type { BadgeProps } from "../types";
3
3
  import { composeBadgeClassName } from "../utils";
4
+ import { Slot } from "../../slot";
4
5
 
5
6
  /**
6
7
  * Badge 컴포넌트; size/style/intent 축을 data attribute로 노출한다.
@@ -50,11 +51,8 @@ const Badge = forwardRef<HTMLElementTagNameMap["figure"], BadgeProps>(
50
51
  data-has-label={hasLabel ? "true" : undefined}
51
52
  >
52
53
  {renderDot}
53
- {["string", "number"].includes(typeof children) ? (
54
- <span className="badge-label">{children}</span>
55
- ) : (
56
- children
57
- )}
54
+ {/* 변경: badge 라벨 텍스트 래핑 규칙을 Slot.Text로 통일한다. */}
55
+ <Slot.Text className="badge-label">{children}</Slot.Text>
58
56
  </figure>
59
57
  );
60
58
  },
@@ -6,7 +6,8 @@
6
6
  --theme-badge-radius: var(--theme-radius-medium-1, 6px);
7
7
  --theme-badge-font-family: var(--font-caption-medium-family, inherit);
8
8
  --theme-badge-font-size: var(--font-caption-medium-size, 11px);
9
- --theme-badge-font-weight: var(--font-caption-medium-weight, 400);
9
+ // 변경: Badge label font-weight 디자인 규칙에 맞춰 400으로 고정한다.
10
+ --theme-badge-font-weight: 400;
10
11
  --theme-badge-line-height: var(--font-caption-medium-line-height, 1.5);
11
12
  --theme-badge-letter-spacing: var(--font-caption-medium-letter-spacing, 0);
12
13
  --theme-badge-dot-size: var(--spacing-gap-3, 8px);
@@ -3,12 +3,18 @@
3
3
  */
4
4
  import "./index.scss";
5
5
 
6
- import { ButtonDefault, ButtonText, ButtonRounded } from "./markup";
6
+ import {
7
+ ButtonDefault,
8
+ ButtonText,
9
+ ButtonRounded,
10
+ ButtonLabel,
11
+ } from "./markup";
7
12
 
8
13
  export const Button = {
9
14
  Default: ButtonDefault,
10
15
  Text: ButtonText,
11
16
  Rounded: ButtonRounded,
17
+ Label: ButtonLabel,
12
18
  };
13
19
 
14
20
  export * from "./hooks";
@@ -3,7 +3,8 @@
3
3
  import clsx from "clsx";
4
4
  import { forwardRef } from "react";
5
5
  import type { ButtonProps } from "../types";
6
- import { SlotComponent } from "../../slot";
6
+ import { Slot } from "../../slot";
7
+ import ButtonLabel from "./Label";
7
8
  import {
8
9
  getFormFieldWidthAttr,
9
10
  getFormFieldWidthValue,
@@ -85,7 +86,7 @@ const ButtonDefault = forwardRef<HTMLElement, ButtonProps>(
85
86
  : style;
86
87
 
87
88
  return (
88
- <SlotComponent
89
+ <Slot.Base
89
90
  className={clsx(
90
91
  "button",
91
92
  `button-fill-${fill}`,
@@ -112,19 +113,13 @@ const ButtonDefault = forwardRef<HTMLElement, ButtonProps>(
112
113
  {left}
113
114
  </span>
114
115
  )}
115
- {typeof children === "string" || typeof children === "number" ? (
116
- <span className="button-label" data-slot="label">
117
- {children}
118
- </span>
119
- ) : (
120
- children
121
- )}
116
+ <ButtonLabel data-slot="label">{children}</ButtonLabel>
122
117
  {right && (
123
118
  <span className="button-right" data-slot="right">
124
119
  {right}
125
120
  </span>
126
121
  )}
127
- </SlotComponent>
122
+ </Slot.Base>
128
123
  );
129
124
  },
130
125
  );
@@ -0,0 +1,23 @@
1
+ import clsx from "clsx";
2
+ import { Slot } from "../../slot";
3
+ import type { ButtonLabelProps } from "../types/label";
4
+
5
+ /**
6
+ * ButtonLabel; Button namespace에서 재사용 가능한 label 래퍼.
7
+ * @component
8
+ * @param {ButtonLabelProps} props
9
+ * @param {React.ElementType} [props.as="span"] 렌더링할 요소.
10
+ * @param {React.ReactNode} [props.children] 문자열/숫자는 button-label span으로 렌더하고, 그 외 ReactNode는 그대로 반환한다.
11
+ * @param {string} [props.className] button-label과 병합할 className.
12
+ * @example
13
+ * <Button.Label>확인</Button.Label>
14
+ */
15
+ export default function ButtonLabel({
16
+ className,
17
+ ...restProps
18
+ }: ButtonLabelProps) {
19
+ // Button 전용 라벨 클래스는 namespace 컴포넌트에서 고정 주입한다.
20
+ return (
21
+ <Slot.Text className={clsx("button-label", className)} {...restProps} />
22
+ );
23
+ }
@@ -1,3 +1,4 @@
1
1
  export { ButtonDefault } from "./Base";
2
2
  export { ButtonText } from "./Text";
3
3
  export { ButtonRounded } from "./Rounded";
4
+ export { default as ButtonLabel } from "./Label";
@@ -2,4 +2,5 @@
2
2
  * Button Types; barrel export 전용 파일
3
3
  */
4
4
  export type * from "./props";
5
+ export type * from "./label";
5
6
  export * from "./options";
@@ -0,0 +1,9 @@
1
+ import type { SlotTextProps } from "../../slot";
2
+
3
+ /**
4
+ * ButtonLabelProps; Button 전용 label 래퍼 props.
5
+ * @property {React.ElementType} [as] 렌더링할 요소. 기본값은 span.
6
+ * @property {React.ReactNode} [children] 문자열/숫자는 래핑하고, 그 외 ReactNode는 그대로 반환한다.
7
+ * @property {string} [className] 기본 button-label 클래스와 병합할 className.
8
+ */
9
+ export type ButtonLabelProps = SlotTextProps;
@@ -4,13 +4,14 @@ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
4
4
  import type { CheckboxFieldProps, CheckboxProps, CheckboxSize } from "../types";
5
5
  import CheckLargeIcon from "../img/check-large.svg";
6
6
  import CheckMediumIcon from "../img/check-medium.svg";
7
+ import { Slot } from "../../slot";
7
8
 
8
9
  const CHECKBOX_CLASSNAME = "checkbox";
9
10
  const CHECKBOX_SURFACE_CLASSNAME = "checkbox-surface";
10
11
  const CHECKBOX_INDICATOR_CLASSNAME = "checkbox-indicator";
11
12
  const CHECKBOX_FIELD_CLASSNAME = "checkbox-field";
12
13
  const CHECKBOX_LABEL_WRAPPER_CLASSNAME = "checkbox-label-wrapper";
13
- const CHECKBOX_LABEL_TEXT_CLASSNAME = "checkbox-label-text";
14
+ const CHECKBOX_LABEL_CLASSNAME = "checkbox-label";
14
15
  const CHECKBOX_HELPER_CLASSNAME = "checkbox-helper";
15
16
 
16
17
  const getIndicatorIcon = (size: CheckboxSize) =>
@@ -95,7 +96,10 @@ const CheckboxField = forwardRef<HTMLButtonElement, CheckboxFieldProps>(
95
96
  ) {
96
97
  const generatedId = useId();
97
98
  const checkboxId = id ?? generatedId;
98
- const labelId = label ? `${checkboxId}-label` : undefined;
99
+ const labelId =
100
+ label && ["string", "number"].includes(typeof label)
101
+ ? `${checkboxId}-label`
102
+ : undefined;
99
103
  const helperId = helperText ? `${checkboxId}-helper` : undefined;
100
104
  // Label/helper는 Root 외부에서 htmlFor/aria 연결을 유지한다.
101
105
 
@@ -126,9 +130,10 @@ const CheckboxField = forwardRef<HTMLButtonElement, CheckboxFieldProps>(
126
130
  ref={ref}
127
131
  />
128
132
  {label ? (
129
- <span id={labelId} className={CHECKBOX_LABEL_TEXT_CLASSNAME}>
133
+ // 변경: label 렌더는 Slot.Text 단일 경로로 통일하고, aria-labelledby는 텍스트일 때만 연결한다.
134
+ <Slot.Text id={labelId} className={CHECKBOX_LABEL_CLASSNAME}>
130
135
  {label}
131
- </span>
136
+ </Slot.Text>
132
137
  ) : null}
133
138
  </label>
134
139
  {helperText ? (
@@ -15,6 +15,8 @@
15
15
  --theme-checkbox-surface-selected-disabled: rgba(26, 106, 255, 0.28);
16
16
  --theme-checkbox-label-color: var(--color-label-strong);
17
17
  --theme-checkbox-label-disabled: var(--color-label-disabled);
18
+ // 변경: Checkbox label font-weight는 디자인 규칙에 맞춰 400으로 고정한다.
19
+ --theme-checkbox-label-font-weight: 400;
18
20
  --theme-checkbox-helper-color: var(--color-label-neutral);
19
21
  --theme-checkbox-helper-disabled: var(--color-label-disabled);
20
22
  --theme-checkbox-icon-default: transparent;
@@ -148,17 +150,17 @@
148
150
  cursor: not-allowed;
149
151
  }
150
152
 
151
- .checkbox-label-text {
152
- font-weight: var(--font-body-medium-weight);
153
+ .checkbox-label {
154
+ font-weight: var(--theme-checkbox-label-font-weight);
153
155
  user-select: none;
154
156
  }
155
157
 
156
- .checkbox-field[data-size="medium"] .checkbox-label-text {
158
+ .checkbox-field[data-size="medium"] .checkbox-label {
157
159
  font-size: var(--font-body-xsmall-size);
158
160
  line-height: var(--font-body-xsmall-line-height);
159
161
  }
160
162
 
161
- .checkbox-field[data-size="large"] .checkbox-label-text {
163
+ .checkbox-field[data-size="large"] .checkbox-label {
162
164
  font-size: var(--font-body-medium-size);
163
165
  line-height: var(--font-body-medium-line-height);
164
166
  }
@@ -1,9 +1,8 @@
1
1
  /**
2
- * chips 카테고리 배럴 placeholder: 실제 구현은 markup/ 하위에 추가한다.
2
+ * chips 카테고리 배럴
3
3
  */
4
4
  import "./index.scss";
5
5
 
6
6
  export * from "./markup";
7
7
  export * from "./hooks";
8
8
  export type * from "./types";
9
- export * from "./utils";
@@ -1,48 +1,55 @@
1
1
  import { forwardRef, type Ref } from "react";
2
+ import clsx from "clsx";
2
3
  import type { ChipInputProps, ChipProps } from "../types";
3
- import ChipDefaultStyle from "./DefaultStyle";
4
+ import ChipClickableStyle from "./DefaultStyle";
4
5
  import ChipInputStyle from "./InputStyle";
5
6
 
6
- // kind === "input" 조합에서 props를 ChipInputProps로 좁히기 위한 type guard.
7
+ // chipStyle === "input" 조합에서 props를 ChipInputProps로 좁히기 위한 type guard.
7
8
  const isChipInputProps = (props: ChipProps): props is ChipInputProps =>
8
- props.kind === "input";
9
+ props.chipStyle === "input";
9
10
 
10
11
  /**
11
- * Chip Markup; Kind별 렌더 분기 Orchestrator 컴포넌트
12
+ * Chip Markup; Style별 렌더 분기 Orchestrator 컴포넌트
12
13
  * @component
13
14
  * @param {ChipProps} props Chip 공통/종류별 props
14
- * @param {"filter" | "filter-rounded" | "assist" | "input"} [props.kind="filter"] Chip 종류
15
+ * @param {"filter" | "assist" | "input"} [props.chipStyle="filter"] Chip 스타일
16
+ * @param {"solid" | "outlined"} [props.fill="solid"] Chip 채움 스타일
17
+ * @param {boolean} [props.rounded=false] pill radius 적용 여부
15
18
  * @param {React.ReactNode} [props.children] Chip 라벨/콘텐츠
16
- * @param {boolean} [props.selected] 선택 상태; filter 계열에서 `aria-pressed`로 반영
17
- * @param {React.ReactNode} [props.leading] assist kind 좌측 slot
19
+ * @param {boolean} [props.selected] 선택 상태; filter 스타일에서 `aria-pressed`로 반영
20
+ * @param {React.ReactNode} [props.leading] assist 스타일 좌측 slot
18
21
  * @param {"default" | "table"} [props.size="default"] 사이즈 축
19
- * @param {string} [props.removeButtonLabel="선택 항목 삭제"] input kind remove 버튼 라벨
20
- * @param {boolean} [props.disabled] input kind 비활성화 여부
21
- * @param {(event: MouseEvent<HTMLButtonElement>) => void} [props.onRemove] input kind remove 핸들러
22
- * @param {(event: MouseEvent<HTMLButtonElement>) => void} [props.onClick] interactive kind click 핸들러
23
- * @param {"button" | "submit" | "reset"} [props.type] interactive kind button type
22
+ * @param {string} [props.removeButtonLabel="선택 항목 삭제"] input 스타일 remove 버튼 라벨
23
+ * @param {boolean} [props.disabled] input 스타일 비활성화 여부
24
+ * @param {(event: MouseEvent<HTMLButtonElement>) => void} [props.onRemove] input 스타일 remove 핸들러
25
+ * @param {(event: MouseEvent<HTMLButtonElement>) => void} [props.onClick] interactive 스타일 click 핸들러
26
+ * @param {"button" | "submit" | "reset"} [props.type] interactive 스타일 button type
24
27
  * @param {string} [props.className] root className
25
28
  * @param {string} [props.id] root id
26
29
  * @param {string} [props.title] root title
27
30
  * @description
28
- * - `kind="input"`이면 `<figure>`를 렌더하고, 나머지 kind는 `<button>`을 렌더한다.
29
- * - `kind="input"`일 때 remove 버튼 클릭 이벤트는 root click으로 버블링되지 않도록 내부에서 차단한다.
30
- * - native HTML attrs는 kind에 맞는 root 요소로 그대로 전달된다.
31
- * @returns {JSX.Element} kind에 맞는 Chip root 요소
31
+ * - `chipStyle="input"`이면 `<figure>`를 렌더하고, 나머지 스타일은 `<button>`을 렌더한다.
32
+ * - `chipStyle="input"`일 때 remove 버튼 클릭 이벤트는 root click으로 버블링되지 않도록 내부에서 차단한다.
33
+ * - native HTML attrs는 style에 맞는 root 요소로 그대로 전달된다.
34
+ * @returns {JSX.Element} style에 맞는 Chip root 요소
32
35
  * @example
33
- * <Chip kind="filter" selected>
36
+ * <ChipDefault chipStyle="filter" fill="solid" selected rounded>
34
37
  * 전체
35
- * </Chip>
38
+ * </ChipDefault>
36
39
  * @example
37
- * <Chip kind="input" onRemove={event => console.log(event.type)}>
40
+ * <ChipDefault chipStyle="input" onRemove={event => console.log(event.type)}>
38
41
  * 첨부파일.pdf
39
- * </Chip>
42
+ * </ChipDefault>
40
43
  */
41
- const Chip = forwardRef<HTMLElement, ChipProps>((props, ref) => {
44
+ const ChipDefault = forwardRef<HTMLElement, ChipProps>((props, ref) => {
45
+ const mergedClassName = clsx("chip-default", props.className);
46
+
42
47
  if (isChipInputProps(props)) {
43
48
  return (
44
49
  <ChipInputStyle
45
50
  {...props}
51
+ // 변경: 역할 className을 루트 컴포넌트에서 누적 전달한다.
52
+ className={mergedClassName}
46
53
  // 변경: 하위 스타일 컴포넌트가 forwardRef를 사용하므로 ref를 직접 전달한다.
47
54
  ref={ref as Ref<HTMLElementTagNameMap["figure"]>}
48
55
  />
@@ -50,11 +57,16 @@ const Chip = forwardRef<HTMLElement, ChipProps>((props, ref) => {
50
57
  }
51
58
 
52
59
  return (
60
+ // 변경: 역할 className을 루트 컴포넌트에서 누적 전달한다.
53
61
  // 변경: interactive 경로도 forwardRef 기반 ref 전달로 통일한다.
54
- <ChipDefaultStyle {...props} ref={ref as Ref<HTMLButtonElement>} />
62
+ <ChipClickableStyle
63
+ {...props}
64
+ className={mergedClassName}
65
+ ref={ref as Ref<HTMLButtonElement>}
66
+ />
55
67
  );
56
68
  });
57
69
 
58
- Chip.displayName = "Chip";
70
+ ChipDefault.displayName = "Chip.Default";
59
71
 
60
- export { Chip };
72
+ export { ChipDefault };