Segmented Field Picker のトレーリングアイコンを軸揃えにした共通スタイル導入
リード文:<wa-time-input> と <wa-date-input> のクリア・展開ボタンが他のフォームコントロールと垂直軸で揃っていなかった問題を、共通スタイルモジュール segmented-field.styles.ts に集約して解決しました。この変更により、ボタンのヒット領域とフォーカスリングは維持しつつ、全ピッカーが同一のトレーリング軸に収まります。
背景
<wa-time-input> の時計トグルとクリアボタンは従来、個別に微調整されており、<wa-select> のチェブロンや <wa-input> のエンドスロットアイコンと比較して数ピクセル内側に位置していました。 その結果、同一行に混在させたときに右端がわずかにずれるという UI の不整合が発生していました。
この視覚的ずれは、ユーザーが複数のフォームコントロールを横並びで使用するシナリオで特に顕在化し、デザインの一貫性が損なわれる要因となっていました。 PR #2543 ではこの問題を根本的に解消し、フォーム全体の統一感を高めることが目的です。
結論として、トレーリング側の揃えを設計要件に据えることで、見た目の統一感が得られ、開発者は個別のピクセル調整から解放されます。
技術的な変更
新規追加された共通スタイルモジュール **segmented-field.styles.ts が、クリア・展開ボタンと開始/終了デコレーションスロットのレイアウトを一元管理します。** 主要な実装は以下の通りです。
+export default css`
+ /* ボタンは 0.25rem のパディングを保持し、マイナスのマージンでトレーリング端にオーバーハングさせます */
+ [part~='clear-button'],
+ [part~='expand-button'] {
+ flex: 0 0 auto;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ color: var(--wa-color-text-quiet);
+ font: inherit;
+ padding: 0.25em;
+ margin-inline-end: -0.25em;
+ border-radius: var(--wa-border-radius-s);
+ transition: color var(--wa-transition-fast);
+ }
+
+ /* 固定幅でアイコンを中央揃えし、スロット幅に依存しない軸揃えを実現 */
+ [part~='expand-button'] {
+ inline-size: 1.75em; /* expand glyph (1.25em) + 2×0.25em padding */
+ margin-inline-start: calc(var(--wa-form-control-padding-inline) - 0.125em);
+ }
+`;
このモジュールは、各ボタンに固定 **inline-size(expand: 1.75 em、clear: 1.5 em)を設定し、margin-inline-end: -0.25em によってパディングがトレーリング端にオーバーハングする設計です。** さらに --wa-form-control-padding-inline トークンに基づく間隔調整により、テーマやサイズ変更に対しても自動的に適応します。
<wa-time-input> コンポーネントはこのスタイルを組み込み、個別のボタン定義を削除しました。 具体的にはインポートと CSS 配列への追加が行われています。
@@
-import formControlStyles from '../../styles/component/form-control.styles.js';
+import formControlStyles from '../../styles/component/form-control.styles.js';
+import segmentedFieldStyles from '../../styles/component/segmented-field.styles.js';
@@
- static css = [sizeStyles, formControlStyles, styles];
+ static css = [sizeStyles, formControlStyles, segmentedFieldStyles, styles];
time-input.styles.ts からは従来のボタンスタイルが削除され、代わりに共通モジュールへの参照コメントが残されています。 これにより重複実装が排除され、保守性が向上します。
@@
- .clear-button,
- .expand-button {
- /* 従来の個別スタイル */
- ...
- }
+ /* Trailing buttons (.clear-button, .expand-button) と start/end スロットは
+ segmentedFieldStyles で共通化され、<wa-select> のトレーリング軸に合わせます */
視覚的揃えが壊れないことを保証するテストが追加されました。 iconCenterFromRight ヘルパーで対象アイコンの中心座標を取得し、<wa-select> の同軸アイコンと 2 px 未満の差で比較しています。
@@
+ const expandDelta = Math.abs(
+ iconCenterFromRight(time, '[part~="expand-icon"]') -
+ iconCenterFromRight(select, '[part~="expand-icon"]'),
+ );
+ const clearDelta = Math.abs(
+ iconCenterFromRight(time, '[part~="clear-button"]') -
+ iconCenterFromRight(select, '[part~="clear-button"]'),
+ );
+
+ expect(expandDelta, 'expand icon is off the select trailing axis').to.be.lessThan(2);
+ expect(clearDelta, 'clear button is off the select trailing axis').to.be.lessThan(2);
これらのテストは、<wa-select> と <wa-input> を基準(アンカー)とし、将来的なレイアウト変更が軸を逸脱しないようガードしています。
設計判断
トレーリングアフォーダンスのスタイルを共通モジュールに集約したことは、重複実装を排除し UI 整合性を強化する明確な設計選択です。 同一モジュールが <wa-time-input> と <wa-date-input> の両方で使用され、プロジェクト全体で一貫した配置が保証されます。
軸の基準を <wa-select> と <wa-input> に固定した点は、これらを「視覚的アンカー」として扱う設計判断を示しています。 テストでアンカーを比較対象とすることで、レイアウト回帰が自動的に検出される仕組みが導入されています。
結果として、UI の一貫性とコードベースの可読性・保守性が同時に向上し、将来的なテーマ追加やサイズ変更にも安定して対応できる基盤が整いました。
まとめ
本 PR は segmented-field.styles.ts にトレーリングボタンの共通レイアウトを実装し、<wa-time-input> と <wa-date-input> のアイコンを <wa-select> や <wa-input> と同一軸に揃えました。重複スタイルの除去とテストガードにより、見た目のずれが再発しない設計となり、テーマやサイズに依存しない安定した UI が提供されます。