sparkle-design 0.9.0

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 (125) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +5 -0
  3. package/README.en.md +275 -0
  4. package/README.md +328 -0
  5. package/dist/components/ui/badge/index.d.ts +67 -0
  6. package/dist/components/ui/badge/index.figma.d.ts +1 -0
  7. package/dist/components/ui/badge/index.figma.js +28 -0
  8. package/dist/components/ui/badge/index.js +129 -0
  9. package/dist/components/ui/breadcrumb/index.d.ts +70 -0
  10. package/dist/components/ui/breadcrumb/index.figma.d.ts +1 -0
  11. package/dist/components/ui/breadcrumb/index.figma.js +28 -0
  12. package/dist/components/ui/breadcrumb/index.js +96 -0
  13. package/dist/components/ui/button/index.d.ts +145 -0
  14. package/dist/components/ui/button/index.figma.d.ts +1 -0
  15. package/dist/components/ui/button/index.figma.js +59 -0
  16. package/dist/components/ui/button/index.js +375 -0
  17. package/dist/components/ui/card/index.d.ts +193 -0
  18. package/dist/components/ui/card/index.figma.d.ts +1 -0
  19. package/dist/components/ui/card/index.figma.js +28 -0
  20. package/dist/components/ui/card/index.js +219 -0
  21. package/dist/components/ui/checkbox/index.d.ts +62 -0
  22. package/dist/components/ui/checkbox/index.figma.d.ts +1 -0
  23. package/dist/components/ui/checkbox/index.figma.js +34 -0
  24. package/dist/components/ui/checkbox/index.js +192 -0
  25. package/dist/components/ui/dialog/index.d.ts +106 -0
  26. package/dist/components/ui/dialog/index.figma.d.ts +1 -0
  27. package/dist/components/ui/dialog/index.figma.js +21 -0
  28. package/dist/components/ui/dialog/index.js +157 -0
  29. package/dist/components/ui/divider/index.d.ts +44 -0
  30. package/dist/components/ui/divider/index.figma.d.ts +1 -0
  31. package/dist/components/ui/divider/index.figma.js +39 -0
  32. package/dist/components/ui/divider/index.js +81 -0
  33. package/dist/components/ui/form/index.d.ts +171 -0
  34. package/dist/components/ui/form/index.figma.d.ts +1 -0
  35. package/dist/components/ui/form/index.figma.js +129 -0
  36. package/dist/components/ui/form/index.js +214 -0
  37. package/dist/components/ui/form/label.d.ts +4 -0
  38. package/dist/components/ui/form/label.js +20 -0
  39. package/dist/components/ui/icon/index.d.ts +71 -0
  40. package/dist/components/ui/icon/index.figma.d.ts +1 -0
  41. package/dist/components/ui/icon/index.figma.js +1858 -0
  42. package/dist/components/ui/icon/index.js +57 -0
  43. package/dist/components/ui/icon-button/index.d.ts +77 -0
  44. package/dist/components/ui/icon-button/index.figma.d.ts +1 -0
  45. package/dist/components/ui/icon-button/index.figma.js +43 -0
  46. package/dist/components/ui/icon-button/index.js +341 -0
  47. package/dist/components/ui/inline-message/index.d.ts +83 -0
  48. package/dist/components/ui/inline-message/index.figma.d.ts +1 -0
  49. package/dist/components/ui/inline-message/index.figma.js +26 -0
  50. package/dist/components/ui/inline-message/index.js +154 -0
  51. package/dist/components/ui/input/index.d.ts +118 -0
  52. package/dist/components/ui/input/index.figma.d.ts +1 -0
  53. package/dist/components/ui/input/index.figma.js +36 -0
  54. package/dist/components/ui/input/index.js +256 -0
  55. package/dist/components/ui/input-password/index.d.ts +27 -0
  56. package/dist/components/ui/input-password/index.figma.d.ts +1 -0
  57. package/dist/components/ui/input-password/index.figma.js +36 -0
  58. package/dist/components/ui/input-password/index.js +35 -0
  59. package/dist/components/ui/link/index.d.ts +68 -0
  60. package/dist/components/ui/link/index.figma.d.ts +1 -0
  61. package/dist/components/ui/link/index.figma.js +22 -0
  62. package/dist/components/ui/link/index.js +92 -0
  63. package/dist/components/ui/modal/index.d.ts +83 -0
  64. package/dist/components/ui/modal/index.figma.d.ts +1 -0
  65. package/dist/components/ui/modal/index.figma.js +61 -0
  66. package/dist/components/ui/modal/index.js +143 -0
  67. package/dist/components/ui/overlay/index.d.ts +19 -0
  68. package/dist/components/ui/overlay/index.figma.d.ts +1 -0
  69. package/dist/components/ui/overlay/index.figma.js +14 -0
  70. package/dist/components/ui/overlay/index.js +39 -0
  71. package/dist/components/ui/radio/index.d.ts +94 -0
  72. package/dist/components/ui/radio/index.figma.d.ts +1 -0
  73. package/dist/components/ui/radio/index.figma.js +63 -0
  74. package/dist/components/ui/radio/index.js +204 -0
  75. package/dist/components/ui/select/index.d.ts +175 -0
  76. package/dist/components/ui/select/index.figma.d.ts +1 -0
  77. package/dist/components/ui/select/index.figma.js +30 -0
  78. package/dist/components/ui/select/index.js +281 -0
  79. package/dist/components/ui/skeleton/index.d.ts +21 -0
  80. package/dist/components/ui/skeleton/index.figma.d.ts +1 -0
  81. package/dist/components/ui/skeleton/index.figma.js +14 -0
  82. package/dist/components/ui/skeleton/index.js +32 -0
  83. package/dist/components/ui/slider/index.d.ts +75 -0
  84. package/dist/components/ui/slider/index.figma.d.ts +1 -0
  85. package/dist/components/ui/slider/index.figma.js +28 -0
  86. package/dist/components/ui/slider/index.js +113 -0
  87. package/dist/components/ui/slider/utils.d.ts +16 -0
  88. package/dist/components/ui/slider/utils.js +56 -0
  89. package/dist/components/ui/spinner/index.d.ts +42 -0
  90. package/dist/components/ui/spinner/index.figma.d.ts +1 -0
  91. package/dist/components/ui/spinner/index.figma.js +16 -0
  92. package/dist/components/ui/spinner/index.js +51 -0
  93. package/dist/components/ui/switch/index.d.ts +46 -0
  94. package/dist/components/ui/switch/index.figma.d.ts +1 -0
  95. package/dist/components/ui/switch/index.figma.js +27 -0
  96. package/dist/components/ui/switch/index.js +75 -0
  97. package/dist/components/ui/tabs/index.d.ts +53 -0
  98. package/dist/components/ui/tabs/index.figma.d.ts +1 -0
  99. package/dist/components/ui/tabs/index.figma.js +55 -0
  100. package/dist/components/ui/tabs/index.js +164 -0
  101. package/dist/components/ui/tag/index.d.ts +50 -0
  102. package/dist/components/ui/tag/index.figma.d.ts +1 -0
  103. package/dist/components/ui/tag/index.figma.js +32 -0
  104. package/dist/components/ui/tag/index.js +177 -0
  105. package/dist/components/ui/textarea/index.d.ts +49 -0
  106. package/dist/components/ui/textarea/index.figma.d.ts +1 -0
  107. package/dist/components/ui/textarea/index.figma.js +27 -0
  108. package/dist/components/ui/textarea/index.js +94 -0
  109. package/dist/components/ui/toast/index.d.ts +60 -0
  110. package/dist/components/ui/toast/index.figma.d.ts +1 -0
  111. package/dist/components/ui/toast/index.figma.js +26 -0
  112. package/dist/components/ui/toast/index.js +57 -0
  113. package/dist/components/ui/tooltip/index.d.ts +52 -0
  114. package/dist/components/ui/tooltip/index.figma.d.ts +1 -0
  115. package/dist/components/ui/tooltip/index.figma.js +23 -0
  116. package/dist/components/ui/tooltip/index.js +65 -0
  117. package/dist/index.d.ts +27 -0
  118. package/dist/index.js +27 -0
  119. package/dist/lib/utils.d.ts +2 -0
  120. package/dist/lib/utils.js +5 -0
  121. package/dist/test/helpers.d.ts +56 -0
  122. package/dist/test/helpers.js +182 -0
  123. package/dist/test/setup.d.ts +1 -0
  124. package/dist/test/setup.js +38 -0
  125. package/package.json +253 -0
@@ -0,0 +1,57 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ /**
14
+ * Copyright 2026 Goodpatch Inc.
15
+ * SPDX-License-Identifier: Apache-2.0
16
+ */
17
+ import * as React from "react";
18
+ import { cn } from "../../../lib/utils.js";
19
+ /**
20
+ * **概要 / Overview**
21
+ *
22
+ * - アイコンはテキスト情報を視覚表現でユーザーに提示するために使用するコンポーネントです。
23
+ * - en: The Icon component is used to present textual information to users through visual representation.
24
+ *
25
+ * **アンチパターン / Anti-patterns**
26
+ *
27
+ * - `material-symbols-rounded` を `span` に直書きせず、`Icon` を使ってください。
28
+ * en: Use `Icon` instead of writing `material-symbols-rounded` directly on a span.
29
+ *
30
+ * ```tsx
31
+ * // ✅ Correct
32
+ * <Icon icon="content_copy" size={4} />
33
+ *
34
+ * // ❌ Wrong - className を直書きしない
35
+ * <span className="material-symbols-rounded text-sm">content_copy</span>
36
+ * ```
37
+
38
+ * **使用例 / Usage Example**
39
+ *
40
+ * ```tsx
41
+ * <Icon icon="check" size={6} fill={true} />
42
+ * ```
43
+ *
44
+ * @param {IconProps} props
45
+ */
46
+ export const Icon = React.forwardRef((_a, ref) => {
47
+ var { className, icon, size = 3, fill = false } = _a, props = __rest(_a, ["className", "icon", "size", "fill"]);
48
+ // 既存のclassNameにicon-X-fill-0の形式が含まれているかチェック
49
+ const hasIconTypographyClass = className === null || className === void 0 ? void 0 : className.match(/icon-\d+-fill-\d+/);
50
+ // サイズクラスの生成(既存のサイズクラスがない場合のみ)
51
+ const fillValue = fill ? 1 : 0;
52
+ const iconTypographyClass = hasIconTypographyClass
53
+ ? ""
54
+ : `icon-${size}-fill-${fillValue}`;
55
+ return (_jsx("span", Object.assign({ ref: ref, className: cn(iconTypographyClass, "select-none", className), "aria-hidden": "true" }, props, { children: icon })));
56
+ });
57
+ Icon.displayName = "Icon";
@@ -0,0 +1,77 @@
1
+ import * as React from "react";
2
+ import { type VariantProps } from "class-variance-authority";
3
+ declare const iconButtonVariants: (props?: ({
4
+ variant?: "solid" | "outline" | "ghost" | null | undefined;
5
+ size?: "xs" | "sm" | "md" | "lg" | null | undefined;
6
+ theme?: "primary" | "neutral" | "negative" | null | undefined;
7
+ isLoading?: boolean | null | undefined;
8
+ isDisabled?: boolean | null | undefined;
9
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
10
+ type IconButtonVariants = VariantProps<typeof iconButtonVariants>;
11
+ export interface IconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
12
+ /**
13
+ * アイコンボタンのバリエーション
14
+ * en: Variation of the icon button
15
+ */
16
+ variant?: IconButtonVariants["variant"];
17
+ /**
18
+ * アイコンボタンのサイズ
19
+ * en: Size of the icon button
20
+ */
21
+ size?: IconButtonVariants["size"];
22
+ /**
23
+ * アイコンボタンのテーマ
24
+ * en: Theme of the icon button
25
+ */
26
+ theme?: IconButtonVariants["theme"];
27
+ /**
28
+ * ボタンを別コンポーネントの子としてレンダリングするか
29
+ * en: Whether to render the button as a child component
30
+ */
31
+ asChild?: boolean;
32
+ /**
33
+ * 表示するアイコン名
34
+ * en: Icon name to display
35
+ */
36
+ icon: string;
37
+ /**
38
+ * ローディング状態かどうか
39
+ * en: Whether the button is in a loading state
40
+ */
41
+ isLoading?: boolean;
42
+ /**
43
+ * ボタンを無効化するかどうか
44
+ * en: Whether the button is disabled
45
+ */
46
+ isDisabled?: boolean;
47
+ }
48
+ /**
49
+ * **概要 / Overview**
50
+ *
51
+ * - アイコンボタンはフォームの送信、ダイアログの展開、アクションのキャンセル、削除の実行など、アクションやイベントのトリガーとして使用するコンポーネントです。
52
+ * - en: The IconButton component is used as a trigger for actions and events such as form submission, dialog expansion, action cancellation, and deletion execution.
53
+ *
54
+ * **使用例 / Usage Example**
55
+ *
56
+ * ```tsx
57
+ * <IconButton variant="solid" size="md" theme="primary" icon="edit" />
58
+ * ```
59
+ *
60
+ * **アンチパターン / Anti-patterns**
61
+ *
62
+ * - アイコンだけのアクションでは `Button` + `prefixIcon` ではなく `IconButton` を使ってください。
63
+ * en: Use `IconButton` for icon-only actions instead of `Button` with `prefixIcon`.
64
+ *
65
+ * ```tsx
66
+ * // ✅ Correct
67
+ * <IconButton icon="content_copy" aria-label="コピー" />
68
+ *
69
+ * // ❌ Wrong - Icon-only action を Button で表現しない
70
+ * <Button prefixIcon="content_copy" aria-label="コピー" />
71
+ * ```
72
+ *
73
+
74
+ * @param {IconButtonProps} props
75
+ */
76
+ declare const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<HTMLButtonElement>>;
77
+ export { IconButton, iconButtonVariants };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import figma from "@figma/code-connect";
3
+ import { IconButton } from "./index.js";
4
+ /**
5
+ * -- This file was auto-generated by Code Connect --
6
+ * `props` includes a mapping from your code props to Figma properties.
7
+ * You should check this is correct, and update the `example` function
8
+ * to return the code example you'd like to see in Figma
9
+ */
10
+ figma.connect(IconButton, "https://www.figma.com/design/7alBZXZf65YgcII41TWT0r/Sparkle-Design?node-id=25%3A906", {
11
+ props: {
12
+ // These props were automatically mapped based on your linked code:
13
+ isLoading: figma.enum("state", {
14
+ loading: true,
15
+ }),
16
+ isDisabled: figma.enum("state", {
17
+ disabled: true,
18
+ }),
19
+ disabled: figma.enum("state", {
20
+ disabled: true,
21
+ }),
22
+ variant: figma.enum("variant", {
23
+ solid: "solid",
24
+ outline: "outline",
25
+ ghost: "ghost",
26
+ }),
27
+ size: figma.enum("size", {
28
+ xs: "xs",
29
+ sm: "sm",
30
+ md: "md",
31
+ lg: "lg",
32
+ }),
33
+ theme: figma.enum("theme", {
34
+ primary: "primary",
35
+ negative: "negative",
36
+ neutral: "neutral",
37
+ }),
38
+ // No matching props could be found for these Figma properties:
39
+ icon: figma.instance("icon").getProps(),
40
+ // "isFocused": figma.boolean('isFocused')
41
+ },
42
+ example: props => (_jsx(IconButton, { icon: props.icon.icon, isLoading: props.isLoading, isDisabled: props.isDisabled, disabled: props.disabled, variant: props.variant, size: props.size, theme: props.theme })),
43
+ });
@@ -0,0 +1,341 @@
1
+ /**
2
+ * Copyright 2026 Goodpatch Inc.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ "use client";
6
+ var __rest = (this && this.__rest) || function (s, e) {
7
+ var t = {};
8
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
9
+ t[p] = s[p];
10
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
11
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
12
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
13
+ t[p[i]] = s[p[i]];
14
+ }
15
+ return t;
16
+ };
17
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
18
+ import * as React from "react";
19
+ import { Slot as SlotPrimitive } from "radix-ui";
20
+ import { cva } from "class-variance-authority";
21
+ import { cn } from "../../../lib/utils.js";
22
+ import { Icon } from "../../../components/ui/icon/index.js";
23
+ import { Spinner } from "../../../components/ui/spinner/index.js";
24
+ const iconButtonVariants = cva([
25
+ "inline-flex items-center justify-center whitespace-nowrap rounded-action",
26
+ "ring-offset-background transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-[var(--color-ring-normal)] focus-visible:ring-offset-2",
27
+ "relative cursor-pointer",
28
+ ].join(" "), {
29
+ variants: {
30
+ variant: {
31
+ solid: "border",
32
+ outline: "border",
33
+ ghost: "",
34
+ },
35
+ size: {
36
+ xs: "w-6 h-6 p-1",
37
+ sm: "w-8 h-8 p-1.5",
38
+ md: "w-10 h-10 p-2",
39
+ lg: "w-12 h-12 p-2",
40
+ },
41
+ theme: {
42
+ primary: "",
43
+ neutral: "",
44
+ negative: "",
45
+ },
46
+ isLoading: {
47
+ true: "cursor-not-allowed",
48
+ false: "",
49
+ },
50
+ isDisabled: {
51
+ true: "cursor-not-allowed",
52
+ false: "",
53
+ },
54
+ },
55
+ compoundVariants: [
56
+ // Solid Primary バリアント
57
+ {
58
+ variant: "solid",
59
+ theme: "primary",
60
+ isLoading: false,
61
+ isDisabled: false,
62
+ className: [
63
+ "bg-primary-500 text-white border-primary-600",
64
+ "hover:bg-primary-600 hover:border-primary-700",
65
+ "active:bg-primary-700 active:border-primary-800",
66
+ ].join(" "),
67
+ },
68
+ {
69
+ variant: "solid",
70
+ theme: "primary",
71
+ isLoading: true,
72
+ isDisabled: false,
73
+ className: "bg-primary-500 text-white border-primary-600",
74
+ },
75
+ // Solid Neutral バリアント
76
+ {
77
+ variant: "solid",
78
+ theme: "neutral",
79
+ isLoading: false,
80
+ isDisabled: false,
81
+ className: [
82
+ "bg-[var(--color-black-alpha-600)] text-white border-neutral-600",
83
+ "hover:bg-[var(--color-black-alpha-700)] hover:border-neutral-700",
84
+ "active:bg-[var(--color-black-alpha-800)] active:border-neutral-800",
85
+ ].join(" "),
86
+ },
87
+ {
88
+ variant: "solid",
89
+ theme: "neutral",
90
+ isLoading: true,
91
+ isDisabled: false,
92
+ className: "bg-[var(--color-black-alpha-600)] text-white border-neutral-600",
93
+ },
94
+ // Solid Negative バリアント
95
+ {
96
+ variant: "solid",
97
+ theme: "negative",
98
+ isLoading: false,
99
+ isDisabled: false,
100
+ className: [
101
+ "bg-negative-500 text-white border-negative-600",
102
+ "hover:bg-negative-600 hover:border-negative-700",
103
+ "active:bg-negative-700 active:border-negative-800",
104
+ ].join(" "),
105
+ },
106
+ {
107
+ variant: "solid",
108
+ theme: "negative",
109
+ isLoading: true,
110
+ isDisabled: false,
111
+ className: "bg-negative-500 text-white border-negative-600",
112
+ },
113
+ // Outline Primary バリアント
114
+ {
115
+ variant: "outline",
116
+ theme: "primary",
117
+ isLoading: false,
118
+ className: [
119
+ "bg-white text-primary-500 border-primary-300",
120
+ "hover:bg-primary-50",
121
+ "active:bg-primary-100 active:border-primary-400 active:text-primary-600",
122
+ ].join(" "),
123
+ },
124
+ {
125
+ variant: "outline",
126
+ theme: "primary",
127
+ isLoading: true,
128
+ isDisabled: false,
129
+ className: "bg-white text-primary-500 border-primary-300",
130
+ },
131
+ // Outline Neutral バリアント
132
+ {
133
+ variant: "outline",
134
+ theme: "neutral",
135
+ isLoading: false,
136
+ className: [
137
+ "bg-white text-neutral-700 border-neutral-300",
138
+ "hover:bg-[var(--color-black-alpha-50)]",
139
+ "active:bg-[var(--color-black-alpha-100)]",
140
+ ].join(" "),
141
+ },
142
+ {
143
+ variant: "outline",
144
+ theme: "neutral",
145
+ isLoading: true,
146
+ isDisabled: false,
147
+ className: "bg-white text-neutral-700 border-neutral-300",
148
+ },
149
+ // Outline Negative バリアント
150
+ {
151
+ variant: "outline",
152
+ theme: "negative",
153
+ isLoading: false,
154
+ isDisabled: false,
155
+ className: [
156
+ "bg-white text-negative-500 border-negative-300",
157
+ "hover:bg-negative-50",
158
+ "active:bg-negative-100 active:border-negative-400 active:text-negative-600",
159
+ ].join(" "),
160
+ },
161
+ {
162
+ variant: "outline",
163
+ theme: "negative",
164
+ isLoading: true,
165
+ isDisabled: false,
166
+ className: "bg-white text-negative-500 border-negative-300",
167
+ },
168
+ // Ghost Primary バリアント
169
+ {
170
+ variant: "ghost",
171
+ theme: "primary",
172
+ isLoading: false,
173
+ isDisabled: false,
174
+ className: "text-primary-500 hover:bg-primary-50 active:bg-primary-100 active:text-primary-600",
175
+ },
176
+ {
177
+ variant: "ghost",
178
+ theme: "primary",
179
+ isLoading: true,
180
+ isDisabled: false,
181
+ className: "text-primary-500",
182
+ },
183
+ // Ghost neutral バリアント
184
+ {
185
+ variant: "ghost",
186
+ theme: "neutral",
187
+ isLoading: false,
188
+ isDisabled: false,
189
+ className: "text-neutral-700 hover:bg-[var(--color-black-alpha-50)] active:bg-[var(--color-black-alpha-100)]",
190
+ },
191
+ {
192
+ variant: "ghost",
193
+ theme: "neutral",
194
+ isLoading: true,
195
+ isDisabled: false,
196
+ className: "text-neutral-700",
197
+ },
198
+ // Ghost Negative バリアント
199
+ {
200
+ variant: "ghost",
201
+ theme: "negative",
202
+ isLoading: false,
203
+ isDisabled: false,
204
+ className: "text-negative-500 hover:bg-negative-50 active:bg-negative-100 active:text-negative-600",
205
+ },
206
+ {
207
+ variant: "ghost",
208
+ theme: "negative",
209
+ isLoading: true,
210
+ isDisabled: false,
211
+ className: "text-negative-500",
212
+ },
213
+ // Disabled styles for all variants
214
+ {
215
+ variant: "solid",
216
+ theme: "primary",
217
+ isDisabled: true,
218
+ className: "disabled:bg-primary-200 disabled:text-white disabled:border-none",
219
+ },
220
+ {
221
+ variant: "solid",
222
+ theme: "neutral",
223
+ isDisabled: true,
224
+ className: "disabled:bg-[var(--color-black-alpha-200)] disabled:text-white disabled:border-none",
225
+ },
226
+ {
227
+ variant: "solid",
228
+ theme: "negative",
229
+ isDisabled: true,
230
+ className: "disabled:bg-negative-200 disabled:text-white disabled:border-none",
231
+ },
232
+ {
233
+ variant: "outline",
234
+ theme: "primary",
235
+ isDisabled: true,
236
+ className: "disabled:bg-[var(--color-white-alpha-700)] disabled:text-primary-200 disabled:border-primary-100",
237
+ },
238
+ {
239
+ variant: "outline",
240
+ theme: "neutral",
241
+ isDisabled: true,
242
+ className: "disabled:bg-[var(--color-white-alpha-700)] disabled:text-neutral-200 disabled:border-neutral-100",
243
+ },
244
+ {
245
+ variant: "outline",
246
+ theme: "negative",
247
+ isDisabled: true,
248
+ className: "disabled:bg-[var(--color-white-alpha-700)] disabled:text-negative-200 disabled:border-negative-100",
249
+ },
250
+ {
251
+ variant: "ghost",
252
+ theme: "primary",
253
+ isDisabled: true,
254
+ className: "disabled:bg-[var(--color-white-alpha-700)] disabled:text-primary-200",
255
+ },
256
+ {
257
+ variant: "ghost",
258
+ theme: "neutral",
259
+ isDisabled: true,
260
+ className: "disabled:bg-[var(--color-white-alpha-700)] disabled:text-neutral-200",
261
+ },
262
+ {
263
+ variant: "ghost",
264
+ theme: "negative",
265
+ isDisabled: true,
266
+ className: "disabled:bg-[var(--color-white-alpha-700)] disabled:text-negative-200",
267
+ },
268
+ ],
269
+ defaultVariants: {
270
+ variant: "solid",
271
+ size: "md",
272
+ theme: "primary",
273
+ isLoading: false,
274
+ isDisabled: false,
275
+ },
276
+ });
277
+ /**
278
+ * **概要 / Overview**
279
+ *
280
+ * - アイコンボタンはフォームの送信、ダイアログの展開、アクションのキャンセル、削除の実行など、アクションやイベントのトリガーとして使用するコンポーネントです。
281
+ * - en: The IconButton component is used as a trigger for actions and events such as form submission, dialog expansion, action cancellation, and deletion execution.
282
+ *
283
+ * **使用例 / Usage Example**
284
+ *
285
+ * ```tsx
286
+ * <IconButton variant="solid" size="md" theme="primary" icon="edit" />
287
+ * ```
288
+ *
289
+ * **アンチパターン / Anti-patterns**
290
+ *
291
+ * - アイコンだけのアクションでは `Button` + `prefixIcon` ではなく `IconButton` を使ってください。
292
+ * en: Use `IconButton` for icon-only actions instead of `Button` with `prefixIcon`.
293
+ *
294
+ * ```tsx
295
+ * // ✅ Correct
296
+ * <IconButton icon="content_copy" aria-label="コピー" />
297
+ *
298
+ * // ❌ Wrong - Icon-only action を Button で表現しない
299
+ * <Button prefixIcon="content_copy" aria-label="コピー" />
300
+ * ```
301
+ *
302
+
303
+ * @param {IconButtonProps} props
304
+ */
305
+ const IconButton = React.forwardRef((_a, ref) => {
306
+ var { className, variant, size, theme, isLoading = false, isDisabled = false, asChild = false, disabled, icon, children } = _a, props = __rest(_a, ["className", "variant", "size", "theme", "isLoading", "isDisabled", "asChild", "disabled", "icon", "children"]);
307
+ // disabled状態の管理(isDisabled、disabled、またはisLoadingがtrueの場合)
308
+ const isIconButtonDisabled = isLoading || isDisabled || disabled;
309
+ // アイコンのみのボタンには aria-label が必要(WCAG 1.1.1)
310
+ // en: Icon-only buttons require aria-label (WCAG 1.1.1)
311
+ if (process.env.NODE_ENV !== "production") {
312
+ if (!asChild && !props["aria-label"] && !props["aria-labelledby"]) {
313
+ console.warn("[IconButton] アイコンのみのボタンには aria-label を指定してください(WCAG 1.1.1)。" +
314
+ " / Icon-only buttons require aria-label (WCAG 1.1.1).");
315
+ }
316
+ }
317
+ const Comp = asChild ? SlotPrimitive.Slot : "button";
318
+ // アイコンのサイズをボタンサイズに合わせて設定
319
+ const getIconSize = () => {
320
+ switch (size) {
321
+ case "xs":
322
+ return 3;
323
+ case "sm":
324
+ return 5;
325
+ case "lg":
326
+ return 7;
327
+ default:
328
+ return 6;
329
+ }
330
+ };
331
+ return (_jsx(Comp, Object.assign({ type: "button", className: cn(iconButtonVariants({
332
+ variant,
333
+ size,
334
+ theme,
335
+ isLoading,
336
+ isDisabled,
337
+ className,
338
+ })), ref: ref, disabled: isIconButtonDisabled }, props, { children: isLoading ? (_jsx(_Fragment, { children: _jsx(Spinner, { size: getIconSize(), className: "text-current" }) })) : (_jsx(Icon, { icon: icon, size: getIconSize() })) })));
339
+ });
340
+ IconButton.displayName = "IconButton";
341
+ export { IconButton, iconButtonVariants };
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Copyright 2026 Goodpatch Inc.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import * as React from "react";
6
+ import { type VariantProps } from "class-variance-authority";
7
+ declare const inlineMessageVariants: (props?: ({
8
+ status?: "negative" | "info" | "success" | "warning" | null | undefined;
9
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
10
+ type InlineMessageVariant = VariantProps<typeof inlineMessageVariants>;
11
+ export interface InlineMessageProps extends React.HTMLAttributes<HTMLDivElement>, InlineMessageVariant {
12
+ /**
13
+ * メッセージのステータス
14
+ * en: Status of the message
15
+ */
16
+ status: InlineMessageVariant["status"];
17
+ /**
18
+ * 閉じる時のハンドラー
19
+ * en: Handler when the message is dismissed
20
+ */
21
+ onClose?: () => void;
22
+ /**
23
+ * 閉じるボタンを表示するかどうか(デフォルト: true)
24
+ * en: Whether to show close button (default: true)
25
+ */
26
+ isCloseTrigger?: boolean;
27
+ /**
28
+ * 子要素
29
+ * en: Child nodes
30
+ */
31
+ children?: React.ReactNode;
32
+ }
33
+ /**
34
+ * **概要 / Overview**
35
+ *
36
+ * - インラインメッセージはユーザーにシステムやサービスの状態を伝えるために使用するコンポーネントです。
37
+ * - en: The InlineMessage component is used to convey system or service status to users.
38
+ *
39
+ * **使用例 / Usage Example**
40
+ *
41
+ * ```tsx
42
+ * <InlineMessage status="info" onClose={() => console.log('closed')}>
43
+ * <InlineMessageTitle>情報</InlineMessageTitle>
44
+ * <InlineMessageDescription>
45
+ * これは情報メッセージです。
46
+ * </InlineMessageDescription>
47
+ * </InlineMessage>
48
+ * ```
49
+ *
50
+ * @param {InlineMessageProps} props
51
+ */
52
+ declare const InlineMessage: React.ForwardRefExoticComponent<InlineMessageProps & React.RefAttributes<HTMLDivElement>>;
53
+ /**
54
+ * **概要 / Overview**
55
+ *
56
+ * - インラインメッセージのタイトルコンポーネントです。
57
+ * - en: Title component for inline messages.
58
+ *
59
+ * **使用例 / Usage Example**
60
+ *
61
+ * ```tsx
62
+ * <InlineMessageTitle>タイトル</InlineMessageTitle>
63
+ * ```
64
+ *
65
+ * @param {React.HTMLAttributes<HTMLSpanElement>} props
66
+ */
67
+ declare const InlineMessageTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & React.RefAttributes<HTMLSpanElement>>;
68
+ /**
69
+ * **概要 / Overview**
70
+ *
71
+ * - インラインメッセージの説明文コンポーネントです。
72
+ * - en: Description component for inline messages.
73
+ *
74
+ * **使用例 / Usage Example**
75
+ *
76
+ * ```tsx
77
+ * <InlineMessageDescription>詳細な説明文</InlineMessageDescription>
78
+ * ```
79
+ *
80
+ * @param {React.HTMLAttributes<HTMLParagraphElement>} props
81
+ */
82
+ declare const InlineMessageDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
83
+ export { InlineMessage, InlineMessageTitle, InlineMessageDescription };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import figma from "@figma/code-connect";
3
+ import { InlineMessage, InlineMessageDescription, InlineMessageTitle, } from "./index.js";
4
+ /**
5
+ * -- This file was auto-generated by Code Connect --
6
+ * `props` includes a mapping from your code props to Figma properties.
7
+ * You should check this is correct, and update the `example` function
8
+ * to return the code example you'd like to see in Figma
9
+ */
10
+ figma.connect(InlineMessage, "https://www.figma.com/design/7alBZXZf65YgcII41TWT0r/Sparkle-Design?node-id=1266%3A14202", {
11
+ props: {
12
+ title: figma.boolean("isTitle", {
13
+ true: figma.string("title"),
14
+ false: undefined,
15
+ }),
16
+ description: figma.string("description"),
17
+ isCloseTrigger: figma.boolean("isCloseTrigger"),
18
+ status: figma.enum("status", {
19
+ info: "info",
20
+ warning: "warning",
21
+ negative: "negative",
22
+ success: "success",
23
+ }),
24
+ },
25
+ example: props => (_jsxs(InlineMessage, { isCloseTrigger: props.isCloseTrigger, status: props.status, children: [_jsx(InlineMessageTitle, { children: props.title }), _jsx(InlineMessageDescription, { children: props.description })] })),
26
+ });