diff --git a/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/Mobile-Chrome/expander-initial.png b/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/Mobile-Chrome/expander-initial.png new file mode 100644 index 000000000..255710bf3 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/Mobile-Chrome/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/Mobile-Safari/expander-initial.png b/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/Mobile-Safari/expander-initial.png new file mode 100644 index 000000000..3bac197ad Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/Mobile-Safari/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/chromium/expander-initial.png b/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/chromium/expander-initial.png new file mode 100644 index 000000000..53886cada Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/chromium/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/firefox/expander-initial.png b/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/firefox/expander-initial.png new file mode 100644 index 000000000..ff581d6bc Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/firefox/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/webkit/expander-initial.png b/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/webkit/expander-initial.png new file mode 100644 index 000000000..3bac197ad Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Button-Alignment-Behaviour/darwin/webkit/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/Mobile-Chrome/expander-initial.png b/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/Mobile-Chrome/expander-initial.png new file mode 100644 index 000000000..bf741406e Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/Mobile-Chrome/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/Mobile-Safari/expander-initial.png b/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/Mobile-Safari/expander-initial.png new file mode 100644 index 000000000..785b21ced Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/Mobile-Safari/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/chromium/expander-initial.png b/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/chromium/expander-initial.png new file mode 100644 index 000000000..042a62fbd Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/chromium/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/firefox/expander-initial.png b/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/firefox/expander-initial.png new file mode 100644 index 000000000..46a2c6f81 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/firefox/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/webkit/expander-initial.png b/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/webkit/expander-initial.png new file mode 100644 index 000000000..20973c5e8 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Disabled-Behaviour/darwin/webkit/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/Mobile-Chrome/expander-initial.png b/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/Mobile-Chrome/expander-initial.png new file mode 100644 index 000000000..bfe242074 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/Mobile-Chrome/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/Mobile-Safari/expander-initial.png b/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/Mobile-Safari/expander-initial.png new file mode 100644 index 000000000..de6e904fa Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/Mobile-Safari/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/chromium/expander-initial.png b/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/chromium/expander-initial.png new file mode 100644 index 000000000..a91f3b431 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/chromium/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/firefox/expander-initial.png b/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/firefox/expander-initial.png new file mode 100644 index 000000000..5c447c3aa Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/firefox/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/webkit/expander-initial.png b/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/webkit/expander-initial.png new file mode 100644 index 000000000..1a421bb75 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expand-Slotted-Icon-Behaviour/darwin/webkit/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/Mobile-Chrome/expander-closed.png b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/Mobile-Chrome/expander-closed.png new file mode 100644 index 000000000..21d2c086b Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/Mobile-Chrome/expander-closed.png differ diff --git a/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/Mobile-Chrome/expander-initial.png b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/Mobile-Chrome/expander-initial.png new file mode 100644 index 000000000..cc3b226e7 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/Mobile-Chrome/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/Mobile-Safari/expander-closed.png b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/Mobile-Safari/expander-closed.png new file mode 100644 index 000000000..202b11219 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/Mobile-Safari/expander-closed.png differ diff --git a/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/Mobile-Safari/expander-initial.png b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/Mobile-Safari/expander-initial.png new file mode 100644 index 000000000..f47c012c6 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/Mobile-Safari/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/chromium/expander-closed.png b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/chromium/expander-closed.png new file mode 100644 index 000000000..f85a7c0b5 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/chromium/expander-closed.png differ diff --git a/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/chromium/expander-initial.png b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/chromium/expander-initial.png new file mode 100644 index 000000000..69ebb494e Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/chromium/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/firefox/expander-closed.png b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/firefox/expander-closed.png new file mode 100644 index 000000000..216166df9 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/firefox/expander-closed.png differ diff --git a/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/firefox/expander-initial.png b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/firefox/expander-initial.png new file mode 100644 index 000000000..af3326e26 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/firefox/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/webkit/expander-closed.png b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/webkit/expander-closed.png new file mode 100644 index 000000000..9bebee5bd Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/webkit/expander-closed.png differ diff --git a/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/webkit/expander-initial.png b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/webkit/expander-initial.png new file mode 100644 index 000000000..89897a21c Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Expanded-Behaviour/darwin/webkit/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/Mobile-Chrome/expander-initial.png b/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/Mobile-Chrome/expander-initial.png new file mode 100644 index 000000000..98c75607b Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/Mobile-Chrome/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/Mobile-Safari/expander-initial.png b/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/Mobile-Safari/expander-initial.png new file mode 100644 index 000000000..ef117bcd8 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/Mobile-Safari/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/chromium/expander-initial.png b/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/chromium/expander-initial.png new file mode 100644 index 000000000..eb1bb8509 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/chromium/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/firefox/expander-initial.png b/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/firefox/expander-initial.png new file mode 100644 index 000000000..9c61b5bfe Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/firefox/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/webkit/expander-initial.png b/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/webkit/expander-initial.png new file mode 100644 index 000000000..d797789df Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Header-Slotted-Icon-Behaviour/darwin/webkit/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-expanded.png b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-expanded.png new file mode 100644 index 000000000..103e89258 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-initial.png b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-initial.png new file mode 100644 index 000000000..4941e59d9 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/Mobile-Safari/expander-expanded.png b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/Mobile-Safari/expander-expanded.png new file mode 100644 index 000000000..55fb070a7 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/Mobile-Safari/expander-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/Mobile-Safari/expander-initial.png b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/Mobile-Safari/expander-initial.png new file mode 100644 index 000000000..1c28308c1 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/Mobile-Safari/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/chromium/expander-expanded.png b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/chromium/expander-expanded.png new file mode 100644 index 000000000..c99cff1a5 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/chromium/expander-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/chromium/expander-initial.png b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/chromium/expander-initial.png new file mode 100644 index 000000000..ef07d95f5 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/chromium/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/firefox/expander-expanded.png b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/firefox/expander-expanded.png new file mode 100644 index 000000000..321a89ac0 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/firefox/expander-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/firefox/expander-initial.png b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/firefox/expander-initial.png new file mode 100644 index 000000000..19d9763db Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/firefox/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/webkit/expander-expanded.png b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/webkit/expander-expanded.png new file mode 100644 index 000000000..6e456049a Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/webkit/expander-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/webkit/expander-initial.png b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/webkit/expander-initial.png new file mode 100644 index 000000000..4a8a8a2f8 Binary files /dev/null and b/.tooling/tests/screenshots/Expander---Visual-and-Behaviour/darwin/webkit/expander-initial.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/Mobile-Chrome/expander-group-both-expanded.png b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/Mobile-Chrome/expander-group-both-expanded.png new file mode 100644 index 000000000..0daa1316f Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/Mobile-Chrome/expander-group-both-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/Mobile-Chrome/expander-group-expanded.png b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/Mobile-Chrome/expander-group-expanded.png new file mode 100644 index 000000000..86c3e654e Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/Mobile-Chrome/expander-group-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/Mobile-Safari/expander-group-both-expanded.png b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/Mobile-Safari/expander-group-both-expanded.png new file mode 100644 index 000000000..058d2f0e1 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/Mobile-Safari/expander-group-both-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/Mobile-Safari/expander-group-expanded.png b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/Mobile-Safari/expander-group-expanded.png new file mode 100644 index 000000000..c6c01a76b Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/Mobile-Safari/expander-group-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/chromium/expander-group-both-expanded.png b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/chromium/expander-group-both-expanded.png new file mode 100644 index 000000000..f4454ddb2 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/chromium/expander-group-both-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/chromium/expander-group-expanded.png b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/chromium/expander-group-expanded.png new file mode 100644 index 000000000..5609da92a Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/chromium/expander-group-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/firefox/expander-group-both-expanded.png b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/firefox/expander-group-both-expanded.png new file mode 100644 index 000000000..4e391930a Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/firefox/expander-group-both-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/firefox/expander-group-expanded.png b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/firefox/expander-group-expanded.png new file mode 100644 index 000000000..c5bb7ed7c Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/firefox/expander-group-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/webkit/expander-group-both-expanded.png b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/webkit/expander-group-both-expanded.png new file mode 100644 index 000000000..5cf4bd439 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/webkit/expander-group-both-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/webkit/expander-group-expanded.png b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/webkit/expander-group-expanded.png new file mode 100644 index 000000000..f75c40919 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Expand-Mode-Behaviour/darwin/webkit/expander-group-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-group-expanded.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-group-expanded.png new file mode 100644 index 000000000..5b91558e6 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-group-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-group-initial.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-group-initial.png new file mode 100644 index 000000000..f9b208894 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-group-initial.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-group-second-expanded.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-group-second-expanded.png new file mode 100644 index 000000000..c9540b713 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Chrome/expander-group-second-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Safari/expander-group-expanded.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Safari/expander-group-expanded.png new file mode 100644 index 000000000..713bf042a Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Safari/expander-group-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Safari/expander-group-initial.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Safari/expander-group-initial.png new file mode 100644 index 000000000..8cf14a54f Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Safari/expander-group-initial.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Safari/expander-group-second-expanded.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Safari/expander-group-second-expanded.png new file mode 100644 index 000000000..516465591 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/Mobile-Safari/expander-group-second-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/chromium/expander-group-expanded.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/chromium/expander-group-expanded.png new file mode 100644 index 000000000..5cd52e7e7 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/chromium/expander-group-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/chromium/expander-group-initial.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/chromium/expander-group-initial.png new file mode 100644 index 000000000..dd5854019 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/chromium/expander-group-initial.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/chromium/expander-group-second-expanded.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/chromium/expander-group-second-expanded.png new file mode 100644 index 000000000..52b8728b4 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/chromium/expander-group-second-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/firefox/expander-group-expanded.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/firefox/expander-group-expanded.png new file mode 100644 index 000000000..6a09423aa Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/firefox/expander-group-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/firefox/expander-group-initial.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/firefox/expander-group-initial.png new file mode 100644 index 000000000..ae6bc199e Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/firefox/expander-group-initial.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/firefox/expander-group-second-expanded.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/firefox/expander-group-second-expanded.png new file mode 100644 index 000000000..8322018e3 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/firefox/expander-group-second-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/webkit/expander-group-expanded.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/webkit/expander-group-expanded.png new file mode 100644 index 000000000..fdaaf5de6 Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/webkit/expander-group-expanded.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/webkit/expander-group-initial.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/webkit/expander-group-initial.png new file mode 100644 index 000000000..236196ecf Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/webkit/expander-group-initial.png differ diff --git a/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/webkit/expander-group-second-expanded.png b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/webkit/expander-group-second-expanded.png new file mode 100644 index 000000000..fd178ae6a Binary files /dev/null and b/.tooling/tests/screenshots/Expander-Group---Visual-and-Behaviour/darwin/webkit/expander-group-second-expanded.png differ diff --git a/.vscode/settings.json b/.vscode/settings.json index d1d050a7f..bccd66c07 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -45,6 +45,7 @@ "modal": true, "tab": true, "toast": true, - "alert": true + "alert": true, + "expander": true } } \ No newline at end of file diff --git a/README.md b/README.md index 73e2ef4a8..f280a8912 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ This example shows how to import and use a few common components. Omni Component
Tag NameDescription
-[omni-loading-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-loading-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -191,7 +191,7 @@ Loading icon component.
-[omni-render-element](/Users/runner/work/omni-components/omni-components/src/render-element/README.md) +[omni-render-element](/Users/cp340150/code/omni-components/omni-components/src/render-element/README.md) @@ -199,7 +199,7 @@ Element that defers content rendering to a provided function / promise.
-[omni-modal](/Users/runner/work/omni-components/omni-components/src/modal/README.md) +[omni-modal](/Users/cp340150/code/omni-components/omni-components/src/modal/README.md) @@ -207,7 +207,7 @@ Control to display modal content with optional header and footer content.
-[omni-button](/Users/runner/work/omni-components/omni-components/src/button/README.md) +[omni-button](/Users/cp340150/code/omni-components/omni-components/src/button/README.md) @@ -215,7 +215,7 @@ Control that allows an action to be executed.
-[omni-alert](/Users/runner/work/omni-components/omni-components/src/alert/README.md) +[omni-alert](/Users/cp340150/code/omni-components/omni-components/src/alert/README.md) @@ -223,7 +223,7 @@ Component that displays an alert.
-[omni-clear-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-clear-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -231,7 +231,7 @@ Clear icon component.
-[omni-search-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-search-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -239,7 +239,7 @@ Search icon component.
-[omni-search-field](/Users/runner/work/omni-components/omni-components/src/search-field/README.md) +[omni-search-field](/Users/cp340150/code/omni-components/omni-components/src/search-field/README.md) @@ -247,7 +247,7 @@ Search input control.
-[omni-chevron-down-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-chevron-down-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -255,7 +255,7 @@ Chevron down icon component.
-[omni-more-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-more-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -263,7 +263,7 @@ More icon component.
-[omni-select](/Users/runner/work/omni-components/omni-components/src/select/README.md) +[omni-select](/Users/cp340150/code/omni-components/omni-components/src/select/README.md) @@ -271,7 +271,7 @@ Control to get / set a value within a list of options.
-[omni-icon](/Users/runner/work/omni-components/omni-components/src/icon/README.md) +[omni-icon](/Users/cp340150/code/omni-components/omni-components/src/icon/README.md) @@ -279,7 +279,7 @@ Component that displays an icon.
-[omni-color-field](/Users/runner/work/omni-components/omni-components/src/color-field/README.md) +[omni-color-field](/Users/cp340150/code/omni-components/omni-components/src/color-field/README.md) @@ -287,7 +287,7 @@ Color input control.
-[omni-text-field](/Users/runner/work/omni-components/omni-components/src/text-field/README.md) +[omni-text-field](/Users/cp340150/code/omni-components/omni-components/src/text-field/README.md) @@ -295,7 +295,7 @@ Control to input text.
-[omni-label](/Users/runner/work/omni-components/omni-components/src/label/README.md) +[omni-label](/Users/cp340150/code/omni-components/omni-components/src/label/README.md) @@ -303,7 +303,7 @@ Label component that renders styled text.
-[omni-switch](/Users/runner/work/omni-components/omni-components/src/switch/README.md) +[omni-switch](/Users/cp340150/code/omni-components/omni-components/src/switch/README.md) @@ -311,7 +311,7 @@ Control to switch a value on or off.
-[omni-chevron-left-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-chevron-left-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -319,7 +319,7 @@ Chevron left icon component.
-[omni-chevron-right-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-chevron-right-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -327,7 +327,7 @@ Chevron right icon component.
-[omni-calendar](/Users/runner/work/omni-components/omni-components/src/calendar/README.md) +[omni-calendar](/Users/cp340150/code/omni-components/omni-components/src/calendar/README.md) @@ -335,7 +335,7 @@ Calendar component to set specific date.
-[omni-indeterminate-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-indeterminate-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -343,7 +343,7 @@ Indeterminate icon component.
-[omni-check-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-check-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -351,7 +351,7 @@ Check icon component.
-[omni-check](/Users/runner/work/omni-components/omni-components/src/check/README.md) +[omni-check](/Users/cp340150/code/omni-components/omni-components/src/check/README.md) @@ -359,7 +359,7 @@ Control that allows a selection to be made.
-[omni-close-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-close-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -367,7 +367,7 @@ Close icon component.
-[omni-chip](/Users/runner/work/omni-components/omni-components/src/chip/README.md) +[omni-chip](/Users/cp340150/code/omni-components/omni-components/src/chip/README.md) @@ -375,7 +375,7 @@ Control that can be used for input, setting attributes, or performing actions.
-[omni-arrow-right-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-arrow-right-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -383,7 +383,7 @@ Arrow right icon component.
-[omni-backspace-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-backspace-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -391,7 +391,7 @@ Backspace icon component.
-[omni-caps-off-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-caps-off-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -399,7 +399,7 @@ Caps off icon component.
-[omni-caps-on-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-caps-on-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -407,7 +407,7 @@ Caps on icon component.
-[omni-caps-lock-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-caps-lock-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -415,7 +415,7 @@ Caps lock icon component.
-[omni-next-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-next-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -423,7 +423,7 @@ Next icon component.
-[omni-previous-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-previous-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -431,7 +431,7 @@ Previous icon component.
-[omni-send-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-send-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -439,7 +439,7 @@ Send icon component.
-[omni-keyboard-button](/Users/runner/work/omni-components/omni-components/src/keyboard/README.md) +[omni-keyboard-button](/Users/cp340150/code/omni-components/omni-components/src/keyboard/README.md) @@ -447,7 +447,7 @@ An internal keyboard button control used in the keyboard component.
-[omni-keyboard](/Users/runner/work/omni-components/omni-components/src/keyboard/README.md) +[omni-keyboard](/Users/cp340150/code/omni-components/omni-components/src/keyboard/README.md) @@ -455,7 +455,7 @@ A responsive on-screen keyboard control component.
-[omni-currency-field](/Users/runner/work/omni-components/omni-components/src/currency-field/README.md) +[omni-currency-field](/Users/cp340150/code/omni-components/omni-components/src/currency-field/README.md) @@ -463,7 +463,7 @@ Control to enter a formatted currency value.
-[omni-calendar-icon](/Users/runner/work/omni-components/omni-components/src/icons/README.md) +[omni-calendar-icon](/Users/cp340150/code/omni-components/omni-components/src/icons/README.md) @@ -471,7 +471,7 @@ A calendar icon component.
-[omni-date-picker](/Users/runner/work/omni-components/omni-components/src/date-picker/README.md) +[omni-date-picker](/Users/cp340150/code/omni-components/omni-components/src/date-picker/README.md) @@ -479,7 +479,7 @@ Control to get / set a specific date using a calendar.
-[omni-email-field](/Users/runner/work/omni-components/omni-components/src/email-field/README.md) +[omni-email-field](/Users/cp340150/code/omni-components/omni-components/src/email-field/README.md) @@ -487,7 +487,23 @@ Email input control, used in forms for input validation and to display correct v
-[omni-hyperlink](/Users/runner/work/omni-components/omni-components/src/hyperlink/README.md) +[omni-expander](/Users/cp340150/code/omni-components/omni-components/src/expander/README.md) + + + +Layout component that groups together content in an expanded box. + +
+ +[omni-expander-group](/Users/cp340150/code/omni-components/omni-components/src/expander/README.md) + + + +Layout container that groups expanders, allowing for automatic expanding and collapsing of sibling expander controls. + +
+ +[omni-hyperlink](/Users/cp340150/code/omni-components/omni-components/src/hyperlink/README.md) @@ -543,7 +559,7 @@ Plus icon component.
-[omni-number-field](/Users/runner/work/omni-components/omni-components/src/number-field/README.md) +[omni-number-field](/Users/cp340150/code/omni-components/omni-components/src/number-field/README.md) @@ -551,7 +567,7 @@ Input control to enter a single line of numbers.
-[omni-password-field](/Users/runner/work/omni-components/omni-components/src/password-field/README.md) +[omni-password-field](/Users/cp340150/code/omni-components/omni-components/src/password-field/README.md) @@ -559,7 +575,7 @@ Password input control.
-[omni-pin-field](/Users/runner/work/omni-components/omni-components/src/pin-field/README.md) +[omni-pin-field](/Users/cp340150/code/omni-components/omni-components/src/pin-field/README.md) @@ -567,7 +583,7 @@ Input control to enter a masked numeric value.
-[omni-radio](/Users/runner/work/omni-components/omni-components/src/radio/README.md) +[omni-radio](/Users/cp340150/code/omni-components/omni-components/src/radio/README.md) @@ -575,7 +591,7 @@ Control to select a single value from a group of values.
-[omni-radio-group](/Users/runner/work/omni-components/omni-components/src/radio/README.md) +[omni-radio-group](/Users/cp340150/code/omni-components/omni-components/src/radio/README.md) @@ -583,7 +599,7 @@ Control to group radio components for single selection
-[omni-tab](/Users/runner/work/omni-components/omni-components/src/tab/README.md) +[omni-tab](/Users/cp340150/code/omni-components/omni-components/src/tab/README.md) @@ -591,7 +607,7 @@ Control that can be used to display slotted content, for use within an Tab Group
-[omni-tab-header](/Users/runner/work/omni-components/omni-components/src/tab/README.md) +[omni-tab-header](/Users/cp340150/code/omni-components/omni-components/src/tab/README.md) @@ -599,7 +615,7 @@ Control that can be used to display custom slotted content, for use within Tab G
-[omni-tab-group](/Users/runner/work/omni-components/omni-components/src/tab/README.md) +[omni-tab-group](/Users/cp340150/code/omni-components/omni-components/src/tab/README.md) @@ -607,7 +623,7 @@ Component that displays content in tabs.
-[omni-toast-stack](/Users/runner/work/omni-components/omni-components/src/toast/README.md) +[omni-toast-stack](/Users/cp340150/code/omni-components/omni-components/src/toast/README.md) @@ -615,7 +631,7 @@ A toast container that animates in and stacks toast elements.
-[omni-toast](/Users/runner/work/omni-components/omni-components/src/toast/README.md) +[omni-toast](/Users/cp340150/code/omni-components/omni-components/src/toast/README.md) diff --git a/package.json b/package.json index 06bd2bcfa..d704c61dc 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,8 @@ "modal", "toast", "tab", - "alert" + "alert", + "expander" ], "exports": { "./*": "./dist/*/index.js" diff --git a/src/expander/Expander.spec.ts b/src/expander/Expander.spec.ts new file mode 100644 index 000000000..645c098b7 --- /dev/null +++ b/src/expander/Expander.spec.ts @@ -0,0 +1,110 @@ +import { test, expect, mockEventListener, withCoverage } from '../utils/JestPlaywright.js'; + +test(`Expander - Visual and Behaviour`, async ({ page }) => { + await withCoverage(page, async () => { + await page.goto('/components/expander/'); + const expander = page.locator('.Interactive').getByTestId('test-expander'); + + await expect(expander).toHaveScreenshot('expander-initial.png'); + // The expanded attribute should be not set by default + await expect(expander).not.toHaveAttribute('expanded', ''); + + const expanderHeader = expander.locator('.header'); + await expanderHeader.click(); + // The expanded attribute should be set once the expander is expanded + await expect(expander).toHaveAttribute('expanded', ''); + + await expect(expander).toHaveScreenshot('expander-expanded.png'); + + await expanderHeader.click(); + + await expect(expander).not.toHaveAttribute('expanded', ''); + }); +}); + +test(`Expander - Disabled Behaviour`, async ({ page }) => { + await withCoverage(page, async () => { + await page.goto('/components/expander/'); + const expander = page.locator('.Disabled').getByTestId('test-expander'); + + await expect(expander).toHaveScreenshot('expander-initial.png'); + + const animantionEnd = await mockEventListener(expander, 'animationend'); + + const expanderHeader = expander.locator('.header'); + await expanderHeader.click(); + + await expect(expander).not.toHaveAttribute('expanded', ''); + + await expect(expander).toHaveScreenshot('expander-initial.png'); + await expect(animantionEnd).toBeCalledTimes(0); + }); +}); + +test(`Expander - Button Alignment Behaviour`, async ({ page }) => { + await withCoverage(page, async () => { + await page.goto('/components/expander/'); + const expander = page.locator('.Button_Alignment').getByTestId('test-expander'); + + await expect(expander).toHaveScreenshot('expander-initial.png'); + + const header = expander.locator('.header'); + + // Confirm that there is 3 elements in the header + await expect(await header.evaluate((h) => h.childElementCount)).toBe(3); + + await expect(expander).toHaveAttribute('button-alignment', 'left'); + + const headerButton = header.locator('.expand-icon-container'); + await expect(headerButton).toHaveCount(1); + }); +}); + +test(`Expander - Expanded Behaviour`, async ({ page }) => { + await withCoverage(page, async () => { + await page.goto('/components/expander/'); + const expander = page.locator('.Expanded').getByTestId('test-expander'); + + await expect(expander).toHaveScreenshot('expander-initial.png'); + await expect(expander).toHaveAttribute('expanded', 'true'); + + const expanderHeader = expander.locator('.header'); + await expanderHeader.click(); + + await expect(expander).not.toHaveAttribute('expanded', ''); + await expect(expander).toHaveScreenshot('expander-closed.png'); + }); +}); + +test(`Expander - Expand Slotted Icon Behaviour`, async ({ page }) => { + await withCoverage(page, async () => { + await page.goto('/components/expander/'); + const expander = page.locator('.Expand_Icon').getByTestId('test-expander'); + + await expect(expander).toHaveScreenshot('expander-initial.png'); + + const header = expander.locator('.header'); + + const expandIconContainer = header.locator('.expand-icon-container'); + await expect(expandIconContainer).toHaveCount(1); + + const slotElement = expander.locator('slot[name="expand-icon"]'); + await expect(slotElement).toHaveCount(1); + }); +}); + +test(`Expander - Header Slotted Icon Behaviour`, async ({ page }) => { + await withCoverage(page, async () => { + await page.goto('/components/expander/'); + const expander = page.locator('.Header_Icon').getByTestId('test-expander'); + + await expect(expander).toHaveScreenshot('expander-initial.png'); + const header = expander.locator('.header'); + + const headerIconContainer = header.locator('.header-icon-container'); + await expect(headerIconContainer).toHaveCount(1); + + const slotElement = expander.locator('slot[name="header-icon"]'); + await expect(slotElement).toHaveCount(1); + }); +}); diff --git a/src/expander/Expander.stories.ts b/src/expander/Expander.stories.ts new file mode 100644 index 000000000..73d81cce9 --- /dev/null +++ b/src/expander/Expander.stories.ts @@ -0,0 +1,210 @@ +import { html, nothing } from 'lit'; +import { unsafeHTML } from 'lit/directives/unsafe-html.js'; +import { ifNotEmpty } from '../utils/Directives.js'; +import { assignToSlot, ComponentStoryFormat, getSourceFromLit, raw } from '../utils/StoryUtils.js'; + +import '../label/Label.js'; +import '../icon/Icon.js'; +import './Expander.js'; +import './ExpanderGroup.js'; + +const buttonAlignment = ['left', 'right'] as const; + +interface Args { + label: string; + disabled: boolean; + expanded: boolean; + buttonAlignment: (typeof buttonAlignment)[number]; + '[Default Slot]': string; + expand_icon: string; + header_icon: string; +} + +export const Interactive: ComponentStoryFormat = { + render: (args: Args) => html` + + ${args.expand_icon ? html`${'\r\n'}${unsafeHTML(assignToSlot('expand-icon', args.expand_icon))}` : nothing} + ${args.header_icon ? html`${'\r\n'}${unsafeHTML(assignToSlot('header-icon', args.header_icon))}` : nothing} + ${args['[Default Slot]'] ? html`${'\r\n'}${unsafeHTML(args['[Default Slot]'])}` : nothing} + + `, + name: 'Interactive', + frameworkSources: [ + { + framework: 'Vue', + load: (args) => + getSourceFromLit(Interactive!.render!(args), undefined, (s) => + s.replace(' disabled', ' :disabled="true"').replace(' expanded', ' :expanded="true"') + ) + } + ], + args: { + label: 'Interactive Expander', + '[Default Slot]': raw``, + disabled: false, + expanded: false, + buttonAlignment: 'right', + expand_icon: '', + header_icon: '' + } +}; + +export const Disabled: ComponentStoryFormat = { + render: (args: Args) => html` + + + + `, + name: 'Disabled', + frameworkSources: [ + { + framework: 'Vue', + load: (args) => getSourceFromLit(Disabled!.render!(args), undefined, (s) => s.replace(' disabled', ' :disabled="true"')) + }, + { + framework: 'React', + load: (args) => `import { OmniExpander } from "@capitec/omni-components-react/expander"; +import { OmniLabel } from "@capitec/omni-components-react/label"; + +const App = () => + + +;` + } + ], + description: 'Prevent interaction (expanding/collapsing).', + args: { + label: 'Disabled expander', + disabled: true + } +}; + +export const Button_Alignment: ComponentStoryFormat = { + render: (args: Args) => html` + + + + `, + frameworkSources: [ + { + framework: 'React', + load: (args) => `import { OmniExpander } from "@capitec/omni-components-react/expander"; +import { OmniLabel } from "@capitec/omni-components-react/label"; + +const App = () => + + +;` + } + ], + name: 'Button Alignment', + description: 'Toggle where the expand button should be oriented.', + args: { + label: 'Left aligned button', + buttonAlignment: 'left' + } +}; + +export const Expanded: ComponentStoryFormat = { + render: (args: Args) => html` + + + + `, + name: 'Expanded', + frameworkSources: [ + { + framework: 'Vue', + load: (args) => getSourceFromLit(Expanded!.render!(args), undefined, (s) => s.replace(' expanded', ' :expanded="true"')) + }, + { + framework: 'React', + load: (args) => `import { OmniExpander } from "@capitec/omni-components-react/expander"; +import { OmniLabel } from "@capitec/omni-components-react/label"; + +const App = () => + + +;` + } + ], + description: 'Toggle expander expanded state', + args: { + label: 'Expanded expander state', + expanded: true + } +}; + +export const Expand_Icon: ComponentStoryFormat = { + render: (args: Args) => html` + + ${unsafeHTML(args.expand_icon)} + + + `, + frameworkSources: [ + { + framework: 'React', + load: (args) => `import { OmniExpander } from "@capitec/omni-components-react/expander"; +import { OmniLabel } from "@capitec/omni-components-react/label"; + +const App = () => + + + +;` + } + ], + name: 'Slotted Expand Icon', + description: 'Custom slotted expand icon', + args: { + label: 'Slotted Expand Icon', + expand_icon: raw`` + } +}; + +export const Header_Icon: ComponentStoryFormat = { + render: (args: Args) => html` + + ${unsafeHTML(args.header_icon)} + + + `, + frameworkSources: [ + { + framework: 'React', + load: (args) => `import { OmniExpander } from "@capitec/omni-components-react/expander"; +import { OmniLabel } from "@capitec/omni-components-react/label"; + +const App = () => + + + +;` + } + ], + name: 'Slotted Header Icon', + description: 'Custom slotted header icon', + args: { + label: 'Slotted Header Icon', + header_icon: raw`` + } +}; diff --git a/src/expander/Expander.ts b/src/expander/Expander.ts new file mode 100644 index 000000000..f71aa8422 --- /dev/null +++ b/src/expander/Expander.ts @@ -0,0 +1,449 @@ +import { css, html, nothing, TemplateResult } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { OmniElement } from '../core/OmniElement.js'; +import '../icons/ChevronDown.icon.js'; +import '../label/Label.js'; + +/** + * Component that groups together content in an expanded box. + * + * @import + * ```js + * import '@capitec/omni-components/expander'; + * ``` + * @example + * html``` + * + * + * + * ``` + * @element omni-expander + * + * @slot - Content to render inside the expander once expanded. + * @slot expand-icon - Replaces the expand icon by default this will be the omni-chevron-down-icon. + * @slot header-icon - Replaces the icon in the header which is usually placed on the opposite end of the expand icon. + * + * @fires expand - Dispatched when the expander is expanded. + * @fires collapse - Dispatched when the expander is collapsed. + * + * @cssprop --omni-expander-header-min-height - Expander component minimum height. + * @cssprop --omni-expander-header-max-height - Expander component maximum height. + * + * @cssprop --omni-expander-width - Expander component width. + * @cssprop --omni-expander-background - Expander component background. + * + * @cssprop --omni-expander-expanded-height - Expander component expanded height. + * + * @cssprop --omni-expander-header-width - Expander header width. + * @cssprop --omni-expander-header-height - Expander header height. + * @cssprop --omni-expander-header-padding - Expander header padding. + * @cssprop --omni-expander-header-border-top - Expander header border top. + * + * @cssprop --omni-expander-header-hover-background - Expander header hover background. + * + * @cssprop --omni-expander-header-label-font-color - Expander header label font color. + * @cssprop --omni-expander-header-label-font-size - Expander header label font size. + * @cssprop --omni-expander-header-label-font-weight - Expander header label font weight. + * + * @cssprop --omni-expander-header-disabled-background - Expander header disabled background. + * + * @cssprop --omni-expander-content-width - Expander content width. + * @cssprop --omni-expander-content-height - Expander content height. + * @cssprop --omni-expander-content-border - Expander content border. + * @cssprop --omni-expander-content-padding - Expander content padding. + * + * @cssprop --omni-expander-content-closed-padding-top - Expander content closed top padding. + * @cssprop --omni-expander-content-closed-padding-bottom - Expander content closed bottom padding. + * + * @cssprop --omni-expander-content-expanded-border-bottom - Bottom border of the expander content. + * + * @cssprop --omni-expander-header-icon-container-padding - Expander header icon container padding. + * + * @cssprop --omni-expander-header-icon-slot-width - Expander header icon slot width. + * @cssprop --omni-expander-header-icon-slot-height - Expander header icon slot height. + * + * @cssprop --omni-expander-expand-icon-container-padding - Expander expand icon container padding. + * + * @cssprop --omni-expander-expand-icon-width - Expander expand icon width. + * @cssprop --omni-expander-expand-icon-height - Expander expand icon height. + * @cssprop --omni-expander-expand-icon-color - Expander expand icon color. + * + * @cssprop --omni-expander-expanding-container-padding-top - Expander expanding content top padding. + * @cssprop --omni-expander-expanding-container-padding-bottom - Expander expanding content bottom padding. + * + */ +@customElement('omni-expander') +export class Expander extends OmniElement { + /** + * Expander component label. + * @attr + */ + @property({ type: String, reflect: true }) label?: string; + + /** + * Indicator if the expander is expanded. + * @attr + */ + @property({ type: Boolean, reflect: true }) expanded?: boolean; + + /** + * Indicator if the expander is disabled. + * @attr + */ + @property({ type: Boolean, reflect: true }) disabled?: boolean; + + /** + * Indicate where the Expander button should be positioned + * @attr [button-alignment] + */ + @property({ type: String, reflect: true, attribute: 'button-alignment' }) buttonAlignment: 'left' | 'right' = 'right'; + + override connectedCallback(): void { + super.connectedCallback(); + this.addEventListener('animationend', this._animationCompleted.bind(this), { + capture: true + }); + } + + override disconnectedCallback() { + // Stop listening for child label change events. + this.removeEventListener(`animationend`, this._animationCompleted.bind(this)); + + // Ensure the component is cleaned up correctly. + super.disconnectedCallback(); + } + + _headerClick(e: MouseEvent) { + // Prevent the event from bubbling up. + e.stopPropagation(); + + // Ignore the click event if the item is disabled. + if (this.disabled) { + return; + } + + // Toggle the expanded state of the item. + if (this.expanded) { + this._collapse(); + } else { + this._expand(); + } + } + + _animationCompleted() { + // Remove the expanding animation, if set. + if (this.hasAttribute(`expanding`)) { + this.removeAttribute(`expanding`); + this.expanded = true; + } + + // Remove the collapsing animation, if set. + if (this.hasAttribute(`collapsing`)) { + this.removeAttribute(`collapsing`); + this.expanded = false; + } + } + + _expand() { + const { matches: motionOK } = window.matchMedia('(prefers-reduced-motion: no-preference)'); + if (motionOK) { + // Ignore the request to expand if the component is already expanded. + if (this.expanded === true || this.hasAttribute(`expanding`)) { + return; + } + + // Trigger the expanding animation. + this.removeAttribute(`collapsing`); + this.setAttribute(`expanding`, ``); + } else { + this.expanded = true; + } + + // Notify any direct subscribers that the component was expanded. + this.dispatchEvent(new CustomEvent(`expand`)); + } + + _collapse() { + const { matches: motionOK } = window.matchMedia('(prefers-reduced-motion: no-preference)'); + + if (motionOK) { + // Ignore the request to collapse if the component is already collapsed. + if (this.expanded === false || this.hasAttribute(`collapsing`)) { + return; + } + + // Trigger the collapsing animation. + this.removeAttribute(`expanding`); + this.setAttribute(`collapsing`, ``); + } else { + this.expanded = false; + } + + // Notify any direct subscribers that the component was collapsed. + this.dispatchEvent(new CustomEvent(`collapse`)); + } + + static override get styles() { + return [ + super.styles, + + css` + :host { + min-height: var(--omni-expander-header-min-height, 50px); + max-height: var(--omni-expander-header-max-height, 50px); + } + `, + css` + + + :host { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: stretch; + width: var(--omni-expander-width, 100%); + background: var(--omni-expander-background, var(--omni-background-color)); + } + + :host([expanded]) { + max-height: unset; + height: var(--omni-expander-expanded-height, 200px); + } + + /* HEADER STYLES */ + + :host > .header { + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; + width: var(--omni-expander-header-width, 100%); + height: var(--omni-expander-header-height, 50px); + padding: var(--omni-expander-header-padding, 10px); + border-top: var(--omni-expander-header-border-top, 1px solid var(--omni-primary-color)); + cursor: pointer; + } + + :host > .header:hover { + background: var(--omni-expander-header-hover-background, var(--omni-background-hover-color)); + } + + + :host > .header > omni-label { + --omni-label-font-color: var(--omni-expander-header-label-font-color, var(--omni-font-color)); + --omni-label-default-font-size: var(--omni-expander-header-label-font-size, var(--omni-font-size)); + --omni-label-default-font-weight: var(--omni-expander-header-label-font-weight, var(--omni-font-weight)); + margin-right: auto; + cursor: pointer; + } + + :host([expanded]) > .header { + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + } + + :host([expanded]) > .header > .expand-icon-container { + transform: rotate(180deg); + } + + :host(:not([expanded])) > .header > .expand-icon-container { + transform: none; + } + + :host([disabled]) > .header { + background: var(--omni-expander-header-disabled-background ,var(--omni-disabled-background-color)); + } + + /* EXPANDER CONTENT STYLES */ + :host > .expander-content { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: stretch; + width: var(--omni-expander-content-width, 100%); + height: var(--omni-expander-content-height, 100%); + + flex: 1 1 auto; + + border-left: var(--omni-expander-content-border, 1px solid var(--omni-primary-color)); + border-right: var(--omni-expander-content-border, 1px solid var(--omni-primary-color)); + border-top: var(--omni-expander-content-border, 1px solid var(--omni-primary-color)); + + padding: var(--omni-expander-content-padding, 10px); + } + + :host(:not([expanded])) > .expander-content { + overflow: hidden; + padding-top: var(--omni-expander-content-closed-padding-top, 0px); + padding-bottom: var(--omni-expander-content-closed-padding-bottom, 0px); + } + + :host([expanding]) > .expander-content, + :host([expanded]) > .expander-content { + border-bottom: var(--omni-expander-content-expanded-border-bottom, 1px solid var(--omni-primary-color)); + } + + + + /* HEADER ICON */ + + .header-icon-container { + display: inline-flex; + flex: 0 0 auto; + align-items: center; + cursor: pointer; + padding: var(--omni-expander-header-icon-container-padding, 10px 10px); + } + + ::slotted([slot='header-icon']) { + width: var(--omni-expander-header-icon-slot-width, 20px); + height: var(--omni-expander-header-icon-slot-height, 20px); + } + + + /* EXPAND ICON */ + .expand-icon-container { + display: inline-flex; + flex: 0 0 auto; + align-items: center; + cursor: pointer; + padding: var(--omni-expander-expand-icon-container-padding, 10px 10px); + } + + .expand-icon { + width: var(--omni-expander-expand-icon-width, 20px); + height: var(--omni-expander-expand-icon-height, 20px); + fill: var(--omni-expander-expand-icon-color, var(--omni-primary-color)); + } + + ::slotted([slot='expand-icon']) { + height: var(--omni-expander-expand-icon-height, 20px); + width: var(--omni-expander-expand-icon-width, 20px); + } + + /* ANIMATIONS */ + + :host([expanding]) { + animation: expand 0.5s; + animation-timing-function: cubic-bezier(0.2, 0.8, 0.5, 1); + animation-fill-mode: forwards; + } + + :host([expanding]) > .header > .expand-icon-container { + transition: all 0.15s linear 0s; + transform: rotate(180deg); + } + + :host([collapsing]) > .header > .expand-icon-container { + transition: all 0.15s linear 0s; + transform: none; + } + + :host([expanding]) > .expander-content { + transition: padding linear 0.2s; + padding-top: var(--omni-expander-expanding-container-padding-top, 10px); + padding-bottom: var(--omni-expander-expanding-container-padding-bottom 10px); + } + + :host([collapsing]) > .expander-content { + overflow: hidden; + } + + /* Hide scrollbar for Chrome, Safari and Opera */ + :host([collapsing]) > .expander-content::-webkit-scrollbar { + display: none; + } + + /* Hide scrollbar for IE and Edge */ + :host([collapsing]) > .expander-content { + -ms-overflow-style: none; + } + + :host([collapsing]) { + animation: collapse 0.5s; + animation-timing-function: cubic-bezier(0.2, 0.8, 0.5, 1); + animation-fill-mode: forwards; + } + + @media (prefers-reduced-motion) { + :host([expanding]) { + animation: unset; + } + + :host([collapsing]) { + animation: unset; + } + } + + @keyframes expand { + 0% { + max-height: var(--omni-expander-header-height, 50px); + height: var(--omni-expander-header-height, 50px); + } + 99% { + max-height: var(--omni-expander-expanding-max-height, 100vh); + height: var(--omni-expander-height, 200px); + } + 100% { + max-height: unset; + height: var(--omni-expander-height, 200px); + } + } + + @keyframes collapse { + 0% { + max-height: var(--omni-expander-height, 200px); + overflow: hidden; + } + 100% { + max-height: var(--omni-expander-header-height, 50px); + overflow: hidden; + } + } + + ` + ]; + } + + protected override render(): TemplateResult { + return html` +
+ ${this._renderHeader()} +
+
+ +
+ + `; + } + + _renderHeader(): TemplateResult { + return html` + ${ + this.buttonAlignment === 'left' + ? html`
` + : this._renderIcon() + } + ${this.label ? html`` : nothing} + ${ + this.buttonAlignment === 'right' + ? html`
` + : this._renderIcon() + } + `; + } + + _renderIcon(): TemplateResult { + return html` +
+ +
+ `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'omni-expander': Expander; + } +} diff --git a/src/expander/ExpanderGroup.spec.ts b/src/expander/ExpanderGroup.spec.ts new file mode 100644 index 000000000..75044637a --- /dev/null +++ b/src/expander/ExpanderGroup.spec.ts @@ -0,0 +1,54 @@ +import { test, expect, mockEventListener, withCoverage } from '../utils/JestPlaywright.js'; + +test(`Expander Group - Visual and Behaviour`, async ({ page }) => { + await withCoverage(page, async () => { + await page.goto('/components/expander-group/'); + const expanderGroup = page.locator('.Interactive').getByTestId('test-expander-group'); + await expect(expanderGroup).toHaveCount(1); + + await expect(expanderGroup).toHaveScreenshot('expander-group-initial.png'); + await expect(expanderGroup).toHaveAttribute('expand-mode', 'single'); + + // Get all the omni-expanders + const nestedExpanders = expanderGroup.locator('omni-expander'); + await expect(nestedExpanders).toHaveCount(2); + + // Open the first expander. + const expander = nestedExpanders.first(); + await expander.click(); + + await expect(expanderGroup).toHaveScreenshot('expander-group-expanded.png'); + + const secondExpander = nestedExpanders.nth(1); + await secondExpander.click(); + + // Take a screenshot of the expected behaviour of the second expander expanding and the first one closing + await expect(expanderGroup).toHaveScreenshot('expander-group-second-expanded.png'); + }); +}); + +test(`Expander Group - Expand Mode Behaviour`, async ({ page }) => { + await withCoverage(page, async () => { + await page.goto('/components/expander-group/'); + const expanderGroup = page.locator('.Expand_Mode').getByTestId('test-expander-group'); + await expect(expanderGroup).toHaveCount(1); + // Check that the expander group has the expand-mode attribute set to multiple. + await expect(expanderGroup).toHaveAttribute('expand-mode', 'multiple'); + + // Get all the omni-expanders. + const nestedExpanders = expanderGroup.locator('omni-expander'); + await expect(nestedExpanders).toHaveCount(2); + + // Open the first expander. + const expander = nestedExpanders.first(); + await expander.click(); + + await expect(expanderGroup).toHaveScreenshot('expander-group-expanded.png'); + + const secondExpander = nestedExpanders.nth(1); + await secondExpander.click(); + + // Take a screenshot of the expected behaviour of both expanders being open due to the expander-groups expand-mode attribute being set to multiple. + await expect(expanderGroup).toHaveScreenshot('expander-group-both-expanded.png'); + }); +}); diff --git a/src/expander/ExpanderGroup.stories.ts b/src/expander/ExpanderGroup.stories.ts new file mode 100644 index 000000000..7e96ee4b6 --- /dev/null +++ b/src/expander/ExpanderGroup.stories.ts @@ -0,0 +1,77 @@ +import { html, nothing } from 'lit'; +import { unsafeHTML } from 'lit/directives/unsafe-html.js'; +import { ComponentStoryFormat, raw } from '../utils/StoryUtils.js'; + +import '../label/Label.js'; +import './Expander.js'; +import './ExpanderGroup.js'; + +interface Args { + expandMode: string; + '[Default Slot]': string; +} + +export const Interactive: ComponentStoryFormat = { + render: (args: Args) => html` + + ${args['[Default Slot]'] ? html`${'\r\n'}${unsafeHTML(args['[Default Slot]'])}` : nothing} + + `, + name: 'Interactive', + description: () => html`

+ The <omni-expander-group> should be used if grouping multiple <omni-expander> components together. +

`, + args: { + expandMode: 'single', + '[Default Slot]': raw` + + + + + ` + } +}; + +export const Expand_Mode: ComponentStoryFormat = { + render: (args: Args) => html` + + ${args['[Default Slot]'] ? html`${'\r\n'}${unsafeHTML(args['[Default Slot]'])}` : nothing} + + `, + name: 'Expand Mode', + frameworkSources: [ + { + framework: 'React', + load: (args) => `import { OmniExpanderGroup, OmniExpander } from "@capitec/omni-components-react/expander"; + import { OmniLabel } from "@capitec/omni-components-react/label"; + +const App = () => + + + + + + + +;` + } + ], + description: () => html`

+ The <omni-expander-group> opens one <omni-expander> by default, to expand mutiple set the attribute expand-mode="multiple". +

`, + args: { + expandMode: 'multiple', + '[Default Slot]': raw` + + + + + ` + } +}; diff --git a/src/expander/ExpanderGroup.ts b/src/expander/ExpanderGroup.ts new file mode 100644 index 000000000..94f182abd --- /dev/null +++ b/src/expander/ExpanderGroup.ts @@ -0,0 +1,112 @@ +import { css, html, TemplateResult } from 'lit'; +import { customElement, property, state } from 'lit/decorators.js'; +import { OmniElement } from '../core/OmniElement.js'; + +/** + * Layout container that groups expanders. + * + * @import + * ```js + * import '@capitec/omni-components/expander'; + * ``` + * @example + * html``` + * + * + * + * + * + * + * + * + * ``` + * + * @element omni-expander-group + * + * @slot - Default slot to slot multiple expanders. + * + * @cssprop --omni-expander-group-container-min-width - Expander group min width. + * @cssprop --omni-expander-group-container-min-height - Expander group min height. + * + * @cssprop --omni-expander-group-container-margin-bottom - Expander group container margin bottom. + */ +@customElement('omni-expander-group') +export class ExpanderGroup extends OmniElement { + /** + * Expander component label. + * @attr [expand-mode] + */ + @property({ type: String, reflect: true, attribute: 'expand-mode' }) expandMode?: 'multiple' | 'single' = 'single'; + + override connectedCallback(): void { + super.connectedCallback(); + this.addEventListener('expand', this._expanderExpanded.bind(this), { + capture: true + }); + } + + override disconnectedCallback() { + // Ensure the component is cleaned up correctly. + super.disconnectedCallback(); + } + + _expanderExpanded(e: Event) { + if (this.expandMode === 'single') { + const expanders = Array.from(this.children); + expanders.forEach((expander: any) => { + if (expander !== e.target) { + expander._collapse(); + } + }); + } + } + + static override get styles() { + return [ + super.styles, + css` + :host { + display: flex; + flex-direction: column; + justify-content: stretch; + align-items: stretch; + min-width: var(--omni-expander-group-container-min-width, 200px); + min-height: var(--omni-expander-group-container-min-height, 100px); + } + + .group-container { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: stretch; + } + + ::slotted(*) { + margin-bottom: var(--omni-expander-group-container-margin-bottom, 0px); + } + + ::slotted(*[expanded]) { + flex: 1 1 auto; + } + + ::slotted(omni-expander:not(:last-of-type)) { + --omni-expander-content-expanded-border-bottom : none; + } + ` + ]; + } + + protected override render(): TemplateResult { + return html` +
+ +
+ `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'omni-expander-group': ExpanderGroup; + } +} diff --git a/src/expander/README.md b/src/expander/README.md new file mode 100644 index 000000000..e0842f219 --- /dev/null +++ b/src/expander/README.md @@ -0,0 +1,139 @@ +# omni-expander + +Layout component that groups together content in an expanded box. + +## Example + +html + +``` + + + +``` + +## Properties + +| Property | Attribute | Modifiers | Type | Default | Description | +|-------------------|--------------------|-----------|------------------------|---------|--------------------------------------------------| +| `buttonAlignment` | `button-alignment` | | `"left" \| "right"` | "right" | Indicate where the Expander button should be positioned | +| `dir` | | | `string` | | | +| `disabled` | `disabled` | | `boolean \| undefined` | | Indicator if the expander is disabled. | +| `expanded` | `expanded` | | `boolean \| undefined` | | Indicator if the expander is expanded. | +| `label` | `label` | | `string \| undefined` | | Expander component label. | +| `lang` | | | `string` | | | +| `override` | `override` | | | | Used to set the base direction of text for display | +| `styles` | | readonly | `CSSResultGroup[]` | | | + +## Events + +| Event | Type | +|------------|------------------------------------------------| +| `collapse` | `CustomEvent<{ label: string \| undefined; }>` | +| `expand` | `CustomEvent<{ label: string \| undefined; }>` | + +## Slots + +| Name | Description | +|---------------------|--------------------------------------------------| +| | Content to render inside the expander once expanded. | +| `expand-icon` | Replaces the expand icon by default this will be the omni-chevron-down-icon. | +| `header-icon` | Replaces the icon in the header which is usually placed on the opposite end of the expand icon. | +| `loading_indicator` | Used to define content that is displayed while async rendering is awaiting, or when renderLoading() is implicitly called | + +## CSS Custom Properties + +| Property | Description | +|-------------------------------------------------|-----------------------------------------| +| `--omni-expander-background-color` | Expander component background color. | +| `--omni-expander-border-top` | Expander header border top. | +| `--omni-expander-content-border` | Expander content border. | +| `--omni-expander-header-height` | Expander header height. | +| `--omni-expander-header-icon-container-padding` | Expander header icon container padding. | +| `--omni-expander-header-padding` | Expander header padding. | +| `--omni-expander-header-width` | Expander header width. | +| `--omni-expander-width` | Expander component width. | +| `--omni-theme-accent-active-color` | Theme accent active color. | +| `--omni-theme-accent-color` | Theme accent color. | +| `--omni-theme-accent-hover-color` | Theme accent hover color. | +| `--omni-theme-background-active-color` | Theme background active color. | +| `--omni-theme-background-color` | Theme background color. | +| `--omni-theme-background-hover-color` | Theme background hover color. | +| `--omni-theme-border-radius` | Theme border radius. | +| `--omni-theme-border-width` | Theme border width. | +| `--omni-theme-box-shadow` | Theme box shadow. | +| `--omni-theme-box-shadow-color` | Theme inactive color. | +| `--omni-theme-disabled-background-color` | Theme disabled background color. | +| `--omni-theme-disabled-border-color` | Theme disabled border color. | +| `--omni-theme-error-border-color` | Theme error border color. | +| `--omni-theme-error-font-color` | Theme disabled background color. | +| `--omni-theme-font-color` | Theme font color. | +| `--omni-theme-font-family` | Theme font family. | +| `--omni-theme-font-size` | Theme font size. | +| `--omni-theme-font-weight` | Theme font weight. | +| `--omni-theme-hint-font-color` | Theme hint font color. | +| `--omni-theme-inactive-color` | Theme inactive color. | +| `--omni-theme-primary-active-color` | Theme primary active color. | +| `--omni-theme-primary-color` | Theme primary color. | +| `--omni-theme-primary-hover-color` | Theme primary hover color. | + + +# omni-expander-group + +Layout container that groups expanders, allowing for automatic expanding and collapsing of sibling expander controls. + +## Example + +html + +``` + + +``` + +## Properties + +| Property | Attribute | Modifiers | Type | Default | Description | +|--------------|--------------|-----------|---------------------------------------|----------|--------------------------------------------------| +| `dir` | | | `string` | | | +| `expandMode` | `expandMode` | | `"multiple" \| "single" \| undefined` | "single" | Expander component label. | +| `lang` | | | `string` | | | +| `override` | `override` | | | | Used to set the base direction of text for display | +| `styles` | | readonly | `CSSResultGroup[]` | | | + +## Slots + +| Name | Description | +|---------------------|--------------------------------------------------| +| `loading_indicator` | Used to define content that is displayed while async rendering is awaiting, or when renderLoading() is implicitly called | + +## CSS Custom Properties + +| Property | Description | +|-------------------------------------------------|-----------------------------------------| +| `--omni-expander-group-container-margin-bottom` | Expander group container margin bottom. | +| `--omni-expander-group-container-min-height` | Expander group min height. | +| `--omni-expander-group-container-min-width` | Expander group min width. | +| `--omni-theme-accent-active-color` | Theme accent active color. | +| `--omni-theme-accent-color` | Theme accent color. | +| `--omni-theme-accent-hover-color` | Theme accent hover color. | +| `--omni-theme-background-active-color` | Theme background active color. | +| `--omni-theme-background-color` | Theme background color. | +| `--omni-theme-background-hover-color` | Theme background hover color. | +| `--omni-theme-border-radius` | Theme border radius. | +| `--omni-theme-border-width` | Theme border width. | +| `--omni-theme-box-shadow` | Theme box shadow. | +| `--omni-theme-box-shadow-color` | Theme inactive color. | +| `--omni-theme-disabled-background-color` | Theme disabled background color. | +| `--omni-theme-disabled-border-color` | Theme disabled border color. | +| `--omni-theme-error-border-color` | Theme error border color. | +| `--omni-theme-error-font-color` | Theme disabled background color. | +| `--omni-theme-font-color` | Theme font color. | +| `--omni-theme-font-family` | Theme font family. | +| `--omni-theme-font-size` | Theme font size. | +| `--omni-theme-font-weight` | Theme font weight. | +| `--omni-theme-hint-font-color` | Theme hint font color. | +| `--omni-theme-inactive-color` | Theme inactive color. | +| `--omni-theme-primary-active-color` | Theme primary active color. | +| `--omni-theme-primary-color` | Theme primary color. | +| `--omni-theme-primary-hover-color` | Theme primary hover color. | diff --git a/src/expander/index.ts b/src/expander/index.ts new file mode 100644 index 000000000..9af35dd98 --- /dev/null +++ b/src/expander/index.ts @@ -0,0 +1,2 @@ +export * from './Expander.js'; +export * from './ExpanderGroup.js';