`<wa-textarea>` に文字数カウント機能を追加

shoelace-style/webawesome

<wa-textarea>with-count 属性が追加され、テキストエリア下部に入力済み文字数または残り文字数を表示できるようになりました。スクリーンリーダー対応のライブリージョンと25言語以上の翻訳を含む、アクセシビリティファーストな実装です。

背景

文字数制限付きフォームにおける文字数カウンターは、ユーザーが自分で文字数を数えなければならない maxlength のネイティブ動作に比べて、はるかに優れたUXを提供します。#573 でこの機能が要望されており、文字数制限のあるフォームでカウンターを表示したいというニーズへの対応です。

Issue #573では「文字数制限があるフォームにカウンター機能があると非常に便利」という要望が寄せられており、今回のPRはその要望を受けた実装です。

技術的な変更

with-count 属性と LocalizeController の導入により、文字数表示とアクセシビリティ対応が実現されています。

textarea.ts では、with-count プロパティの追加とともに、LocalizeController をインポートして翻訳キー numCharacters / numCharactersRemaining を使ってカウントテキストを生成します。maxlength が設定されている場合は残り文字数(maxlength - value.length)を表示し、設定されていない場合は入力済み文字数(value.length)を表示します。

アクセシビリティのために announcedCountText という @state() プロパティと countAnnounceTimeout によるデバウンスが導入されています。ユーザーが入力するたびに即座にライブリージョンを更新するのではなく、一定時間後に遅延アナウンスすることで、スクリーンリーダーが過剰に読み上げるのを防いでいます。視覚的な表示と読み上げ用テキストを分離し、後者は visuallyHidden スタイルで非表示にした要素に格納しています。

スタイル面では textarea.styles.ts.footer クラスが追加されました。ヒントと文字数カウンターを横並びに配置するレイアウトです。

.footer {
  display: flex;
  align-items: baseline;
  gap: 1em;
}

.footer.has-count [part='hint'] {
  flex: 1 1 auto;
  min-width: 0;
}

.count {
  flex: 0 0 auto;
  color: var(--wa-form-control-hint-color);
  font-weight: var(--wa-form-control-hint-font-weight);
  line-height: var(--wa-form-control-hint-line-height);
  margin-block-start: 0.5em;
  font-size: var(--wa-font-size-smaller);
  margin-inline-start: auto;
}

ヒントが存在する場合、.has-count [part='hint']flex: 1 1 auto が適用され、ヒントテキストが利用可能なスペースを占有します。カウンター(.count)は flex: 0 0 auto で幅を固定し、margin-inline-start: auto によって右端に配置されます。カウンターのフォントスタイルはヒントと同一のCSS変数(--wa-form-control-hint-color など)を使用しており、視覚的な一貫性が保たれています。

翻訳ファイルには numCharactersnumCharactersRemaining の2つのキーが25言語以上に追加されました。言語ごとに複数形のルールが丁寧に実装されており、たとえばアラビア語(ar.ts)では0・1・2・3〜10・11以上の5段階、ロシア語(ru.ts)やポーランド語(pl.ts)では mod10/mod100 を用いたスラブ語族特有の複数形ロジックが組み込まれています。

設計判断

視覚表示とスクリーンリーダーへのアナウンスを分離した設計が採用されています。

[part='count'] として公開されたカウンター要素は視覚的なカウント表示を担い、別途 visuallyHidden な要素がライブリージョンとして機能します。視覚的なカウントをそのままライブリージョンに使う実装も考えられますが、デバウンスによる遅延アナウンスとの分離により、「表示はリアルタイム・読み上げは適切な頻度」という挙動を実現しています。

カウンターのスタイルにはコンポーネント固有の値ではなく、ヒントと共通の --wa-form-control-hint-* CSS変数が使われています。これにより、ヒントとカウンターの外観をテーマレベルで一括制御でき、コンポーネントの設定値を増やさずに済むトレードオフが選択されています。

まとめ

with-count 属性の追加は単純な文字数表示にとどまらず、スクリーンリーダー対応・多言語複数形ロジック・フレキシブルレイアウトを包含した実装です。ヒントとカウンターを同一フッター領域に共存させながら、翻訳システムに乗ることで25言語以上の即時対応を達成しており、コンポーネントの国際化基盤の成熟度が改めて示されています。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
1e9e995f

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
2回 (改善を経て承認)
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→セクション群(各論)→まとめ(結論)の3部構成が明確に適用されています。背景、技術詳細、設計判断の各セクションも適切に配置されています。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライト(```css:path/to/file.ts)およびGitHubのIssue/PRリンク記法([#573](URL))が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

Webコンポーネント開発に関する専門用語(ライブリージョン、デバウンス、LocalizeControllerなど)を前提としており、対象読者であるエンジニアに適した技術レベルです。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクション内が「総論→各論」で構成され、各段落はトピックセンテンスで始まっています。1段落1トピックの原則が守られ、段落長も適切です。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事に引用されているCSSコードブロックは、提供されたDiff内の`packages/webawesome/src/components/textarea/textarea.styles.ts`の変更内容と完全に一致しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`with-count`, `LocalizeController`, `visuallyHidden`, スラブ語族の複数形ロジックなど、PRのDiffから読み取れる技術用語を正確かつ適切に使用しています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

maxlengthの有無による表示切り替え、デバウンスによるスクリーンリーダー読み上げの最適化、CSS Flexboxによるレイアウト、多言語の複数形対応ロジックなど、技術的な説明はすべて正確で論理的です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張(Issue #573への言及、25言語以上の翻訳対応、アクセシビリティ設計など)は、PRのDescriptionやDiff内のコードで裏付けられており、ハルシネーションは検出されませんでした。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#2236)とIssue番号(#573)が正確に記載されています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトル「`<wa-textarea>` に文字数カウント機能を追加」は、PRのタイトル「Add `with-count` to `<wa-textarea>`」の内容を的確に反映しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

記事に含まれる情報はすべてPR内の情報に基づいており、サポート状況やリリース予定などのPR外の知識の捏造はありません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

変更が完了したPRとして、「〜が追加されました」のように過去形や完了形で適切に表現されており、時間表現の歪曲はありません。