Skip to content

♻️ refactor: 全コンポーネントを React 19 の ref-as-prop に移行(塩漬け)#274

Open
touyou wants to merge 3 commits into
mainfrom
fix/270-react19-ref-as-prop
Open

♻️ refactor: 全コンポーネントを React 19 の ref-as-prop に移行(塩漬け)#274
touyou wants to merge 3 commits into
mainfrom
fix/270-react19-ref-as-prop

Conversation

@touyou
Copy link
Copy Markdown
Member

@touyou touyou commented May 19, 2026

Summary

モチベーション

issue #270 のコメントで言及されている通り、Button は既に `function Button(props) { ... }` の React 19 流の書き方になっているが forwardRef を含めずに ref を受け取れない状態。shadcn/ui は 2024 年に forwardRef を全面廃止して ref-as-prop に移行済みで、sparkle-design もその流派なので素直に揃えるのが筋。

変更点

コンポーネント(全 11 ファイル)

  • Button / IconButton
  • Card 系(ClickableCard / Card / CardHeader / CardTitle / CardDescription / CardControl / CardContent / CardFooter
  • Input / Textarea / InputPassword
  • Spinner / Icon
  • Link / Divider
  • InlineMessage / InlineMessageTitle / InlineMessageDescription
  • Overlay / Tag / TabsTabsTrigger

すべて React.forwardRef<*, *>(({...}, ref) => ...)function X({ ref, ... }: XProps) に変換。基底型も React.HTMLAttributes<*> / React.*HTMLAttributes<*> から React.ComponentProps<\"*\"> に統一(ref を含む形)。

依存

  • react: `^18 || ^19` → `^19`
  • react-dom: `^18 || ^19` → `^19`
  • @types/react: `^18` → `^19`
  • @types/react-dom: `^18` → `^19`

CI 修正

  • pnpm.overrides(package.json)を pnpm-workspace.yamloverrides: に移行。pnpm 11 で pnpm.overrides フィールドが読まれなくなった影響で Vercel pnpm 10 と lockfile 不整合が発生していた問題を解消。

⚠️ Breaking Change(要レビュー判断)

ref-as-prop は React 19 ランタイム機能のため、React 18 では ref prop が剥がされて機能しません(試したところ ref forwarding テストが React 18 で落ちることを確認済み)。

そのため react の対応バージョンを `^19` 以上に絞っており、React 18 を使い続けている consumer はこの PR をマージすると ref forwarding が無言で壊れます

そこで本 PR は次の運用を想定しています:

  • そのままマージせず塩漬け
  • モーション系マージ等、他の大規模アップデートと同時にまとめてリリース
  • consumer 側(sparkle-design-internal 等)の React 19 移行と歩調を合わせる

issue #270 について

別途 main 基点で forwardRef で Button をラップするだけの小さい PR を切ります。そちらで issue #270 を React 18 互換のまま解決します。

Test plan

  • tsc --noEmit クリーン
  • vitest unit プロジェクト全 595 件 pass
  • prettier フォーマット OK
  • pnpm install --frozen-lockfile 通る
  • Vercel preview build 通る(push 後の自動 CI で確認)
  • Storybook で全コンポーネントの挙動を実機確認
  • consumer 側で React 19 環境を用意し、各コンポーネントに ref を直接渡せることを確認

🤖 Generated with Claude Code

- `React.forwardRef` を廃止し、ref を通常の prop として受け取る React 19 流に書き換え
- これにより Radix `Trigger asChild` 等から Button へ直接 ref を渡せるようになり、`sparkle-design-internal#182` の `PopoverTriggerButton` workaround が削除可能になる
- 前提として `@types/react`/`@types/react-dom` および `react`/`react-dom` を `^19` にバンプ(ref-as-prop は React 19 ランタイム機能のため)
- `ButtonProps` の `NativeButtonProps` を `React.ComponentPropsWithoutRef` → `React.ComponentProps` に変更
- `IconButtonProps` の base 型を `React.ButtonHTMLAttributes` → `React.ComponentProps<"button">` に変更

refs: #270

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 19, 2026 09:33
@vercel
Copy link
Copy Markdown

vercel Bot commented May 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
sparkle-design Ready Ready Preview, Comment May 19, 2026 9:51am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Review Change Stack

Walkthrough

多数の UI コンポーネントで props の基底型を React.ComponentProps 系に統一し、forwardRef ベースの実装を通常の関数コンポーネントに置換して ref を props から受け渡すようにした一括リファクタ。

Changes

forwardRef 廃止と ComponentProps への統一

Layer / File(s) Summary
Button の型・ref 受け渡し
src/components/ui/button/index.tsx
NativeButtonPropsComponentProps<"button"> に変更し、Button が props で ref を受け取りレンダリング要素へ ref={ref} を渡すように変更。
IconButton の forwardRef 廃止
src/components/ui/icon-button/index.tsx
IconButtonPropsComponentProps<"button"> に変更。forwardRef を廃止して関数コンポーネントで ref を受け渡す実装に置換(loading/disabled/アイコンロジックは維持)。
Card 系コンポーネントの置換
src/components/ui/card/index.tsx
ClickableCard / Card / CardHeader / CardTitle / CardDescription / CardControl / CardContent / CardFooter の基底型を ComponentProps 系にし、forwardRef 実装を関数コンポーネントへ置換。
Divider / Icon / Spinner / Tag の更新
src/components/ui/divider/*, src/components/ui/icon/*, src/components/ui/spinner/*, src/components/ui/tag/*
各コンポーネントの基底型を ComponentProps 系に切替え、forwardRef を廃止して ref を props から受け textarea/span/div 等へ渡す実装へ。
InlineMessage と子コンポーネント
src/components/ui/inline-message/index.tsx
InlineMessage, InlineMessageTitle, InlineMessageDescription を ComponentProps 系へ変更し、forwardRef を廃止。コンテキスト登録と aria 制御は維持。
Input 系(Input / InputPassword)
src/components/ui/input/*, src/components/ui/input-password/index.tsx
InputProps を Omit<React.ComponentProps<"input">, "size"> に変更。Input と InputPassword を forwardRef から関数コンポーネントへ置換し、ref を props で受けて useMergeRefs 等へ渡す構成に変更。
Link / TabsTrigger / Overlay の置換
src/components/ui/link/*, src/components/ui/tabs/*, src/components/ui/overlay/*
Link, TabsTrigger, Overlay の基底型を ComponentProps 系へ変更し、forwardRef を廃止。Link の asChild ロジックと icon 注入を再構成。
Textarea の置換
src/components/ui/textarea/index.tsx
TextareaProps を ComponentProps<"textarea"> に変更し、forwardRef 実装を通常関数へ置換。

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • goodpatch/sparkle-design#272: Input の ref/フォーカス処理を扱う改修が重複しており、useMergeRefs / focus 制御の観点でコードレベルの関連あり。

Poem

🐰✨ ぼくウサギが跳ねて祝うよ、
ref を受けて渡す道が整い、
forwardRef の森を抜けて、
ComponentProps の草原へ出たよ、
コンポーネントたち、軽やかに舞え!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed PR タイトルは「♻️ refactor: 全コンポーネントを React 19 の ref-as-prop に移行(塩漬け)」で、変更の主要内容を明確に表現している。forwardRef 廃止と ref-as-prop への統一という重要な変化が簡潔に記載されている。
Description check ✅ Passed PR 説明に「概要」「モチベーション」「変更点」「Breaking Change」「テスト結果」が含まれており、テンプレートの主要な記載項目を網羅している。React 19 への移行背景と塩漬け方針、各コンポーネントの変更内容が詳細に記載されている。
Linked Issues check ✅ Passed PR は issue #270 の目的「Button が ref を DOM に確実に渡せるようにすること」を達成している。React 19 の ref-as-prop パターンで ref forwarding を実現し、Radix asChild パターンとの合成を可能にした。全 11 ファイルの関連コンポーネントについても同様に対応している。
Out of Scope Changes check ✅ Passed 全ての変更は React 19 の ref-as-prop パターンへの統一という明確な目的に沿っており、pnpm.overrides の移行も依存関連の必要な修正である。scope 外の変更は検出されない。
Docstring Coverage ✅ Passed Docstring coverage is 86.96% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/270-react19-ref-as-prop
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch fix/270-react19-ref-as-prop

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 31a145c2cd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread pnpm-lock.yaml
Comment on lines 4 to 5
autoInstallPeers: true
excludeLinksFromLockfile: false
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore the pnpm overrides in the lockfile

With this lockfile, a clean CI/dev install using the normal frozen path fails before dependencies are installed because package.json still defines pnpm.overrides but the regenerated lockfile no longer records them; I verified pnpm install --frozen-lockfile exits with ERR_PNPM_LOCKFILE_CONFIG_MISMATCH. Please regenerate the lockfile with the repository's current pnpm configuration so the overrides block matches package.json.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/ui/icon-button/index.tsx`:
- Around line 389-420: The IconButton currently ignores the children prop when
asChild is true and always renders the internal Icon/Spinner and unconditional
attributes (type="button", disabled), breaking composition and semantics; update
the return logic in the IconButton component so that when asChild is true (Comp
= SlotPrimitive.Slot) you render children instead of the internal Icon/Spinner
and ensure ref and className are composed onto the child via Slot, and only
apply type="button", disabled and button-specific event suppression (e.g.,
prevent clicks when disabled) when Comp is the native "button"; keep using
iconButtonVariants, isIconButtonDisabled and props spreading for other
attributes but conditionally omit button-only attributes when asChild is used.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bbb8035f-40f7-46be-86e8-b48b8a7af9ef

📥 Commits

Reviewing files that changed from the base of the PR and between f57d11a and 31a145c.

⛔ Files ignored due to path filters (2)
  • package.json is excluded by !**/*.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !**/*.yaml
📒 Files selected for processing (2)
  • src/components/ui/button/index.tsx
  • src/components/ui/icon-button/index.tsx

Comment on lines +389 to +420
const Comp = asChild ? SlotPrimitive.Slot : "button";

// アイコンのサイズをボタンサイズに合わせて設定
const getIconSize = () => {
switch (size) {
case "xs":
return 3;
case "sm":
return 5;
case "lg":
return 7;
default:
return 6;
}
};
// アイコンのサイズをボタンサイズに合わせて設定
const getIconSize = () => {
switch (size) {
case "xs":
return 3;
case "sm":
return 5;
case "lg":
return 7;
default:
return 6;
}
};

return (
<Comp
type="button"
className={cn(
iconButtonVariants({
variant,
size,
theme,
isLoading,
isDisabled,
className,
})
)}
ref={ref}
disabled={isIconButtonDisabled}
{...props}
>
{isLoading ? (
<>
<Spinner size={getIconSize()} className="text-current" />
</>
) : (
<Icon icon={icon} size={getIconSize()} />
)}
</Comp>
);
}
);
return (
<Comp
ref={ref}
type="button"
className={cn(
iconButtonVariants({
variant,
size,
theme,
isLoading,
isDisabled,
className,
})
)}
disabled={isIconButtonDisabled}
{...props}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

wc -l src/components/ui/icon-button/index.tsx

Repository: goodpatch/sparkle-design

Length of output: 112


🏁 Script executed:

cat -n src/components/ui/icon-button/index.tsx | sed -n '290,310p'

Repository: goodpatch/sparkle-design

Length of output: 686


🏁 Script executed:

cat -n src/components/ui/icon-button/index.tsx | sed -n '355,435p'

Repository: goodpatch/sparkle-design

Length of output: 2347


asChild の合成が成立していません。

children プロップは分割代入されていますが(line 372)、return 内で一度も描画されていません。代わりに <Icon> / <Spinner> のみが常にレンダリングされるため、<IconButton asChild><a href="..." /></IconButton> のような使用時に、caller が提供した要素は DOM に含まれず、ref や className も合成されません。また type="button"disabled も無条件に Comp へ渡されるため、非 button 要素とのスロット合成ではセマンティクスが崩れます。Button コンポーネントと同様に asChild 時は children を描画する分岐を追加し、typedisabled・イベント抑止を条件分けしてください。

修正イメージ
   return (
     <Comp
       ref={ref}
-      type="button"
+      type={asChild ? undefined : "button"}
+      aria-busy={isLoading || undefined}
+      aria-disabled={asChild && isIconButtonDisabled ? true : undefined}
       className={cn(
         iconButtonVariants({
           variant,
           size,
           theme,
           isLoading,
           isDisabled,
           className,
         })
       )}
-      disabled={isIconButtonDisabled}
+      disabled={asChild ? undefined : isIconButtonDisabled}
       {...props}
     >
-      {isLoading ? (
+      {asChild ? (
+        children
+      ) : isLoading ? (
         <>
           <Spinner size={getIconSize()} className="text-current" />
         </>
       ) : (
         <Icon icon={icon} size={getIconSize()} />
       )}
     </Comp>
   );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ui/icon-button/index.tsx` around lines 389 - 420, The
IconButton currently ignores the children prop when asChild is true and always
renders the internal Icon/Spinner and unconditional attributes (type="button",
disabled), breaking composition and semantics; update the return logic in the
IconButton component so that when asChild is true (Comp = SlotPrimitive.Slot)
you render children instead of the internal Icon/Spinner and ensure ref and
className are composed onto the child via Slot, and only apply type="button",
disabled and button-specific event suppression (e.g., prevent clicks when
disabled) when Comp is the native "button"; keep using iconButtonVariants,
isIconButtonDisabled and props spreading for other attributes but conditionally
omit button-only attributes when asChild is used.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

React 19 の ref-as-prop パターンへ移行することで、Button / IconButton を Radix の asChild 合成などでより自然に ref 連携できるようにしつつ、React/型定義を React 19 系に揃える PR です。

Changes:

  • Button の props 型を React.ComponentProps<"button"> ベースに変更し、ref を props として受け取って内部要素へ渡すように更新
  • IconButtonReact.forwardRef から ref-as-prop の関数コンポーネントへ移行
  • react / react-dom / @types/react / @types/react-dom^19 に更新

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/components/ui/button/index.tsx ref を props で受けて <Comp> に渡す形へ型と実装を更新
src/components/ui/icon-button/index.tsx forwardRef を廃止し ref-as-prop 化(ただし asChild の子要素取り扱いに不具合あり)
package.json React 本体・型定義を ^19 にバンプし、React 18 サポートを終了

Comment on lines +369 to +373
disabled,
icon,
ref,
children,
...props
touyou and others added 2 commits May 19, 2026 18:49
- Card 系(ClickableCard / Card / CardHeader / CardTitle / CardDescription / CardControl / CardContent / CardFooter)
- Input / Textarea / InputPassword
- Spinner / Icon
- Link / Divider
- InlineMessage / InlineMessageTitle / InlineMessageDescription
- Overlay / Tag / Tabs (TabsTrigger)

すべての `React.forwardRef` を廃止し、ref を通常の prop として受け取る形式に変換。
基底型も `React.HTMLAttributes<*>` / `React.*HTMLAttributes<*>` から `React.ComponentProps<"*">` に統一して、ref を含む形に揃えた。

これで sparkle-design 全体が shadcn/ui 流派の React 19 ref-as-prop パターンに揃う。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pnpm 11 で `pnpm.overrides` フィールドが package.json から読まれなくなったため、
推奨形式である pnpm-workspace.yaml の overrides フィールドに移行。

これにより ローカル pnpm 11 と Vercel pnpm 10 の間で lockfile 整合性が取れず、
`ERR_PNPM_LOCKFILE_CONFIG_MISMATCH` で CI が落ちていた問題を解消する。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@touyou touyou changed the title ♻️ refactor: Button/IconButton を React 19 の ref-as-prop に移行 (#270) ♻️ refactor: 全コンポーネントを React 19 の ref-as-prop に移行(塩漬け) May 19, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
src/components/ui/input-password/index.tsx (1)

35-42: 💤 Low value

インラインコメントに英語訳が不足しています

コーディングガイドラインでは、インラインコメントは「日本語の後に en: プレフィックス付きで英語訳を記載する」形式が求められています。

例:

-  // パスワードの表示状態を管理
+  // パスワードの表示状態を管理 en: Manage password visibility state
   const [isVisibility, setIsVisibility] = React.useState(false);

-  // パスワード表示切り替えハンドラー
+  // パスワード表示切り替えハンドラー en: Password visibility toggle handler
   const handleTogglePasswordVisibility = React.useCallback(() => {

As per coding guidelines: "Write inline code comments in the format: Japanese description followed by en: prefix and English translation"

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ui/input-password/index.tsx` around lines 35 - 42, Update the
inline comments inside the InputPassword component to include English
translations using the required format: keep the existing Japanese comment and
append an English translation prefixed with "en:" for each comment (e.g., the
comment above the isVisibility state and the comment above
handleTogglePasswordVisibility). Locate the comments in the function
InputPassword and adjust them to follow the guideline "Japanese description
followed by `en:` and the English translation" so both comments (for
isVisibility and handleTogglePasswordVisibility) comply.
src/components/ui/input/index.tsx (1)

217-328: 💤 Low value

インラインコメントに英語訳を追加することを推奨します

このファイル内の多くのインラインコメント(例: Line 217 // 状態管理、Line 221、Line 224 など)が日本語のみで記載されています。コーディングガイドラインでは en: プレフィックス付きの英語訳を含める形式が求められています。

例:

-  // 状態管理
+  // 状態管理 en: State management
   const [isInputFocused, setIsInputFocused] = React.useState(false);

本PRの主目的はref移行のため、この修正は別PRでまとめて対応しても問題ありません。

As per coding guidelines: "Inline code comments within components must use Japanese followed by en: prefix with English translation"

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ui/input/index.tsx` around lines 217 - 328, Many inline
comments in this component are only in Japanese; update them to include an
English translation prefixed with "en:" (e.g., "状態管理 // en: state management").
Locate comments around the state and handlers such as the
isInputFocused/isIconButtonFocused declarations, handleChange, handleInputFocus,
handleInputBlur, handleIconButtonFocus, handleIconButtonBlur,
handleContainerClick, the useEffect outside click handler (handleOutsideClick),
and iconButtonSize memo, and append concise English translations after the
Japanese text using the `en:` prefix. You can do this in a follow-up PR if
preferred per the note in the review; keep translations short and consistent
with existing Japanese comments.
src/components/ui/textarea/index.tsx (1)

69-69: コーディングガイドラインと React 19 パターンの不一致を確認

en: Verify coding guideline vs React 19 pattern mismatch

コーディングガイドラインでは React.ComponentPropsWithoutRef<> を拡張するよう指定されていますが、このコードでは React.ComponentProps<"textarea"> (= ComponentPropsWithRef) を使用しています。

en: The coding guideline specifies extending React.ComponentPropsWithoutRef<>, but this code uses React.ComponentProps<"textarea"> (= ComponentPropsWithRef).

ただし、これは React 19 の ref-as-prop パターンに必要な変更です。ComponentPropsWithoutRef を使用すると、ref が型に含まれず、Line 103 での ref の分割代入と Line 121 での ref の受け渡しが TypeScript エラーになります。

en: However, this is a necessary change for React 19's ref-as-prop pattern. Using ComponentPropsWithoutRef would exclude ref from the type, causing TypeScript errors at line 103 (destructuring ref) and line 121 (passing ref).

推奨事項 / Recommendation: React 19 への移行に伴い、コーディングガイドラインを更新して React.ComponentProps<> または React.ComponentPropsWithRef<> の使用を推奨することを検討してください。また、React.forwardRef の使用に関する記述も React 19 では非推奨になったため、更新が必要です。

en: Consider updating the coding guidelines to recommend React.ComponentProps<> or React.ComponentPropsWithRef<> for React 19 migration. Also update the guidance about React.forwardRef as it's deprecated in React 19.

As per coding guidelines: "Use consistent TypeScript component interface patterns extending React.ComponentPropsWithoutRef<> and VariantProps" and "Use React.forwardRef for proper ref forwarding in components" - noting these guidelines appear to be based on React 18 patterns and may need updating for React 19.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ui/textarea/index.tsx` at line 69, The component's props
extend React.ComponentProps<"textarea"> (which includes ref) while the project
guideline demands React.ComponentPropsWithoutRef<>, causing a guideline
mismatch; update either the code or the guideline: if staying on React 19
ref-as-prop pattern keep React.ComponentProps<"textarea"> or explicitly use
React.ComponentPropsWithRef<"textarea"> to type the props (so the destructured
ref and the ref prop you pass through compile), and update any docs about using
React.forwardRef (now deprecated in React 19) to reflect the new ref-as-prop
pattern; adjust the type declaration replacing ComponentPropsWithoutRef<> with
ComponentProps<>/ComponentPropsWithRef<> and ensure the ref destructuring and
propagation sites use the matching prop name and type.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/components/ui/input-password/index.tsx`:
- Around line 35-42: Update the inline comments inside the InputPassword
component to include English translations using the required format: keep the
existing Japanese comment and append an English translation prefixed with "en:"
for each comment (e.g., the comment above the isVisibility state and the comment
above handleTogglePasswordVisibility). Locate the comments in the function
InputPassword and adjust them to follow the guideline "Japanese description
followed by `en:` and the English translation" so both comments (for
isVisibility and handleTogglePasswordVisibility) comply.

In `@src/components/ui/input/index.tsx`:
- Around line 217-328: Many inline comments in this component are only in
Japanese; update them to include an English translation prefixed with "en:"
(e.g., "状態管理 // en: state management"). Locate comments around the state and
handlers such as the isInputFocused/isIconButtonFocused declarations,
handleChange, handleInputFocus, handleInputBlur, handleIconButtonFocus,
handleIconButtonBlur, handleContainerClick, the useEffect outside click handler
(handleOutsideClick), and iconButtonSize memo, and append concise English
translations after the Japanese text using the `en:` prefix. You can do this in
a follow-up PR if preferred per the note in the review; keep translations short
and consistent with existing Japanese comments.

In `@src/components/ui/textarea/index.tsx`:
- Line 69: The component's props extend React.ComponentProps<"textarea"> (which
includes ref) while the project guideline demands
React.ComponentPropsWithoutRef<>, causing a guideline mismatch; update either
the code or the guideline: if staying on React 19 ref-as-prop pattern keep
React.ComponentProps<"textarea"> or explicitly use
React.ComponentPropsWithRef<"textarea"> to type the props (so the destructured
ref and the ref prop you pass through compile), and update any docs about using
React.forwardRef (now deprecated in React 19) to reflect the new ref-as-prop
pattern; adjust the type declaration replacing ComponentPropsWithoutRef<> with
ComponentProps<>/ComponentPropsWithRef<> and ensure the ref destructuring and
propagation sites use the matching prop name and type.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7a7209c4-1a3a-44b7-92dc-10c1e6b647be

📥 Commits

Reviewing files that changed from the base of the PR and between 31a145c and a20e466.

⛔ Files ignored due to path filters (3)
  • package.json is excluded by !**/*.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !**/*.yaml
  • pnpm-workspace.yaml is excluded by !**/*.yaml
📒 Files selected for processing (12)
  • src/components/ui/card/index.tsx
  • src/components/ui/divider/index.tsx
  • src/components/ui/icon/index.tsx
  • src/components/ui/inline-message/index.tsx
  • src/components/ui/input-password/index.tsx
  • src/components/ui/input/index.tsx
  • src/components/ui/link/index.tsx
  • src/components/ui/overlay/index.tsx
  • src/components/ui/spinner/index.tsx
  • src/components/ui/tabs/index.tsx
  • src/components/ui/tag/index.tsx
  • src/components/ui/textarea/index.tsx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants