sparkle-design 2.0.0-beta.0 → 2.0.0-beta.1
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.en.md +19 -0
- package/README.md +19 -0
- package/dist/components/ui/badge/index.d.ts +1 -1
- package/dist/components/ui/badge/index.js +10 -4
- package/dist/components/ui/button/index.js +5 -5
- package/dist/components/ui/checkbox/index.js +17 -15
- package/dist/components/ui/dialog/index.js +4 -3
- package/dist/components/ui/form/index.js +1 -1
- package/dist/components/ui/icon/index.d.ts +14 -13
- package/dist/components/ui/icon/index.js +2 -2
- package/dist/components/ui/icon-button/index.js +3 -3
- package/dist/components/ui/inline-message/index.js +1 -1
- package/dist/components/ui/input/index.js +8 -4
- package/dist/components/ui/link/index.js +7 -5
- package/dist/components/ui/modal/index.js +3 -2
- package/dist/components/ui/radio/index.js +16 -14
- package/dist/components/ui/select/index.js +10 -8
- package/dist/components/ui/slider/index.js +2 -2
- package/dist/components/ui/spinner/index.d.ts +6 -6
- package/dist/components/ui/spinner/index.js +4 -4
- package/dist/components/ui/tabs/index.js +3 -3
- package/dist/components/ui/tag/index.d.ts +3 -1
- package/dist/components/ui/tag/index.js +20 -12
- package/dist/components/ui/textarea/index.d.ts +1 -1
- package/dist/components/ui/textarea/index.js +4 -5
- package/dist/components/ui/toast/index.js +1 -1
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -24,6 +24,25 @@ It implements [Goodpatch](https://goodpatch.com/)'s "Sparkle Design" system on t
|
|
|
24
24
|
- 🎨 **Customizability** ... A dedicated CLI tool lets you apply the same customizations found in the Figma files. This makes it easy to spin up code for design systems built on Sparkle Design.
|
|
25
25
|
- 🤖 **AI Friendly** ... Ships with skills and guard configurations for Claude Code, Cursor, and Codex. Maintain design system quality even during AI-assisted coding.
|
|
26
26
|
|
|
27
|
+
## Versions, React and CLI support
|
|
28
|
+
|
|
29
|
+
| Version | React | sparkle-design-cli | Status |
|
|
30
|
+
|---|---|---|---|
|
|
31
|
+
| **2.x** | 19+ | Latest (currently beta: `npx --yes sparkle-design-cli@beta`) | Current. New features and components land here only (currently in beta: `npm install sparkle-design@beta`) |
|
|
32
|
+
| **1.x** | 18 (19 also works) | Latest (`npx --yes sparkle-design-cli`) | **Deprecated maintenance line.** Only bug and security fixes, plus token/style updates needed to stay compatible with the latest CLI |
|
|
33
|
+
|
|
34
|
+
2.x receives `ref` as a regular prop (the React 19 approach) in every component, so on React 18 refs and Radix `asChild` compositions (e.g. Tooltip / Dialog triggers) don't work correctly. Use 1.x for React 18 projects (npm refuses to install 2.x into a React 18 project because of the peer dependency conflict).
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install sparkle-design@1
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Both lines use the latest CLI without pinning. When the tokens generated by the CLI change, 1.x follows, so 1.x looks the same as 2.x (only React 19-specific changes and new features stay out of 1.x).
|
|
41
|
+
|
|
42
|
+
Even if you stay on 1.x, run `migrate` to check your app's legacy token classes when the tokens generated by the CLI change.
|
|
43
|
+
|
|
44
|
+
To move from 1.x to 2.x, upgrade your project to React 19 first. `npx --yes sparkle-design-cli@beta migrate` reports how to replace legacy tokens (e.g. `text-neutral-900`) with the new ones (dry run by default; `--write` rewrites files).
|
|
45
|
+
|
|
27
46
|
## Quick Start
|
|
28
47
|
|
|
29
48
|
### 1. Set up
|
package/README.md
CHANGED
|
@@ -24,6 +24,25 @@ shadcn/ui をベースに、[グッドパッチ](https://goodpatch.com/)のデ
|
|
|
24
24
|
- 🎨 **カスタマイズ性** ... 専用CLIツールを利用し、Figmaファイルと同等のカスタマイズを適用することが出来ます。これによりSparkle Designをベースとしたデザインシステムのコードを素早く用意することが出来ます。
|
|
25
25
|
- 🤖 **AI フレンドリー** ... Claude Code / Cursor / Codex 向けのスキルとガード設定を同梱。AI コーディングでもデザインシステムの品質を維持できます。
|
|
26
26
|
|
|
27
|
+
## バージョンと React・CLI の対応
|
|
28
|
+
|
|
29
|
+
| バージョン | React | sparkle-design-cli | 状態 |
|
|
30
|
+
|---|---|---|---|
|
|
31
|
+
| **2.x** | 19 以上 | 最新(現在は beta: `npx --yes sparkle-design-cli@beta`) | 現行。新機能・新コンポーネントはこちらにだけ入ります(現在は beta: `npm install sparkle-design@beta`) |
|
|
32
|
+
| **1.x** | 18(19 でも可) | 最新(`npx --yes sparkle-design-cli`) | **非推奨(deprecated)のメンテナンスライン**。不具合・セキュリティの修正と、最新の CLI と噛み合わせるためのトークン・スタイルの追従だけを行います |
|
|
33
|
+
|
|
34
|
+
2.x は全コンポーネントで `ref` を通常の props として受け取る React 19 の方式に移行しているため、React 18 では `ref` や Radix の `asChild` 経由の組み合わせ(Tooltip / Dialog のトリガーなど)が正しく動きません。React 18 のプロジェクトは 1.x をお使いください(2.x を React 18 のプロジェクトに入れると、npm では peer 依存の衝突で止まります)。
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install sparkle-design@1
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
CLI はどちらのバージョンでも固定せず最新を使います。CLI が生成するトークンが変わるときは 1.x も追従するので、1.x でも見た目は 2.x と同じデザインになります(1.x に入らないのは React 19 前提の変更と新機能だけです)。
|
|
41
|
+
|
|
42
|
+
1.x を使い続ける場合も、CLI が生成するトークンが変わったときは、アプリ側で使っている旧トークンのクラスを `migrate` で確認してください。
|
|
43
|
+
|
|
44
|
+
1.x から 2.x へは、プロジェクトを React 19 に上げてから移行してください。旧トークン(`text-neutral-900` など)から新トークンへの置き換えは `npx --yes sparkle-design-cli@beta migrate` で確認できます(既定は変更内容の表示のみ。`--write` で書き換え)。
|
|
45
|
+
|
|
27
46
|
## クイックスタート
|
|
28
47
|
|
|
29
48
|
### 1. セットアップ
|
|
@@ -7,7 +7,7 @@ import { type VariantProps } from "class-variance-authority";
|
|
|
7
7
|
declare const badgeVariants: (props?: ({
|
|
8
8
|
variant?: "normal" | "emphasis" | null | undefined;
|
|
9
9
|
isNumberVisible?: boolean | null | undefined;
|
|
10
|
-
size?: "xs" | "sm" | "md" | "lg" | null | undefined;
|
|
10
|
+
size?: "2xs" | "xs" | "sm" | "md" | "lg" | null | undefined;
|
|
11
11
|
isGapped?: boolean | null | undefined;
|
|
12
12
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
13
13
|
type BadgeVariants = VariantProps<typeof badgeVariants>;
|
|
@@ -12,7 +12,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
13
|
import { cva } from "class-variance-authority";
|
|
14
14
|
import { cn } from "../../../lib/utils.js";
|
|
15
|
-
const badgeVariants = cva("inline-flex items-center text-text-inverse text-center justify-center rounded-full transition-colors focus:outline-hidden focus:ring-2 focus:ring-border-ring focus:ring-offset-2", {
|
|
15
|
+
const badgeVariants = cva("inline-flex overflow-hidden items-center text-text-inverse text-center justify-center rounded-full transition-colors focus:outline-hidden focus:ring-2 focus:ring-border-ring focus:ring-offset-2", {
|
|
16
16
|
variants: {
|
|
17
17
|
variant: {
|
|
18
18
|
normal: "bg-surface-primary-high-enabled",
|
|
@@ -23,7 +23,8 @@ const badgeVariants = cva("inline-flex items-center text-text-inverse text-cente
|
|
|
23
23
|
false: "",
|
|
24
24
|
},
|
|
25
25
|
size: {
|
|
26
|
-
|
|
26
|
+
"2xs": "w-2 h-2 min-w-2",
|
|
27
|
+
xs: "w-3.5 h-3.5 min-w-3.5",
|
|
27
28
|
sm: "w-4 h-4 min-w-4",
|
|
28
29
|
md: "min-w-6 py-0.5 px-1.5 character-1-bold-mono",
|
|
29
30
|
lg: "min-w-8 py-1 px-1.5 character-3-bold-mono",
|
|
@@ -37,9 +38,14 @@ const badgeVariants = cva("inline-flex items-center text-text-inverse text-cente
|
|
|
37
38
|
// isGappedのボーダー設定
|
|
38
39
|
{
|
|
39
40
|
isGapped: true,
|
|
40
|
-
size: "
|
|
41
|
+
size: "2xs",
|
|
41
42
|
class: "outline-border-inverse outline-2",
|
|
42
43
|
},
|
|
44
|
+
{
|
|
45
|
+
isGapped: true,
|
|
46
|
+
size: "xs",
|
|
47
|
+
class: "outline-border-inverse outline-4",
|
|
48
|
+
},
|
|
43
49
|
{
|
|
44
50
|
isGapped: true,
|
|
45
51
|
size: "sm",
|
|
@@ -108,7 +114,7 @@ function Badge(_a) {
|
|
|
108
114
|
var { className, isNumberVisible = true, size, variant = "normal", isGapped = false, children, role = "status" } = _a, props = __rest(_a, ["className", "isNumberVisible", "size", "variant", "isGapped", "children", "role"]);
|
|
109
115
|
// sm以下のサイズの場合は、文字を非表示にする
|
|
110
116
|
// en: Hide text for sizes sm and below
|
|
111
|
-
if (size === "sm" || size === "xs") {
|
|
117
|
+
if (size === "sm" || size === "xs" || size === "2xs") {
|
|
112
118
|
isNumberVisible = false;
|
|
113
119
|
}
|
|
114
120
|
// childrenがない場合はisNumberVisibleがfalseの扱いにする
|
|
@@ -37,9 +37,9 @@ const buttonVariants = cva([
|
|
|
37
37
|
ghost: "",
|
|
38
38
|
},
|
|
39
39
|
size: {
|
|
40
|
-
sm: "h-8 min-w-16 px-3 py-1 character-
|
|
41
|
-
md: "h-10 min-w-20 px-4 py-1.5 character-
|
|
42
|
-
lg: "h-12 min-w-24 px-5 py-2 character-
|
|
40
|
+
sm: "h-8 min-w-16 px-3 py-1 character-1-bold-pro",
|
|
41
|
+
md: "h-10 min-w-20 px-4 py-1.5 character-2-bold-pro",
|
|
42
|
+
lg: "h-12 min-w-24 px-5 py-2 character-3-bold-pro",
|
|
43
43
|
},
|
|
44
44
|
theme: {
|
|
45
45
|
primary: "",
|
|
@@ -368,7 +368,7 @@ function Button(_a) {
|
|
|
368
368
|
case "sm":
|
|
369
369
|
return 4;
|
|
370
370
|
case "lg":
|
|
371
|
-
return
|
|
371
|
+
return 7;
|
|
372
372
|
default:
|
|
373
373
|
return 5;
|
|
374
374
|
}
|
|
@@ -531,7 +531,7 @@ function Button(_a) {
|
|
|
531
531
|
theme,
|
|
532
532
|
isLoading,
|
|
533
533
|
className,
|
|
534
|
-
})), onClickCapture: handleClickCapture, onAuxClickCapture: handleAuxClickCapture, onKeyDownCapture: handleKeyDownCapture, onClick: handleClick, onKeyDown: handleKeyDown }, restProps, { children: asChild ? (slottedChildren) : (_jsxs(_Fragment, { children: [prefixIcon && (_jsx(Icon, { icon: prefixIcon, size: getIconSize(), className: cn({ "opacity-0": isLoading }) })), isLoading ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 inline-flex", children: _jsx(Spinner, { size: getIconSize(), className: "text-current" }) }), _jsx("span", { className: "opacity-0", children: children })] })) : (_jsx("span", { className: "px-1", children: children })), suffixIcon && (_jsx(Icon, { icon: suffixIcon, size: getIconSize(), className: cn({ "opacity-0": isLoading }) }))] })) })));
|
|
534
|
+
})), onClickCapture: handleClickCapture, onAuxClickCapture: handleAuxClickCapture, onKeyDownCapture: handleKeyDownCapture, onClick: handleClick, onKeyDown: handleKeyDown }, restProps, { children: asChild ? (slottedChildren) : (_jsxs(_Fragment, { children: [prefixIcon && (_jsx(Icon, { icon: prefixIcon, size: getIconSize(), className: cn("text-current", { "opacity-0": isLoading }) })), isLoading ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 inline-flex", children: _jsx(Spinner, { size: getIconSize(), className: "text-current" }) }), _jsx("span", { className: "opacity-0", children: children })] })) : (_jsx("span", { className: "px-1", children: children })), suffixIcon && (_jsx(Icon, { icon: suffixIcon, size: getIconSize(), className: cn("text-current", { "opacity-0": isLoading }) }))] })) })));
|
|
535
535
|
}
|
|
536
536
|
Button.displayName = "Button";
|
|
537
537
|
export { Button, buttonVariants };
|
|
@@ -20,15 +20,17 @@ import { Checkbox as CheckboxPrimitive } from "radix-ui";
|
|
|
20
20
|
import { cva } from "class-variance-authority";
|
|
21
21
|
import { cn } from "../../../lib/utils.js";
|
|
22
22
|
import { Icon } from "../../../components/ui/icon/index.js";
|
|
23
|
-
const checkboxItemVariants = cva(
|
|
24
|
-
|
|
23
|
+
const checkboxItemVariants = cva(
|
|
24
|
+
// 表示寸法を維持しつつ、疑似要素で横24pxの操作領域を確保。en: Keep visuals, expand hit width to 24px.
|
|
25
|
+
[
|
|
26
|
+
"relative before:absolute before:inset-y-0 before:left-1/2 before:w-6 before:-translate-x-1/2 before:content-[''] rounded-sm transition-colors flex items-center justify-center cursor-pointer",
|
|
25
27
|
"focus:outline-none",
|
|
26
28
|
].join(" "), {
|
|
27
29
|
variants: {
|
|
28
30
|
size: {
|
|
29
|
-
sm: "h-8 w-
|
|
30
|
-
md: "h-10 w-
|
|
31
|
-
lg: "h-12 w-
|
|
31
|
+
sm: "h-8 w-4",
|
|
32
|
+
md: "h-10 w-[18px]",
|
|
33
|
+
lg: "h-12 w-5",
|
|
32
34
|
},
|
|
33
35
|
isDisabled: {
|
|
34
36
|
true: "cursor-not-allowed",
|
|
@@ -47,8 +49,8 @@ const checkboxRootVariants = cva([
|
|
|
47
49
|
variants: {
|
|
48
50
|
size: {
|
|
49
51
|
sm: "h-4 w-4",
|
|
50
|
-
md: "h-
|
|
51
|
-
lg: "h-
|
|
52
|
+
md: "h-[18px] w-[18px]",
|
|
53
|
+
lg: "h-5 w-5",
|
|
52
54
|
},
|
|
53
55
|
isInvalid: {
|
|
54
56
|
true: [
|
|
@@ -115,12 +117,12 @@ const checkboxLabelVariants = cva("cursor-pointer", {
|
|
|
115
117
|
variants: {
|
|
116
118
|
size: {
|
|
117
119
|
sm: "character-2-regular-pro",
|
|
118
|
-
md: "character-
|
|
119
|
-
lg: "character-
|
|
120
|
+
md: "character-2-regular-pro",
|
|
121
|
+
lg: "character-3-regular-pro",
|
|
120
122
|
},
|
|
121
123
|
isDisabled: {
|
|
122
124
|
true: "text-text-neutral-disabled cursor-not-allowed",
|
|
123
|
-
false: "text-text-neutral-middle",
|
|
125
|
+
false: "text-text-neutral-middle group-hover/checkbox:text-text-neutral-high",
|
|
124
126
|
},
|
|
125
127
|
},
|
|
126
128
|
defaultVariants: {
|
|
@@ -170,22 +172,22 @@ function Checkbox(_a) {
|
|
|
170
172
|
}, [isControlled, onCheckedChange]);
|
|
171
173
|
// isDisabledとdisabledの組み合わせで無効状態を管理
|
|
172
174
|
const isCheckboxDisabled = isDisabled || disabled;
|
|
173
|
-
return (_jsxs("div", { className: "flex items-center", children: [_jsx(CheckboxPrimitive.Root, Object.assign({ "data-slot": "checkbox", id: id, "aria-invalid": isInvalid || undefined, className: cn(checkboxItemVariants({ size, isDisabled: isCheckboxDisabled }), "group", className), disabled: isCheckboxDisabled, checked: checked, onCheckedChange: handleChange }, props, { children: _jsx("div", { className: cn(checkboxRootVariants({
|
|
175
|
+
return (_jsxs("div", { className: cn("group/checkbox flex items-center", size === "lg" ? "gap-2" : "gap-1.5"), children: [_jsx(CheckboxPrimitive.Root, Object.assign({ "data-slot": "checkbox", id: id, "aria-invalid": isInvalid || undefined, className: cn(checkboxItemVariants({ size, isDisabled: isCheckboxDisabled }), "group", className), disabled: isCheckboxDisabled, checked: checked, onCheckedChange: handleChange }, props, { children: _jsx("div", { className: cn(checkboxRootVariants({
|
|
174
176
|
size,
|
|
175
177
|
isInvalid,
|
|
176
178
|
isDisabled: isCheckboxDisabled,
|
|
177
|
-
})), children: _jsx(CheckboxPrimitive.Indicator, { "data-slot": "checkbox-indicator", className: "flex items-center justify-center text-surface-base-0", children: _jsx(Icon, { icon: checked === "indeterminate"
|
|
179
|
+
})), children: _jsx(CheckboxPrimitive.Indicator, { "data-slot": "checkbox-indicator", className: "flex items-center justify-center text-surface-base-0", children: _jsx(Icon, { className: "text-current", icon: checked === "indeterminate"
|
|
178
180
|
? "check_indeterminate_small"
|
|
179
181
|
: "check", size: (function () {
|
|
180
182
|
switch (size) {
|
|
181
183
|
case "sm":
|
|
182
184
|
return 3;
|
|
183
185
|
case "md":
|
|
184
|
-
return
|
|
186
|
+
return 4;
|
|
185
187
|
case "lg":
|
|
186
|
-
return 6;
|
|
187
|
-
default:
|
|
188
188
|
return 5;
|
|
189
|
+
default:
|
|
190
|
+
return 4;
|
|
189
191
|
}
|
|
190
192
|
})() }) }) }) })), label && (_jsx("label", { htmlFor: id, className: cn(checkboxLabelVariants({ size, isDisabled: isCheckboxDisabled })), children: label }))] }));
|
|
191
193
|
}
|
|
@@ -18,6 +18,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
18
18
|
import { AlertDialog as DialogPrimitive } from "radix-ui";
|
|
19
19
|
import { cn } from "../../../lib/utils.js";
|
|
20
20
|
import { Button } from "../../../components/ui/button/index.js";
|
|
21
|
+
import { Overlay } from "../overlay/index.js";
|
|
21
22
|
import { Icon } from "../icon/index.js";
|
|
22
23
|
/**
|
|
23
24
|
* **概要 / Overview**
|
|
@@ -90,7 +91,7 @@ function DialogPortal(_a) {
|
|
|
90
91
|
}
|
|
91
92
|
function DialogOverlay(_a) {
|
|
92
93
|
var { className } = _a, props = __rest(_a, ["className"]);
|
|
93
|
-
return (_jsx(DialogPrimitive.Overlay, Object.assign({ "data-slot": "dialog-overlay", className: cn("
|
|
94
|
+
return (_jsx(DialogPrimitive.Overlay, Object.assign({}, props, { asChild: true, children: _jsx(Overlay, { "data-slot": "dialog-overlay", className: cn("z-50", className) }) })));
|
|
94
95
|
}
|
|
95
96
|
function DialogContent(_a) {
|
|
96
97
|
var { className, children, showCloseButton = true } = _a, props = __rest(_a, ["className", "children", "showCloseButton"]);
|
|
@@ -133,7 +134,7 @@ function DialogDescription(_a) {
|
|
|
133
134
|
*/
|
|
134
135
|
function DialogCancel(_a) {
|
|
135
136
|
var { className, children } = _a, props = __rest(_a, ["className", "children"]);
|
|
136
|
-
return (_jsx(DialogPrimitive.Cancel, Object.assign({ "data-slot": "dialog-cancel", asChild: true }, props, { children: _jsx(Button, { variant: "ghost", theme: "neutral", size: "
|
|
137
|
+
return (_jsx(DialogPrimitive.Cancel, Object.assign({ "data-slot": "dialog-cancel", asChild: true }, props, { children: _jsx(Button, { variant: "ghost", theme: "neutral", size: "md", className: className, children: children }) })));
|
|
137
138
|
}
|
|
138
139
|
/**
|
|
139
140
|
* **アンチパターン / Anti-patterns**
|
|
@@ -152,6 +153,6 @@ function DialogCancel(_a) {
|
|
|
152
153
|
*/
|
|
153
154
|
function DialogAction(_a) {
|
|
154
155
|
var { className, children, theme = "primary", variant = "solid" } = _a, props = __rest(_a, ["className", "children", "theme", "variant"]);
|
|
155
|
-
return (_jsx(DialogPrimitive.Action, Object.assign({ "data-slot": "dialog-action", asChild: true }, props, { children: _jsx(Button, { variant: variant, theme: theme, size: "
|
|
156
|
+
return (_jsx(DialogPrimitive.Action, Object.assign({ "data-slot": "dialog-action", asChild: true }, props, { children: _jsx(Button, { variant: variant, theme: theme, size: "md", className: className, children: children }) })));
|
|
156
157
|
}
|
|
157
158
|
export { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogIcon, DialogTitle, DialogTrigger, DialogCancel, DialogAction, };
|
|
@@ -219,6 +219,6 @@ function FormErrorMessage(_a) {
|
|
|
219
219
|
if (!body) {
|
|
220
220
|
return null;
|
|
221
221
|
}
|
|
222
|
-
return (_jsxs("p", Object.assign({ "data-slot": "form-message", id: formMessageId, className: cn("flex gap-1 items-center text-text-negative-enabled character-1-regular-pro", className) }, props, { children: [_jsx(Icon, { icon: "error", size: 3 }), body] })));
|
|
222
|
+
return (_jsxs("p", Object.assign({ "data-slot": "form-message", id: formMessageId, className: cn("flex gap-1 items-center text-text-negative-enabled character-1-regular-pro", className) }, props, { children: [_jsx(Icon, { icon: "error", size: 3, className: "text-object-negative-enabled" }), body] })));
|
|
223
223
|
}
|
|
224
224
|
export { useFormField, Form, FormItem, FormHeader, FormControl, FormHelperMessage, FormErrorMessage, FormField, };
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import * as React from "react";
|
|
6
6
|
/**
|
|
7
|
-
* アイコンサイズのスケール値(1-
|
|
8
|
-
* en: Icon size scale values (1-
|
|
7
|
+
* アイコンサイズのスケール値(1-13)
|
|
8
|
+
* en: Icon size scale values (1-13)
|
|
9
9
|
*
|
|
10
10
|
* | scale | px |
|
|
11
11
|
* |-------|-----|
|
|
@@ -14,15 +14,16 @@ import * as React from "react";
|
|
|
14
14
|
* | 3 | 16 |
|
|
15
15
|
* | 4 | 18 |
|
|
16
16
|
* | 5 | 20 |
|
|
17
|
-
* | 6 |
|
|
18
|
-
* | 7 |
|
|
19
|
-
* | 8 |
|
|
20
|
-
* | 9 |
|
|
21
|
-
* | 10 |
|
|
22
|
-
* | 11 |
|
|
23
|
-
* | 12 |
|
|
17
|
+
* | 6 | 22 |
|
|
18
|
+
* | 7 | 24 |
|
|
19
|
+
* | 8 | 28 |
|
|
20
|
+
* | 9 | 32 |
|
|
21
|
+
* | 10 | 36 |
|
|
22
|
+
* | 11 | 42 |
|
|
23
|
+
* | 12 | 48 |
|
|
24
|
+
* | 13 | 54 |
|
|
24
25
|
*/
|
|
25
|
-
export type IconSize = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
|
|
26
|
+
export type IconSize = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13;
|
|
26
27
|
export interface IconProps extends React.ComponentProps<"span"> {
|
|
27
28
|
/**
|
|
28
29
|
* 表示するアイコン名
|
|
@@ -30,8 +31,8 @@ export interface IconProps extends React.ComponentProps<"span"> {
|
|
|
30
31
|
*/
|
|
31
32
|
icon: string;
|
|
32
33
|
/**
|
|
33
|
-
* アイコンサイズ(スケール値 1-
|
|
34
|
-
* en: Size of the icon (scale value 1-
|
|
34
|
+
* アイコンサイズ(スケール値 1-13)
|
|
35
|
+
* en: Size of the icon (scale value 1-13)
|
|
35
36
|
* @see IconSize
|
|
36
37
|
*/
|
|
37
38
|
size?: IconSize;
|
|
@@ -63,7 +64,7 @@ export interface IconProps extends React.ComponentProps<"span"> {
|
|
|
63
64
|
* **使用例 / Usage Example**
|
|
64
65
|
*
|
|
65
66
|
* ```tsx
|
|
66
|
-
* <Icon icon="check" size={
|
|
67
|
+
* <Icon icon="check" size={7} fill={true} />
|
|
67
68
|
* ```
|
|
68
69
|
*
|
|
69
70
|
* @param {IconProps} props
|
|
@@ -33,7 +33,7 @@ import { cn } from "../../../lib/utils.js";
|
|
|
33
33
|
* **使用例 / Usage Example**
|
|
34
34
|
*
|
|
35
35
|
* ```tsx
|
|
36
|
-
* <Icon icon="check" size={
|
|
36
|
+
* <Icon icon="check" size={7} fill={true} />
|
|
37
37
|
* ```
|
|
38
38
|
*
|
|
39
39
|
* @param {IconProps} props
|
|
@@ -52,6 +52,6 @@ export function Icon(_a) {
|
|
|
52
52
|
// font-weight が継承されると疑似ボールド(faux bold)で太く描画されるため明示する。
|
|
53
53
|
// en: Icons are unified at weight 500. Set font-weight explicitly so an inherited
|
|
54
54
|
// font-weight (e.g. bold Button labels) does not trigger faux-bold rendering.
|
|
55
|
-
className: cn(iconTypographyClass, "select-none font-medium", className), "aria-hidden": "true" }, props, { children: icon })));
|
|
55
|
+
className: cn(iconTypographyClass, "select-none font-medium text-object-neutral-high", className), "aria-hidden": "true" }, props, { children: icon })));
|
|
56
56
|
}
|
|
57
57
|
Icon.displayName = "Icon";
|
|
@@ -443,9 +443,9 @@ function IconButton(_a) {
|
|
|
443
443
|
case "sm":
|
|
444
444
|
return 5;
|
|
445
445
|
case "lg":
|
|
446
|
-
return
|
|
446
|
+
return 8;
|
|
447
447
|
default:
|
|
448
|
-
return
|
|
448
|
+
return 7;
|
|
449
449
|
}
|
|
450
450
|
};
|
|
451
451
|
const { onClick, onKeyDown, onClickCapture, onKeyDownCapture, onAuxClickCapture, type, form, formAction, formEncType, formMethod, formNoValidate, formTarget, value, popoverTarget, popoverTargetAction, "aria-disabled": ariaDisabled } = props, restProps = __rest(props, ["onClick", "onKeyDown", "onClickCapture", "onKeyDownCapture", "onAuxClickCapture", "type", "form", "formAction", "formEncType", "formMethod", "formNoValidate", "formTarget", "value", "popoverTarget", "popoverTargetAction", "aria-disabled"]);
|
|
@@ -553,7 +553,7 @@ function IconButton(_a) {
|
|
|
553
553
|
// aria-disabled as well.
|
|
554
554
|
isDisabled: Boolean(isDisabled || disabled) || isSoftDisabled,
|
|
555
555
|
className,
|
|
556
|
-
})), disabled: canUseButtonProps ? isIconButtonDisabled : undefined, onClickCapture: handleClickCapture, onAuxClickCapture: handleAuxClickCapture, onKeyDownCapture: handleKeyDownCapture, onClick: handleClick, onKeyDown: handleKeyDown }, restProps, { children: [asChild && (_jsx(SlotPrimitive.Slottable, { children: slottedChildren })), isLoading ? (_jsx(Spinner, { size: getIconSize(), className: "text-current" })) : (_jsx(Icon, { icon: icon, size: getIconSize() }))] })));
|
|
556
|
+
})), disabled: canUseButtonProps ? isIconButtonDisabled : undefined, onClickCapture: handleClickCapture, onAuxClickCapture: handleAuxClickCapture, onKeyDownCapture: handleKeyDownCapture, onClick: handleClick, onKeyDown: handleKeyDown }, restProps, { children: [asChild && (_jsx(SlotPrimitive.Slottable, { children: slottedChildren })), isLoading ? (_jsx(Spinner, { size: getIconSize(), className: "text-current" })) : (_jsx(Icon, { icon: icon, size: getIconSize(), className: "text-current" }))] })));
|
|
557
557
|
}
|
|
558
558
|
IconButton.displayName = "IconButton";
|
|
559
559
|
export { IconButton, iconButtonVariants };
|
|
@@ -94,7 +94,7 @@ function InlineMessage(_a) {
|
|
|
94
94
|
const colorClass = status
|
|
95
95
|
? statusColorClasses[status]
|
|
96
96
|
: statusColorClasses.info;
|
|
97
|
-
return (_jsx(InlineMessageContext.Provider, { value: contextValue, children: _jsxs("div", Object.assign({ ref: ref, role: "alert", "aria-labelledby": hasTitle ? titleId : undefined, "aria-describedby": hasDesc ? descId : undefined, className: cn(inlineMessageVariants({ status }), className) }, props, { children: [_jsx("span", { className: "inline-flex p-1 items-center justify-center", "aria-hidden": "true", children: _jsx(Icon, { icon: statusIcon, size:
|
|
97
|
+
return (_jsx(InlineMessageContext.Provider, { value: contextValue, children: _jsxs("div", Object.assign({ ref: ref, role: "alert", "aria-labelledby": hasTitle ? titleId : undefined, "aria-describedby": hasDesc ? descId : undefined, className: cn(inlineMessageVariants({ status }), className) }, props, { children: [_jsx("span", { className: "inline-flex p-1 items-center justify-center", "aria-hidden": "true", children: _jsx(Icon, { icon: statusIcon, size: 7, fill: false, className: cn(colorClass) }) }), _jsx("div", { className: "flex flex-col flex-1 min-h-8", children: children }), isCloseTrigger && onClose && (_jsx(IconButton, { icon: "close", size: "sm", variant: "ghost", theme: "neutral", onClick: onClose, "aria-label": "\u9589\u3058\u308B", className: "shrink-0" }))] })) }));
|
|
98
98
|
}
|
|
99
99
|
InlineMessage.displayName = "InlineMessage";
|
|
100
100
|
/**
|
|
@@ -25,8 +25,8 @@ const inputVariants = cva("flex gap-0 items-center w-full rounded-action border
|
|
|
25
25
|
variants: {
|
|
26
26
|
size: {
|
|
27
27
|
sm: "h-8 character-2-regular-pro",
|
|
28
|
-
md: "h-10 character-
|
|
29
|
-
lg: "h-12 character-
|
|
28
|
+
md: "h-10 character-2-regular-pro",
|
|
29
|
+
lg: "h-12 character-3-regular-pro",
|
|
30
30
|
},
|
|
31
31
|
isInvalid: {
|
|
32
32
|
true: "border-border-negative-extra-high-enabled",
|
|
@@ -236,12 +236,16 @@ function Input(_a) {
|
|
|
236
236
|
isDisabled: isInputDisabled,
|
|
237
237
|
isFocused: isInputFocused && !isIconButtonFocused,
|
|
238
238
|
className,
|
|
239
|
-
}),
|
|
239
|
+
}), isInputDisabled &&
|
|
240
|
+
!isInvalid &&
|
|
241
|
+
!isTrigger &&
|
|
242
|
+
"border-border-neutral-middle", !isInputDisabled && "cursor-text" // 入力可能な場合はテキストカーソルを表示
|
|
240
243
|
),
|
|
241
244
|
// NOTE: not supportエラーがLintで出るためコメントアウト
|
|
242
245
|
// aria-disabled={isInputDisabled}
|
|
243
246
|
// aria-invalid={isInvalid === null ? undefined : isInvalid}
|
|
244
|
-
onClick: handleContainerClick, role: "presentation", tabIndex: -1, children: [_jsx("input", Object.assign({ ref: mergedInputRef, disabled: isInputDisabled, "aria-invalid": isInvalid || undefined, className: cn("w-full h-full bg-transparent border-none outline-hidden focus:outline-hidden", "text-text-neutral-high placeholder:text-text-neutral-low
|
|
247
|
+
onClick: handleContainerClick, role: "presentation", tabIndex: -1, children: [_jsx("input", Object.assign({ ref: mergedInputRef, disabled: isInputDisabled, "aria-invalid": isInvalid || undefined, className: cn("w-full h-full bg-transparent border-none outline-hidden focus:outline-hidden", "text-text-neutral-high placeholder:text-text-neutral-low pr-2", size === "lg" ? "pl-3" : size === "sm" ? "pl-1.5" : "pl-2", !isTrigger &&
|
|
248
|
+
(size === "lg" ? "pr-3" : size === "sm" ? "pr-1.5" : "pr-2"), isInputDisabled &&
|
|
245
249
|
"cursor-not-allowed text-text-neutral-disabled placeholder:text-text-neutral-disabled"), onChange: handleChange, onFocus: handleInputFocus, onBlur: handleInputBlur, defaultValue: defaultValue, value: value, "aria-disabled": isInputDisabled }, props)), isTrigger && (_jsx(IconButton
|
|
246
250
|
// triggerProps を先に展開し、専用 props (triggerAriaLabel / onIconButtonClick)
|
|
247
251
|
// と内部制御プロパティで上書きする
|
|
@@ -68,13 +68,13 @@ export function Link(_a) {
|
|
|
68
68
|
const hasCharacterClass = className === null || className === void 0 ? void 0 : className.includes("character-");
|
|
69
69
|
// character-X-*-* のXの部分(サイズ)を取得
|
|
70
70
|
const characterSizeMatch = className === null || className === void 0 ? void 0 : className.match(/character-(\d+)-/);
|
|
71
|
-
const parsed = characterSizeMatch ? parseInt(characterSizeMatch[1], 10) :
|
|
72
|
-
const characterSize = (parsed >= 1 && parsed <= 12 ? parsed :
|
|
71
|
+
const parsed = characterSizeMatch ? parseInt(characterSizeMatch[1], 10) : 2;
|
|
72
|
+
const characterSize = (parsed >= 1 && parsed <= 12 ? parsed : 2);
|
|
73
73
|
// character クラスの生成
|
|
74
74
|
const characterSizeClass = hasCharacterClass
|
|
75
75
|
? "" // 外部で指定されている場合は付与しない
|
|
76
76
|
: `character-${characterSize}-regular-pro`;
|
|
77
|
-
const linkClassName = cn("inline group", characterSizeClass, className);
|
|
77
|
+
const linkClassName = cn("inline group rounded-lg focus-visible:outline-2 focus-visible:outline-border-ring focus-visible:outline-offset-2", characterSizeClass, className);
|
|
78
78
|
if (asChild &&
|
|
79
79
|
typeof process !== "undefined" &&
|
|
80
80
|
process.env.NODE_ENV !== "production" &&
|
|
@@ -84,10 +84,12 @@ export function Link(_a) {
|
|
|
84
84
|
console.warn("[Link] asChild の子要素にはリンク要素(<a> や next/link 等)を渡してください。<span> や <div> を渡すとアクセシビリティが損なわれます。");
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
-
const linkContent = (_jsxs(_Fragment, { children: [_jsx("span", { className: "transition-colors text-text-primary-enabled group-hover:text-text-primary-hover underline decoration-current underline-offset-2", children: children }), isExternalLink && (_jsx(Icon, { icon: "open_in_new", size: characterSize, className: "ml-1 align-middle inline-block text-object-primary-enabled group-hover:text-object-primary-hover" }))] }));
|
|
87
|
+
const linkContent = (_jsxs(_Fragment, { children: [_jsx("span", { className: "transition-colors text-text-primary-enabled group-hover:text-text-primary-hover underline decoration-current underline-offset-2", children: children }), isExternalLink && (_jsx(Icon, { icon: "open_in_new", size: (characterSize >= 6 ? characterSize + 1 : characterSize), className: "ml-1 align-middle inline-block text-object-primary-enabled group-hover:text-object-primary-hover" }))] }));
|
|
88
88
|
if (asChild) {
|
|
89
89
|
return (_jsx(SlotPrimitive.Slot, Object.assign({ ref: ref, className: linkClassName }, props, { children: React.isValidElement(children)
|
|
90
|
-
? React.cloneElement(children, {}, _jsxs(_Fragment, { children: [_jsx("span", { className: "transition-colors text-text-primary-enabled group-hover:text-text-primary-hover underline decoration-current underline-offset-2", children: children.props.children }), isExternalLink && (_jsx(Icon, { icon: "open_in_new", size: characterSize
|
|
90
|
+
? React.cloneElement(children, {}, _jsxs(_Fragment, { children: [_jsx("span", { className: "transition-colors text-text-primary-enabled group-hover:text-text-primary-hover underline decoration-current underline-offset-2", children: children.props.children }), isExternalLink && (_jsx(Icon, { icon: "open_in_new", size: (characterSize >= 6
|
|
91
|
+
? characterSize + 1
|
|
92
|
+
: characterSize), className: "ml-1 align-middle inline-block text-object-primary-enabled group-hover:text-object-primary-hover" }))] }))
|
|
91
93
|
: linkContent })));
|
|
92
94
|
}
|
|
93
95
|
return (_jsx("a", Object.assign({ ref: ref, className: linkClassName }, props, { children: linkContent })));
|
|
@@ -18,6 +18,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
18
18
|
import * as React from "react";
|
|
19
19
|
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
20
20
|
import { cn } from "../../../lib/utils.js";
|
|
21
|
+
import { Overlay } from "../overlay/index.js";
|
|
21
22
|
import { IconButton } from "../icon-button/index.js";
|
|
22
23
|
/**
|
|
23
24
|
* **概要 / Overview**
|
|
@@ -95,12 +96,12 @@ function ModalTitle(_a) {
|
|
|
95
96
|
/// モーダルのクローズボタン
|
|
96
97
|
function ModalClose(_a) {
|
|
97
98
|
var { "aria-label": ariaLabel = "閉じる" } = _a, props = __rest(_a, ["aria-label"]);
|
|
98
|
-
return (_jsx(DialogPrimitive.Close, { asChild: true, children: _jsx(IconButton, Object.assign({ icon: "close", "data-slot": "modal-close", size: "
|
|
99
|
+
return (_jsx(DialogPrimitive.Close, { asChild: true, children: _jsx(IconButton, Object.assign({ icon: "close", "data-slot": "modal-close", size: "sm", variant: "ghost", theme: "neutral", "aria-label": ariaLabel }, props)) }));
|
|
99
100
|
}
|
|
100
101
|
/// モーダルのオーバーレイ要素
|
|
101
102
|
function ModalOverlay(_a) {
|
|
102
103
|
var { className } = _a, props = __rest(_a, ["className"]);
|
|
103
|
-
return (_jsx(DialogPrimitive.Overlay, Object.assign({ "data-slot": "modal-overlay", className: cn("
|
|
104
|
+
return (_jsx(DialogPrimitive.Overlay, Object.assign({}, props, { asChild: true, children: _jsx(Overlay, { "data-slot": "modal-overlay", className: cn("z-50", className) }) })));
|
|
104
105
|
}
|
|
105
106
|
/// モーダルの本体
|
|
106
107
|
function ModalContent(_a) {
|
|
@@ -28,8 +28,8 @@ const labelVariants = cva("cursor-pointer", {
|
|
|
28
28
|
variants: {
|
|
29
29
|
size: {
|
|
30
30
|
sm: "character-2-regular-pro",
|
|
31
|
-
md: "character-
|
|
32
|
-
lg: "character-
|
|
31
|
+
md: "character-2-regular-pro",
|
|
32
|
+
lg: "character-3-regular-pro",
|
|
33
33
|
},
|
|
34
34
|
isDisabled: {
|
|
35
35
|
true: "text-text-neutral-disabled cursor-not-allowed",
|
|
@@ -41,15 +41,17 @@ const labelVariants = cva("cursor-pointer", {
|
|
|
41
41
|
isDisabled: false,
|
|
42
42
|
},
|
|
43
43
|
});
|
|
44
|
-
const radioItemVariants = cva(
|
|
45
|
-
|
|
44
|
+
const radioItemVariants = cva(
|
|
45
|
+
// 表示寸法を維持しつつ、疑似要素で横24pxの操作領域を確保。en: Keep visuals, expand hit width to 24px.
|
|
46
|
+
[
|
|
47
|
+
"relative before:absolute before:inset-y-0 before:left-1/2 before:w-6 before:-translate-x-1/2 before:content-[''] rounded-full transition-colors flex items-center justify-center cursor-pointer",
|
|
46
48
|
"focus:outline-none",
|
|
47
49
|
].join(" "), {
|
|
48
50
|
variants: {
|
|
49
51
|
size: {
|
|
50
|
-
sm: "h-8 w-
|
|
51
|
-
md: "h-10 w-
|
|
52
|
-
lg: "h-12 w-
|
|
52
|
+
sm: "h-8 w-4",
|
|
53
|
+
md: "h-10 w-[18px]",
|
|
54
|
+
lg: "h-12 w-5",
|
|
53
55
|
},
|
|
54
56
|
isDisabled: {
|
|
55
57
|
true: "cursor-not-allowed",
|
|
@@ -68,8 +70,8 @@ const radioIndicatorVariants = cva([
|
|
|
68
70
|
variants: {
|
|
69
71
|
size: {
|
|
70
72
|
sm: "h-4 w-4",
|
|
71
|
-
md: "h-
|
|
72
|
-
lg: "h-
|
|
73
|
+
md: "h-[18px] w-[18px]",
|
|
74
|
+
lg: "h-5 w-5",
|
|
73
75
|
},
|
|
74
76
|
isInvalid: {
|
|
75
77
|
true: "border-object-negative-enabled [.group[data-state=checked]_&]:border-object-negative-enabled",
|
|
@@ -110,8 +112,8 @@ const radioIndicatorDotVariants = cva("rounded-full transition-colors flex items
|
|
|
110
112
|
variants: {
|
|
111
113
|
size: {
|
|
112
114
|
sm: "h-4 w-4",
|
|
113
|
-
md: "h-
|
|
114
|
-
lg: "h-
|
|
115
|
+
md: "h-[18px] w-[18px]",
|
|
116
|
+
lg: "h-5 w-5",
|
|
115
117
|
},
|
|
116
118
|
isInvalid: {
|
|
117
119
|
true: "[.group[data-state=checked]_&]:bg-object-negative-enabled",
|
|
@@ -154,8 +156,8 @@ const radioIndicatorDotInnerVariants = cva("rounded-full bg-surface-base-0", {
|
|
|
154
156
|
variants: {
|
|
155
157
|
size: {
|
|
156
158
|
sm: "h-2 w-2",
|
|
157
|
-
md: "h-
|
|
158
|
-
lg: "h-
|
|
159
|
+
md: "h-[9px] w-[9px]",
|
|
160
|
+
lg: "h-2.5 w-2.5",
|
|
159
161
|
},
|
|
160
162
|
},
|
|
161
163
|
defaultVariants: {
|
|
@@ -264,7 +266,7 @@ Radio.displayName = RadioPrimitive.Root.displayName;
|
|
|
264
266
|
function RadioItem(_a) {
|
|
265
267
|
var { className, size = "md", isInvalid: isInvalidProp = false, disabled = false, label, id } = _a, props = __rest(_a, ["className", "size", "isInvalid", "disabled", "label", "id"]);
|
|
266
268
|
const isInvalid = React.useContext(RadioInvalidContext) || !!isInvalidProp;
|
|
267
|
-
return (_jsxs("div", { className: "flex items-center", children: [_jsx(RadioPrimitive.Item, Object.assign({ "data-slot": "radio-group-item", id: id, className: cn(radioItemVariants({ size, isDisabled: disabled }), "group", className), disabled: disabled }, props, { children: _jsx("div", { className: cn(radioIndicatorVariants({ size, isInvalid, isDisabled: disabled })), children: _jsx(RadioPrimitive.Indicator, { "data-slot": "radio-group-indicator", className: cn(radioIndicatorDotVariants({
|
|
269
|
+
return (_jsxs("div", { className: cn("flex items-center", size === "lg" ? "gap-2" : "gap-1.5"), children: [_jsx(RadioPrimitive.Item, Object.assign({ "data-slot": "radio-group-item", id: id, className: cn(radioItemVariants({ size, isDisabled: disabled }), "group", className), disabled: disabled }, props, { children: _jsx("div", { className: cn(radioIndicatorVariants({ size, isInvalid, isDisabled: disabled })), children: _jsx(RadioPrimitive.Indicator, { "data-slot": "radio-group-indicator", className: cn(radioIndicatorDotVariants({
|
|
268
270
|
size,
|
|
269
271
|
isInvalid,
|
|
270
272
|
isDisabled: disabled,
|
|
@@ -26,9 +26,11 @@ const selectTriggerVariants = cva([
|
|
|
26
26
|
].join(" "), {
|
|
27
27
|
variants: {
|
|
28
28
|
size: {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
// Figma の内側6px + 外側4pxを合成した10px。en: Combine inner 6px and outer 4px.
|
|
30
|
+
// sparkle-disable-next-line use-figma-spacing-scale
|
|
31
|
+
sm: "h-8 py-1 pl-2.5 pr-1.5 gap-2 character-2-regular-pro",
|
|
32
|
+
md: "h-10 py-1 pl-3 pr-2 gap-2 character-2-regular-pro",
|
|
33
|
+
lg: "h-12 py-1 pl-4 pr-2 gap-2 character-3-regular-pro",
|
|
32
34
|
},
|
|
33
35
|
isInvalid: {
|
|
34
36
|
true: "bg-surface-base-0 border-border-negative-extra-high-enabled hover:border-border-negative-extra-high-hover data-[state=open]:border-border-negative-extra-high-hover",
|
|
@@ -56,8 +58,8 @@ const selectIconVariants = cva("", {
|
|
|
56
58
|
variants: {
|
|
57
59
|
size: {
|
|
58
60
|
sm: "icon-5-fill-0",
|
|
59
|
-
md: "icon-
|
|
60
|
-
lg: "icon-
|
|
61
|
+
md: "icon-7-fill-0",
|
|
62
|
+
lg: "icon-8-fill-0",
|
|
61
63
|
},
|
|
62
64
|
isDisabled: {
|
|
63
65
|
true: "text-object-neutral-disabled",
|
|
@@ -228,7 +230,7 @@ function SelectItem(_a) {
|
|
|
228
230
|
"py-1.5 pl-8 pr-2 text-sm",
|
|
229
231
|
"character-1-regular-pro text-text-neutral-middle",
|
|
230
232
|
"outline-none focus:bg-neutral-100 data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50",
|
|
231
|
-
].join(" "), className) }, props, { children: [_jsx(SelectPrimitive.ItemIndicator, { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: _jsx(Icon, { icon: "check", size: 4 }) }), _jsx(SelectPrimitive.ItemText, { className: cn("flex-1", textClassName), children: children })] })));
|
|
233
|
+
].join(" "), className) }, props, { children: [_jsx(SelectPrimitive.ItemIndicator, { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: _jsx(Icon, { icon: "check", size: 4, className: "text-current" }) }), _jsx(SelectPrimitive.ItemText, { className: cn("flex-1", textClassName), children: children })] })));
|
|
232
234
|
}
|
|
233
235
|
/**
|
|
234
236
|
* **概要 / Overview**
|
|
@@ -260,7 +262,7 @@ function SelectSeparator(_a) {
|
|
|
260
262
|
*/
|
|
261
263
|
function SelectScrollUpButton(_a) {
|
|
262
264
|
var { className } = _a, props = __rest(_a, ["className"]);
|
|
263
|
-
return (_jsx(SelectPrimitive.ScrollUpButton, Object.assign({ "data-slot": "select-scroll-up-button", className: cn("flex cursor-default items-center justify-center py-1", className) }, props, { children: _jsx(Icon, { icon: "expand_less", size: 4 }) })));
|
|
265
|
+
return (_jsx(SelectPrimitive.ScrollUpButton, Object.assign({ "data-slot": "select-scroll-up-button", className: cn("flex cursor-default items-center justify-center py-1", className) }, props, { children: _jsx(Icon, { icon: "expand_less", size: 4, className: "text-object-neutral-middle" }) })));
|
|
264
266
|
}
|
|
265
267
|
/**
|
|
266
268
|
* **概要 / Overview**
|
|
@@ -276,6 +278,6 @@ function SelectScrollUpButton(_a) {
|
|
|
276
278
|
*/
|
|
277
279
|
function SelectScrollDownButton(_a) {
|
|
278
280
|
var { className } = _a, props = __rest(_a, ["className"]);
|
|
279
|
-
return (_jsx(SelectPrimitive.ScrollDownButton, Object.assign({ "data-slot": "select-scroll-down-button", className: cn("flex cursor-default items-center justify-center py-1", className) }, props, { children: _jsx(Icon, { icon: "expand_more", size: 4 }) })));
|
|
281
|
+
return (_jsx(SelectPrimitive.ScrollDownButton, Object.assign({ "data-slot": "select-scroll-down-button", className: cn("flex cursor-default items-center justify-center py-1", className) }, props, { children: _jsx(Icon, { icon: "expand_more", size: 4, className: "text-object-neutral-middle" }) })));
|
|
280
282
|
}
|
|
281
283
|
export { Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton, };
|
|
@@ -41,7 +41,7 @@ const sliderRangeVariants = cva("absolute h-full bg-object-info", {
|
|
|
41
41
|
},
|
|
42
42
|
});
|
|
43
43
|
const sliderThumbVariants = cva([
|
|
44
|
-
"relative block rounded-full border border-object-neutral-low bg-surface-base-0 shadow-
|
|
44
|
+
"relative block rounded-full border border-object-neutral-low bg-surface-base-0 shadow-base cursor-pointer",
|
|
45
45
|
// 半透明の状態色は白地に重ねる(つまみの下のトラックを透かさない)
|
|
46
46
|
// en: Layer translucent state colors over the white fill so the track does not show through
|
|
47
47
|
"ring-offset-background transition-colors hover:border-object-neutral-middle hover:bg-linear-to-r hover:from-surface-neutral-low-hover hover:to-surface-neutral-low-hover",
|
|
@@ -54,7 +54,7 @@ const sliderThumbVariants = cva([
|
|
|
54
54
|
].join(" "), {
|
|
55
55
|
variants: {
|
|
56
56
|
isDisabled: {
|
|
57
|
-
true: "pointer-events-none bg-surface-neutral-middle-disabled bg-none border-
|
|
57
|
+
true: "pointer-events-none bg-surface-neutral-middle-disabled bg-none border-object-neutral-low shadow-base cursor-not-allowed",
|
|
58
58
|
},
|
|
59
59
|
},
|
|
60
60
|
defaultVariants: {
|
|
@@ -6,8 +6,8 @@ import React from "react";
|
|
|
6
6
|
import { type IconSize } from "@/components/ui/icon";
|
|
7
7
|
export interface SpinnerProps extends React.ComponentProps<"span"> {
|
|
8
8
|
/**
|
|
9
|
-
* スピナーのサイズ(スケール値 1-
|
|
10
|
-
* en: Size of the spinner (scale value 1-
|
|
9
|
+
* スピナーのサイズ(スケール値 1-13)
|
|
10
|
+
* en: Size of the spinner (scale value 1-13)
|
|
11
11
|
* @see IconSize
|
|
12
12
|
*/
|
|
13
13
|
size?: IconSize;
|
|
@@ -20,12 +20,12 @@ export interface SpinnerProps extends React.ComponentProps<"span"> {
|
|
|
20
20
|
*
|
|
21
21
|
* **アンチパターン / Anti-patterns**
|
|
22
22
|
*
|
|
23
|
-
* - `size` にピクセル値(24, 32 など)を渡さないでください。スケール値(1-
|
|
24
|
-
* en: Do not pass pixel values to `size`. Use scale values (1-
|
|
23
|
+
* - `size` にピクセル値(24, 32 など)を渡さないでください。スケール値(1-13)を使用してください。
|
|
24
|
+
* en: Do not pass pixel values to `size`. Use scale values (1-13) instead.
|
|
25
25
|
*
|
|
26
26
|
* ```tsx
|
|
27
27
|
* // ✅ Correct - スケール値
|
|
28
|
-
* <Spinner size={
|
|
28
|
+
* <Spinner size={7} />
|
|
29
29
|
*
|
|
30
30
|
* // ❌ Wrong - ピクセル値
|
|
31
31
|
* <Spinner size={24} />
|
|
@@ -34,7 +34,7 @@ export interface SpinnerProps extends React.ComponentProps<"span"> {
|
|
|
34
34
|
* **使用例 / Usage Example**
|
|
35
35
|
*
|
|
36
36
|
* ```tsx
|
|
37
|
-
* <Spinner size={
|
|
37
|
+
* <Spinner size={7} />
|
|
38
38
|
* ```
|
|
39
39
|
*
|
|
40
40
|
* @param {SpinnerProps} props
|
|
@@ -20,12 +20,12 @@ import { Icon } from "../../../components/ui/icon/index.js";
|
|
|
20
20
|
*
|
|
21
21
|
* **アンチパターン / Anti-patterns**
|
|
22
22
|
*
|
|
23
|
-
* - `size` にピクセル値(24, 32 など)を渡さないでください。スケール値(1-
|
|
24
|
-
* en: Do not pass pixel values to `size`. Use scale values (1-
|
|
23
|
+
* - `size` にピクセル値(24, 32 など)を渡さないでください。スケール値(1-13)を使用してください。
|
|
24
|
+
* en: Do not pass pixel values to `size`. Use scale values (1-13) instead.
|
|
25
25
|
*
|
|
26
26
|
* ```tsx
|
|
27
27
|
* // ✅ Correct - スケール値
|
|
28
|
-
* <Spinner size={
|
|
28
|
+
* <Spinner size={7} />
|
|
29
29
|
*
|
|
30
30
|
* // ❌ Wrong - ピクセル値
|
|
31
31
|
* <Spinner size={24} />
|
|
@@ -34,7 +34,7 @@ import { Icon } from "../../../components/ui/icon/index.js";
|
|
|
34
34
|
* **使用例 / Usage Example**
|
|
35
35
|
*
|
|
36
36
|
* ```tsx
|
|
37
|
-
* <Spinner size={
|
|
37
|
+
* <Spinner size={7} />
|
|
38
38
|
* ```
|
|
39
39
|
*
|
|
40
40
|
* @param {SpinnerProps} props
|
|
@@ -26,8 +26,8 @@ const TabsListVariantContext = createContext(undefined);
|
|
|
26
26
|
*/
|
|
27
27
|
const tabsTriggerVariants = cva([
|
|
28
28
|
"inline-flex items-center justify-center gap-1.5 whitespace-nowrap transition-colors duration-150 cursor-pointer disabled:cursor-not-allowed",
|
|
29
|
-
"px-3 py-2 character-
|
|
30
|
-
"focus-visible:outline-none",
|
|
29
|
+
"px-3 py-2 character-2-regular-pro data-[state=active]:[font-weight:var(--font-weight-char-bold)]!",
|
|
30
|
+
"relative focus-visible:outline-none focus-visible:z-20 before:pointer-events-none before:absolute before:inset-[-4px] before:rounded-lg before:border-2 before:border-border-ring before:opacity-0 focus-visible:before:opacity-100",
|
|
31
31
|
], {
|
|
32
32
|
variants: {
|
|
33
33
|
variant: {
|
|
@@ -102,7 +102,7 @@ const tabsListVariants = cva(["relative inline-flex items-center"], {
|
|
|
102
102
|
},
|
|
103
103
|
scrollable: {
|
|
104
104
|
true: [
|
|
105
|
-
"w-full max-w-full justify-start gap-2 overflow-x-auto overflow-y-visible",
|
|
105
|
+
"w-full max-w-full justify-start gap-2 overflow-x-auto overflow-y-visible p-1",
|
|
106
106
|
"whitespace-nowrap overscroll-x-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
107
107
|
].join(" "),
|
|
108
108
|
false: "w-fit justify-center gap-2 overflow-visible",
|
|
@@ -10,6 +10,8 @@ declare const tagVariants: (props?: ({
|
|
|
10
10
|
status?: "neutral" | "negative" | "info" | "success" | "warning" | null | undefined;
|
|
11
11
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
12
12
|
export interface TagProps extends React.ComponentProps<"div">, VariantProps<typeof tagVariants> {
|
|
13
|
+
/** ステータスドットの表示 / en: Whether to show a status dot */
|
|
14
|
+
body?: "none" | "status";
|
|
13
15
|
/**
|
|
14
16
|
* タグのラベルテキスト
|
|
15
17
|
* en: Label text displayed inside the tag
|
|
@@ -46,7 +48,7 @@ export interface TagProps extends React.ComponentProps<"div">, VariantProps<type
|
|
|
46
48
|
*
|
|
47
49
|
* @param {TagProps} props
|
|
48
50
|
*/
|
|
49
|
-
declare function Tag({ className, variant, size, status, children, ref, ...props }: TagProps): React.JSX.Element;
|
|
51
|
+
declare function Tag({ className, variant, size, status, body, children, ref, ...props }: TagProps): React.JSX.Element;
|
|
50
52
|
declare namespace Tag {
|
|
51
53
|
var displayName: string;
|
|
52
54
|
}
|
|
@@ -9,11 +9,11 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
import { cva } from "class-variance-authority";
|
|
14
14
|
import { cn } from "../../../lib/utils.js";
|
|
15
15
|
// タグのスタイル定義
|
|
16
|
-
const tagVariants = cva("inline-flex items-center justify-center rounded-
|
|
16
|
+
const tagVariants = cva("inline-flex items-center justify-center rounded-full h-fit min-w-0", {
|
|
17
17
|
variants: {
|
|
18
18
|
variant: {
|
|
19
19
|
solid: "",
|
|
@@ -21,9 +21,9 @@ const tagVariants = cva("inline-flex items-center justify-center rounded-notice
|
|
|
21
21
|
subtle: "",
|
|
22
22
|
},
|
|
23
23
|
size: {
|
|
24
|
-
sm: "py-
|
|
25
|
-
md: "py-
|
|
26
|
-
lg: "py-1 px-2 min-w-14 character-2-bold-pro",
|
|
24
|
+
sm: "min-h-5 py-1 px-1.5 min-w-10 character-1-bold-pro",
|
|
25
|
+
md: "min-h-6 py-1.5 px-2 min-w-12 character-1-bold-pro",
|
|
26
|
+
lg: "min-h-7 py-1.5 px-2 min-w-14 character-2-bold-pro",
|
|
27
27
|
},
|
|
28
28
|
status: {
|
|
29
29
|
neutral: "",
|
|
@@ -70,31 +70,31 @@ const tagVariants = cva("inline-flex items-center justify-center rounded-notice
|
|
|
70
70
|
{
|
|
71
71
|
variant: "outline",
|
|
72
72
|
status: "neutral",
|
|
73
|
-
className: "border-
|
|
73
|
+
className: "border-border-neutral-middle text-text-neutral-middle bg-surface-base-0",
|
|
74
74
|
},
|
|
75
75
|
// info + outline
|
|
76
76
|
{
|
|
77
77
|
variant: "outline",
|
|
78
78
|
status: "info",
|
|
79
|
-
className: "border-
|
|
79
|
+
className: "border-border-info text-text-info bg-surface-base-0",
|
|
80
80
|
},
|
|
81
81
|
// success + outline
|
|
82
82
|
{
|
|
83
83
|
variant: "outline",
|
|
84
84
|
status: "success",
|
|
85
|
-
className: "border-
|
|
85
|
+
className: "border-border-success text-text-success bg-surface-base-0",
|
|
86
86
|
},
|
|
87
87
|
// warning + outline
|
|
88
88
|
{
|
|
89
89
|
variant: "outline",
|
|
90
90
|
status: "warning",
|
|
91
|
-
className: "border-
|
|
91
|
+
className: "border-border-warning text-text-warning bg-surface-base-0",
|
|
92
92
|
},
|
|
93
93
|
// negative + outline
|
|
94
94
|
{
|
|
95
95
|
variant: "outline",
|
|
96
96
|
status: "negative",
|
|
97
|
-
className: "border-
|
|
97
|
+
className: "border-border-negative-high text-text-negative-enabled bg-surface-base-0",
|
|
98
98
|
},
|
|
99
99
|
// === SUBTLE バリアント ===
|
|
100
100
|
// neutral + subtle
|
|
@@ -165,8 +165,16 @@ const tagVariants = cva("inline-flex items-center justify-center rounded-notice
|
|
|
165
165
|
* @param {TagProps} props
|
|
166
166
|
*/
|
|
167
167
|
function Tag(_a) {
|
|
168
|
-
var { className, variant, size, status, children, ref } = _a, props = __rest(_a, ["className", "variant", "size", "status", "children", "ref"]);
|
|
169
|
-
return (
|
|
168
|
+
var { className, variant = "solid", size = "md", status = "neutral", body = "none", children, ref } = _a, props = __rest(_a, ["className", "variant", "size", "status", "body", "children", "ref"]);
|
|
169
|
+
return (_jsxs("div", Object.assign({ ref: ref, className: cn(tagVariants({ variant, size, status, className })) }, props, { children: [body === "status" && (_jsx("span", { "aria-hidden": "true", className: cn("flex size-2.5 shrink-0 items-center justify-center", size === "sm" ? "mr-0.5" : "mr-1"), children: _jsx("span", { className: cn("size-1.5 rounded-full", variant === "solid"
|
|
170
|
+
? "bg-object-inverse"
|
|
171
|
+
: {
|
|
172
|
+
neutral: "bg-object-neutral-middle",
|
|
173
|
+
info: "bg-object-info",
|
|
174
|
+
success: "bg-object-success",
|
|
175
|
+
warning: "bg-object-warning",
|
|
176
|
+
negative: "bg-object-negative-enabled",
|
|
177
|
+
}[status !== null && status !== void 0 ? status : "neutral"]) }) })), _jsx("span", { className: "min-w-0 truncate [text-box-trim:trim-both] [text-box-edge:cap_alphabetic]", children: children })] })));
|
|
170
178
|
}
|
|
171
179
|
Tag.displayName = "Tag";
|
|
172
180
|
export { Tag, tagVariants };
|
|
@@ -11,7 +11,7 @@ import { type VariantProps } from "class-variance-authority";
|
|
|
11
11
|
* - en: The Textarea component is used to capture user input in the form of multi-line text fields.
|
|
12
12
|
*/
|
|
13
13
|
declare const textareaVariants: (props?: ({
|
|
14
|
-
size?: "
|
|
14
|
+
size?: "md" | "lg" | null | undefined;
|
|
15
15
|
isInvalid?: boolean | null | undefined;
|
|
16
16
|
isDisabled?: boolean | null | undefined;
|
|
17
17
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
@@ -20,13 +20,12 @@ import { cn } from "../../../lib/utils.js";
|
|
|
20
20
|
*/
|
|
21
21
|
const textareaVariants = cva(
|
|
22
22
|
// ベーススタイル
|
|
23
|
-
"flex w-full rounded-action border bg-surface-base-0
|
|
23
|
+
"flex w-full rounded-action border bg-surface-base-0 pt-2 pb-1 ring-offset-background placeholder:text-text-neutral-low focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-border-ring focus-visible:ring-offset-2 resize", {
|
|
24
24
|
variants: {
|
|
25
|
-
// サイズバリアント(
|
|
25
|
+
// サイズバリアント(md, lg)
|
|
26
26
|
size: {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
lg: "min-h-[64px] character-4-regular-pro",
|
|
27
|
+
md: "min-h-32 px-3 character-2-regular-pro",
|
|
28
|
+
lg: "min-h-32 px-4 character-3-regular-pro",
|
|
30
29
|
},
|
|
31
30
|
// エラー状態のバリアント
|
|
32
31
|
isInvalid: {
|
|
@@ -42,7 +42,7 @@ import { IconButton } from "../../../components/ui/icon-button/index.js";
|
|
|
42
42
|
* @param {ToastProps} props
|
|
43
43
|
*/
|
|
44
44
|
export function Toast({ className, title, description, isCloseTrigger = true, id, }) {
|
|
45
|
-
return (_jsxs("div", { role: "status", className: cn("shadow-float px-3 py-
|
|
45
|
+
return (_jsxs("div", { role: "status", className: cn("shadow-float px-3 py-3 text-text-neutral-high flex w-[320px] rounded-notice gap-2 bg-surface-neutral-middle-enabled border border-border-neutral-middle", className), children: [_jsxs("div", { className: "h-full flex flex-col justify-center gap-0 px-1 grow", children: [title && (_jsx("p", { className: "character-3-bold-pro min-h-8 flex items-center", children: title })), _jsx("p", { className: "character-2-regular-pro min-h-8 flex items-center", children: description })] }), isCloseTrigger && (_jsx(IconButton, { icon: "close", size: "sm", variant: "ghost", theme: "neutral", "aria-label": "\u9589\u3058\u308B", onClick: () => {
|
|
46
46
|
sonnerToast.dismiss(id);
|
|
47
47
|
} }))] }));
|
|
48
48
|
}
|