leaf-multiple オプションで <wa-tree> の葉ノード複数選択を実現
このPRは <wa-tree> コンポーネントに leaf-multiple という新しい selection オプションを追加し、葉ノードの複数選択を可能にしつつ、親ノードは展開・折りたたみだけに限定します。これにより、ツリー構造の UI で「親は操作対象外、子は自由に選択できる」ユースケースをシンプルに実装できます。
背景
従来の <wa-tree> は single、multiple、leaf の三種の selection 挙動しか提供しておらず、葉ノードのみを対象にした複数選択は実装できませんでした。leaf モードは葉の単一選択に留まり、multiple は親も含めて全ノードが選択対象になるため、用途が限定されていました。
leaf-multiple の導入は、Issue #1989 で報告された「葉ノードだけを複数選択したい」要望に直接応えるものです。親ノードは従来通り展開/折りたたみのトリガーに留め、選択ロジックを分離することで UI の一貫性を保ちます。
技術的な変更
API拡張
selection プロパティに新たなリテラル 'leaf-multiple' が加えられ、型定義が 'single' | 'multiple' | 'leaf' | 'leaf-multiple' に拡張されました。デフォルトは従来通り 'single' のままで、既存の使用コードに影響を与えません。
@@ -83,8 +83,9 @@ export default class WaTree extends WebAwesomeElement {
* displays checkboxes and allows more than one node to be selected. Leaf allows only leaf nodes to be selected.
+ * Leaf-multiple allows multiple leaf nodes to be selected while parent nodes only expand and collapse.
*/
- @property() selection: 'single' | 'multiple' | 'leaf' = 'single';
+ @property() selection: 'single' | 'multiple' | 'leaf' | 'leaf-multiple' = 'single';
この変更により、開発者は <wa-tree selection="leaf-multiple"> と記述するだけで新機能を利用できます。
ツリ項目の初期化ロジック変更
initTreeItem で各 wa-tree-item の selectable フラグが設定されるロジックが拡張され、leaf-multiple 時は葉ノードだけが選択可能になります。これにより、親ノードはクリック時に選択状態にならず、展開操作だけが行われます。
@@ -149,7 +150,7 @@ export default class WaTree extends WebAwesomeElement {
private initTreeItem = (item: WaTreeItem) => {
item.updateComplete.then(() => {
- item.selectable = this.selection === 'multiple';
+ item.selectable = this.selection === 'multiple' || (this.selection === 'leaf-multiple' && item.isLeaf);
結果として、leaf-multiple モードでは UI が自動的に葉ノードのみチェック可能であることを保証します。
選択処理の分岐追加
selectItem メソッドに leaf-multiple 用の分岐が挿入され、葉ノードは選択状態をトグルし、親ノードは expanded プロパティだけを切り替えるようになりました。これにより、ユーザーが Enter キーやクリックで親ノードを操作したときに選択が付与されることはありません。
@@ -194,6 +195,12 @@ export default class WaTree extends WebAwesomeElement {
syncCheckboxes(selectedItem);
+ } else if (this.selection === 'leaf-multiple') {
+ if (selectedItem.isLeaf) {
+ selectedItem.selected = !selectedItem.selected;
+ } else {
+ selectedItem.expanded = !selectedItem.expanded;
+ }
} else if (this.selection === 'single' || selectedItem.isLeaf) {
このロジックはテストで検証され、親ノードの展開と葉ノードの独立した選択が正しく動作することが保証されています。
ARIA属性と選択可能フラグの同期
handleSelectionChange が leaf-multiple を判定対象に加え、aria-multiselectable を true に設定すると同時に、全アイテムの selectable フラグを更新します。ARIA の適切な設定により、支援技術が複数選択可能なツリーであることを認識できます。
@@ -361,13 +368,14 @@ export default class WaTree extends WebAwesomeElement {
@watch('selection')
async handleSelectionChange() {
const isSelectionMultiple = this.selection === 'multiple';
+ const isSelectionLeafMultiple = this.selection === 'leaf-multiple';
const items = this.getAllTreeItems();
- this.setAttribute('aria-multiselectable', isSelectionMultiple ? 'true' : 'false');
+ this.setAttribute('aria-multiselectable', isSelectionMultiple || isSelectionLeafMultiple ? 'true' : 'false');
for (const item of items) {
item.updateComplete.then(() => {
- item.selectable = isSelectionMultiple;
+ item.selectable = isSelectionMultiple || (isSelectionLeafMultiple && item.isLeaf);
});
}
この変更により、ARIA の意味論的な一貫性が保たれ、アクセシビリティ要件を満たす形で新機能が提供されます。
テストの追加
tree.test.ts には leaf-multiple 動作を検証するテストが 4 つ追加されました。代表的なテストは、葉ノードだけが selectable になること、複数葉ノードが独立して選択できること、親ノードが選択されずに展開だけが行われることを確認しています。
@@ -67,6 +67,18 @@ describe('<wa-tree>', () => {
}
});
+ it('should set selectable on leaf items only when selection is "leaf-multiple"', async () => {
+ el.selection = 'leaf-multiple';
+ await el.updateComplete;
+
+ const items = el.querySelectorAll<WaTreeItem>('wa-tree-item');
+ await Promise.all([...items].map(item => item.updateComplete));
+
+ for (const item of items) {
+ expect(item.selectable).to.equal(item.isLeaf);
+ }
+ });
これらのテストにより、実装が期待通りの振る舞いを示すことが CI で自動的に保証されます。
設計判断
leaf-multiple を新たなリテラルとして selection 列挙型に組み込んだ設計は、既存の API を拡張しつつ後方互換性を最大化する選択です。別属性を導入するとコンポーネントのプロパティが増え、使用側の学習コストが上がりますが、今回のアプローチは「選択モードは一元管理」という一貫性を保ちます。
また、ARIA の aria-multiselectable フラグや selectable プロパティの更新ロジックを共通化したことで、機能追加による分岐増加を最小限に抑えつつ、アクセシビリティ要件も満たすバランスが取れています。テストを通じた振る舞いの明示は、将来の拡張やリファクタリング時の安全性を高める設計上の利点です。
まとめ
leaf-multiple の導入により、開発者は <wa-tree> で「葉だけの複数選択」機能をシンプルに利用でき、既存コードへの影響はなく、アクセシビリティも維持された形で UI の表現力が向上します。