diff --git a/.changeset/major-adults-bake.md b/.changeset/major-adults-bake.md new file mode 100644 index 00000000000..bb56b4445e1 --- /dev/null +++ b/.changeset/major-adults-bake.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +Add UnderlinePanels2 Component diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-colorblind-linux.png new file mode 100644 index 00000000000..380729cf417 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-dimmed-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-dimmed-linux.png new file mode 100644 index 00000000000..6ba0952ef13 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-high-contrast-linux.png new file mode 100644 index 00000000000..572b14f775c Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-linux.png new file mode 100644 index 00000000000..380729cf417 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-tritanopia-linux.png new file mode 100644 index 00000000000..380729cf417 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-light-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-light-colorblind-linux.png new file mode 100644 index 00000000000..1ed79aaea66 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-light-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-light-high-contrast-linux.png new file mode 100644 index 00000000000..1d4331b7752 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-light-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-light-linux.png new file mode 100644 index 00000000000..1ed79aaea66 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-light-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-light-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-light-tritanopia-linux.png new file mode 100644 index 00000000000..1ed79aaea66 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Default-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-colorblind-linux.png new file mode 100644 index 00000000000..380729cf417 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-dimmed-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-dimmed-linux.png new file mode 100644 index 00000000000..6ba0952ef13 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-high-contrast-linux.png new file mode 100644 index 00000000000..572b14f775c Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-linux.png new file mode 100644 index 00000000000..380729cf417 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-tritanopia-linux.png new file mode 100644 index 00000000000..380729cf417 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-light-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-light-colorblind-linux.png new file mode 100644 index 00000000000..1ed79aaea66 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-light-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-light-high-contrast-linux.png new file mode 100644 index 00000000000..1d4331b7752 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-light-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-light-linux.png new file mode 100644 index 00000000000..1ed79aaea66 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-light-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-light-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-light-tritanopia-linux.png new file mode 100644 index 00000000000..1ed79aaea66 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Dev-Default-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-colorblind-linux.png new file mode 100644 index 00000000000..775708b3e59 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-dimmed-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-dimmed-linux.png new file mode 100644 index 00000000000..691ab37f700 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-high-contrast-linux.png new file mode 100644 index 00000000000..5a59ac5cfc0 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-linux.png new file mode 100644 index 00000000000..775708b3e59 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-tritanopia-linux.png new file mode 100644 index 00000000000..775708b3e59 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-light-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-light-colorblind-linux.png new file mode 100644 index 00000000000..7ef2b17da04 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-light-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-light-high-contrast-linux.png new file mode 100644 index 00000000000..826116ad125 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-light-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-light-linux.png new file mode 100644 index 00000000000..7ef2b17da04 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-light-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-light-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-light-tritanopia-linux.png new file mode 100644 index 00000000000..7ef2b17da04 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Labelled-By-External-Element-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-colorblind-linux.png new file mode 100644 index 00000000000..a95a5472776 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-dimmed-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-dimmed-linux.png new file mode 100644 index 00000000000..07303911f0b Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-high-contrast-linux.png new file mode 100644 index 00000000000..4755127c858 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-linux.png new file mode 100644 index 00000000000..a95a5472776 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-tritanopia-linux.png new file mode 100644 index 00000000000..a95a5472776 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-light-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-light-colorblind-linux.png new file mode 100644 index 00000000000..1e9614f028d Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-light-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-light-high-contrast-linux.png new file mode 100644 index 00000000000..a6b1cc225b8 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-light-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-light-linux.png new file mode 100644 index 00000000000..1e9614f028d Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-light-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-light-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-light-tritanopia-linux.png new file mode 100644 index 00000000000..1e9614f028d Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-Selected-Tab-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-colorblind-linux.png new file mode 100644 index 00000000000..e4bbf59873f Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-dimmed-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-dimmed-linux.png new file mode 100644 index 00000000000..bccafd46ed9 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-high-contrast-linux.png new file mode 100644 index 00000000000..0a0048d51a8 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-linux.png new file mode 100644 index 00000000000..b76e862b711 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-tritanopia-linux.png new file mode 100644 index 00000000000..e4bbf59873f Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-light-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-light-colorblind-linux.png new file mode 100644 index 00000000000..39fd21dbded Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-light-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-light-high-contrast-linux.png new file mode 100644 index 00000000000..391e41a82a7 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-light-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-light-linux.png new file mode 100644 index 00000000000..39fd21dbded Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-light-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-light-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-light-tritanopia-linux.png new file mode 100644 index 00000000000..39fd21dbded Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-In-Loading-State-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-colorblind-linux.png new file mode 100644 index 00000000000..06312377557 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-dimmed-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-dimmed-linux.png new file mode 100644 index 00000000000..8b34b8686c2 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-high-contrast-linux.png new file mode 100644 index 00000000000..0b566ed6a86 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-linux.png new file mode 100644 index 00000000000..06312377557 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-tritanopia-linux.png new file mode 100644 index 00000000000..06312377557 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-light-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-light-colorblind-linux.png new file mode 100644 index 00000000000..2dc42e41db5 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-light-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-light-high-contrast-linux.png new file mode 100644 index 00000000000..259cc07ed6f Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-light-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-light-linux.png new file mode 100644 index 00000000000..2dc42e41db5 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-light-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-light-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-light-tritanopia-linux.png new file mode 100644 index 00000000000..2dc42e41db5 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Counters-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-colorblind-linux.png new file mode 100644 index 00000000000..fef8afe02db Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-dimmed-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-dimmed-linux.png new file mode 100644 index 00000000000..e3b49a50fd8 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-high-contrast-linux.png new file mode 100644 index 00000000000..e5776e97060 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-linux.png new file mode 100644 index 00000000000..fef8afe02db Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-tritanopia-linux.png new file mode 100644 index 00000000000..fef8afe02db Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-light-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-light-colorblind-linux.png new file mode 100644 index 00000000000..1258c1ed187 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-light-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-light-high-contrast-linux.png new file mode 100644 index 00000000000..30403a93e92 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-light-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-light-linux.png new file mode 100644 index 00000000000..1258c1ed187 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-light-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-light-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-light-tritanopia-linux.png new file mode 100644 index 00000000000..1258c1ed187 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-Hidden-On-Narrow-Screen-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-colorblind-linux.png new file mode 100644 index 00000000000..79b4f821f96 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-dimmed-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-dimmed-linux.png new file mode 100644 index 00000000000..2af230e86b4 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-high-contrast-linux.png new file mode 100644 index 00000000000..b3ac40e62b7 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-linux.png new file mode 100644 index 00000000000..79b4f821f96 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-tritanopia-linux.png new file mode 100644 index 00000000000..79b4f821f96 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-light-colorblind-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-light-colorblind-linux.png new file mode 100644 index 00000000000..d05768fe7ca Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-light-high-contrast-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-light-high-contrast-linux.png new file mode 100644 index 00000000000..39292cd5085 Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-light-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-light-linux.png new file mode 100644 index 00000000000..d05768fe7ca Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-light-linux.png differ diff --git a/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-light-tritanopia-linux.png b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-light-tritanopia-linux.png new file mode 100644 index 00000000000..d05768fe7ca Binary files /dev/null and b/.playwright/snapshots/components/UnderlinePanels2.test.ts-snapshots/UnderlinePanels2-With-Icons-light-tritanopia-linux.png differ diff --git a/e2e/components/UnderlinePanels2.test.ts b/e2e/components/UnderlinePanels2.test.ts new file mode 100644 index 00000000000..fddb4dd0e78 --- /dev/null +++ b/e2e/components/UnderlinePanels2.test.ts @@ -0,0 +1,59 @@ +import {test, expect} from '@playwright/test' +import {visit} from '../test-helpers/storybook' +import {themes} from '../test-helpers/themes' + +const stories: Array<{title: string; id: string}> = [ + { + title: 'Default', + id: 'experimental-components-underlinepanels2--default', + }, + { + title: 'Dev Default', + id: 'experimental-components-underlinepanels2-dev--default', + }, + { + title: 'Labelled By External Element', + id: 'experimental-components-underlinepanels2-features--labelled-by-external-element', + }, + { + title: 'Selected Tab', + id: 'experimental-components-underlinepanels2-features--selected-tab', + }, + { + title: 'With Counters', + id: 'experimental-components-underlinepanels2-features--with-counters', + }, + { + title: 'With Counters In Loading State', + id: 'experimental-components-underlinepanels2-features--with-counters-in-loading-state', + }, + { + title: 'With Icons', + id: 'experimental-components-underlinepanels2-features--with-icons', + }, + { + title: 'With Icons Hidden On Narrow Screen', + id: 'experimental-components-underlinepanels2-features--with-icons-hidden-on-narrow-screen', + }, +] + +test.describe('UnderlinePanels2', () => { + for (const story of stories) { + test.describe(story.title, () => { + for (const theme of themes) { + test.describe(theme, () => { + test('@vrt', async ({page}) => { + await visit(page, { + id: story.id, + globals: { + colorScheme: theme, + }, + }) + + await expect(page).toHaveScreenshot(`UnderlinePanels2.${story.title}.${theme}.png`) + }) + }) + } + }) + } +}) diff --git a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap index 4b6b6bbb4ad..cd1a020ee5f 100644 --- a/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap +++ b/packages/react/src/__tests__/__snapshots__/exports.test.ts.snap @@ -357,6 +357,10 @@ exports[`@primer/react/experimental > should not update exports without a semver "Tooltip", "type TooltipProps", "UnderlinePanels", + "UnderlinePanels2", + "type UnderlinePanels2PanelProps", + "type UnderlinePanels2Props", + "type UnderlinePanels2TabProps", "type UnderlinePanelsPanelProps", "type UnderlinePanelsProps", "type UnderlinePanelsTabProps", diff --git a/packages/react/src/experimental/Tabs/Tabs.tsx b/packages/react/src/experimental/Tabs/Tabs.tsx index 71fe02c0e4b..5b7fbc78451 100644 --- a/packages/react/src/experimental/Tabs/Tabs.tsx +++ b/packages/react/src/experimental/Tabs/Tabs.tsx @@ -1,7 +1,6 @@ import React, { createContext, useContext, - useId, useMemo, type AriaAttributes, type ElementRef, @@ -9,7 +8,7 @@ import React, { } from 'react' import useIsomorphicLayoutEffect from '../../utils/useIsomorphicLayoutEffect' import {useControllableState} from '../../hooks/useControllableState' -import {useProvidedRefOrCreate} from '../../hooks' +import {useId, useProvidedRefOrCreate} from '../../hooks' /** * Props to be used when the Tabs component's state is controlled by the parent @@ -53,7 +52,10 @@ type UncontrolledTabsProps = { onValueChange?: ({value}: {value: string}) => void } -type TabsProps = PropsWithChildren +type TabsProps = { + /** Base id for generating unique ids for tabs and panels */ + id?: string +} & PropsWithChildren /** * The Tabs component provides the base structure for a tabbed interface, without providing any formal requirement on DOM structure or styling. @@ -62,9 +64,9 @@ type TabsProps = PropsWithChildren * This is intended to be used in conjunction with the `useTab`, `useTabList`, and `useTabPanel` hooks to build a fully accessible tabs component. * The `Tab`, `TabList`, and `TabPanel` components are provided for convenience to showcase the API & implementation. */ -function Tabs(props: TabsProps) { +function Tabs({id, ...props}: TabsProps) { const {children, onValueChange} = props - const groupId = useId() + const groupId = useId(id) const [selectedValue, setSelectedValue] = useControllableState({ name: 'tab-selection', @@ -92,15 +94,18 @@ function Tabs(props: TabsProps) { } type Label = { + /** The accessible label for the tab list */ 'aria-label': string } type LabelledBy = { + /** The id of an external element that labels the tab list */ 'aria-labelledby': string } type Labelled = Label | LabelledBy -type TabListProps = Labelled & React.HTMLAttributes +type TabListProps = Labelled & + Pick, 'aria-orientation' | 'aria-label' | 'aria-labelledby'> function useTabList( props: TabListProps & { @@ -182,7 +187,7 @@ function useTabList( } } -function TabList({children, ...rest}: TabListProps) { +function TabList({children, ...rest}: React.PropsWithChildren>) { const {tabListProps} = useTabList(rest) return ( diff --git a/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.dev.stories.tsx b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.dev.stories.tsx new file mode 100644 index 00000000000..a41b4e4b298 --- /dev/null +++ b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.dev.stories.tsx @@ -0,0 +1,53 @@ +import type {ComponentProps} from '../../utils/types' +import type {Meta, StoryFn} from '@storybook/react-vite' +import {UnderlinePanels} from './UnderlinePanels2' + +export default { + title: 'Experimental/Components/UnderlinePanels2/Dev', + component: UnderlinePanels, + subcomponents: {Tab: UnderlinePanels.Tab, Panel: UnderlinePanels.Panel, TabList: UnderlinePanels.TabList}, +} as Meta> + +export const Default = () => ( + + + Tab 1 + Tab 2 + Tab 3 + + Panel 1 + Panel 2 + Panel 3 + +) + +export const SingleTabPlayground: StoryFn> = args => { + return ( + + + + Users + + + Users Panel + + ) +} + +SingleTabPlayground.args = { + counter: '14K', + disabled: false, +} + +SingleTabPlayground.argTypes = { + disabled: { + control: { + type: 'boolean', + }, + }, + counter: { + control: { + type: 'text', + }, + }, +} diff --git a/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.docs.json b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.docs.json new file mode 100644 index 00000000000..687cfa799bc --- /dev/null +++ b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.docs.json @@ -0,0 +1,141 @@ +{ + "id": "underline_panels2", + "name": "UnderlinePanels2", + "status": "draft", + "a11yReviewed": false, + "stories": [ + { + "id": "experimental-components-underlinepanels2--default" + }, + { + "id": "experimental-components-underlinepanels2-features--labelled-by-external-element" + }, + { + "id": "experimental-components-underlinepanels2-features--selected-tab" + }, + { + "id": "experimental-components-underlinepanels2-features--with-counters" + }, + { + "id": "experimental-components-underlinepanels2-features--with-counters-in-loading-state" + }, + { + "id": "experimental-components-underlinepanels2-features--with-icons" + }, + { + "id": "experimental-components-underlinepanels2-features--with-icons-hidden-on-narrow-screen" + } + ], + "importPath": "@primer/react/experimental", + "props": [ + { + "name": "id", + "type": "string", + "derive": true + }, + { + "name": "value", + "type": "string", + "derive": true + }, + { + "name": "defaultValue", + "type": "string", + "derive": true + }, + { + "name": "onValueChange", + "derive": true + }, + { + "name": "children", + "type": "React.ReactNode", + "derive": true + }, + { + "name": "loadingCounters", + "type": "boolean", + "derive": true + } + ], + "subcomponents": [ + { + "name": "UnderlinePanels2.TabList", + "props": [ + { + "name": "aria-label", + "type": "string", + "derive": true + }, + { + "name": "aria-labelledby", + "type": "string", + "derive": true + }, + { + "name": "children", + "type": "React.ReactNode", + "derive": true + }, + { + "name": "ref", + "type": "React.Ref", + "derive": true + } + ], + "passthrough": { + "element": "ul", + "url": "https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul#Attributes" + } + }, + { + "name": "UnderlinePanels2.Tab", + "props": [ + { + "name": "value", + "type": "string", + "derive": true + }, + { + "name": "counter", + "type": "number | string", + "derive": true + }, + { + "name": "disabled", + "type": "boolean", + "derive": true + }, + { + "name": "icon", + "type": "Icon", + "derive": true + }, + { + "name": "children", + "type": "React.ReactNode", + "derive": true + } + ] + }, + { + "name": "UnderlinePanels2.Panel", + "props": [ + { + "name": "value", + "type": "string", + "derive": true + }, + { + "name": "children", + "type": "React.ReactNode", + "derive": true + } + ], + "passthrough": { + "element": "div", + "url": "https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div#Attributes" + } + } + ] +} diff --git a/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.features.stories.tsx b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.features.stories.tsx new file mode 100644 index 00000000000..e6068436052 --- /dev/null +++ b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.features.stories.tsx @@ -0,0 +1,161 @@ +import type {Meta} from '@storybook/react-vite' +import {INITIAL_VIEWPORTS} from 'storybook/viewport' +import {UnderlinePanels} from './UnderlinePanels2' +import type {ComponentProps} from '../../utils/types' +import { + CodeIcon, + CommentDiscussionIcon, + EyeIcon, + GearIcon, + GitPullRequestIcon, + GraphIcon, + PlayIcon, + ProjectIcon, + ShieldLockIcon, +} from '@primer/octicons-react' + +export default { + title: 'Experimental/Components/UnderlinePanels2/Features', + component: UnderlinePanels, +} as Meta> + +export const SelectedTab = () => ( + + + Tab 1 + Tab 2 + Tab 3 + + Panel 1 + Panel 2 + Panel 3 + +) + +export const LabelledByExternalElement = () => ( + <> +

UnderlinePanels example

+ + + Tab 1 + Tab 2 + Tab 3 + + Panel 1 + Panel 2 + Panel 3 + + +) + +export const WithIcons = () => ( + + + + Tab 1 + + + Tab 2 + + + Tab 3 + + + Panel 1 + Panel 2 + Panel 3 + +) + +export const WithIconsHiddenOnNarrowScreen = () => ( + + + + Tab 1 + + + Tab 2 + + + Tab 3 + + + Tab 4 + + + Tab 5 + + + Tab 6 + + + Tab 7 + + + Tab 8 + + + Tab 9 + + + Panel 1 + Panel 2 + Panel 3 + Panel 4 + Panel 5 + Panel 6 + Panel 7 + Panel 8 + Panel 9 + +) + +WithIconsHiddenOnNarrowScreen.parameters = { + viewport: { + viewports: { + ...INITIAL_VIEWPORTS, + narrowScreen: { + name: 'Narrow Screen', + styles: { + width: '800px', + height: '100%', + }, + }, + }, + defaultViewport: 'narrowScreen', + }, +} + +export const WithCounters = () => { + return ( + + + + Tab 1 + + + Tab 2 + + + Panel 1 + Panel 2 + + ) +} + +export const WithCountersInLoadingState = () => { + return ( + + + + Tab 1 + + + Tab 2 + + + Panel 1 + Panel 2 + + ) +} diff --git a/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.module.css b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.module.css new file mode 100644 index 00000000000..9e4905c2c7f --- /dev/null +++ b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.module.css @@ -0,0 +1,10 @@ +.StyledUnderlineWrapper { + width: 100%; + overflow-x: auto; + overflow-y: hidden; + -webkit-overflow-scrolling: auto; +} + +.StyledUnderlineWrapper[data-icons-visible='false'] [data-component='icon'] { + display: none; +} diff --git a/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.stories.tsx b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.stories.tsx new file mode 100644 index 00000000000..fd647570820 --- /dev/null +++ b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.stories.tsx @@ -0,0 +1,81 @@ +import type {Meta, StoryFn} from '@storybook/react-vite' +import {UnderlinePanels} from './UnderlinePanels2' + +const meta: Meta = { + title: 'Experimental/Components/UnderlinePanels2', + component: UnderlinePanels, + parameters: { + controls: { + expanded: true, + }, + }, + argTypes: { + id: { + type: { + name: 'string', + }, + }, + defaultValue: { + type: { + required: true, + name: 'string', + }, + }, + loadingCounters: { + control: { + type: 'boolean', + }, + }, + }, + args: { + id: 'test', + loadingCounters: false, + defaultValue: 'tab-0', + }, +} + +export default meta + +export const Default: StoryFn = () => { + const tabs = ['Tab 1', 'Tab 2', 'Tab 3'] + const panels = ['Panel 1', 'Panel 2', 'Panel 3'] + + return ( + + + {tabs.map((tab: string, index: number) => ( + + {tab} + + ))} + + {panels.map((panel: string, index: number) => ( + + {panel} + + ))} + + ) +} + +export const Playground: StoryFn = args => { + const tabs = ['Tab 1', 'Tab 2', 'Tab 3'] + const panels = ['Panel 1', 'Panel 2', 'Panel 3'] + + return ( + + + {tabs.map((tab: string, index: number) => ( + + {tab} + + ))} + + {panels.map((panel: string, index: number) => ( + + {panel} + + ))} + + ) +} diff --git a/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.test.tsx b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.test.tsx new file mode 100644 index 00000000000..18a45df54c6 --- /dev/null +++ b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.test.tsx @@ -0,0 +1,140 @@ +import ReactDOMServer from 'react-dom/server' +import {render, screen} from '@testing-library/react' +import {describe, it, expect, vi} from 'vitest' +import {UnderlinePanels, type UnderlinePanelsTabListProps} from './UnderlinePanels2' +import {userEvent} from 'vitest/browser' + +const UnderlinePanelsMockComponent = ({id, ...rest}: {id?: string} & Omit) => ( + + + Tab 1 + Tab 2 + Tab 3 + + Panel 1 + Panel 2 + Panel 3 + +) + +describe('UnderlinePanels', () => { + it('renders with a custom ID', () => { + render() + + const firstTab = screen.getByRole('tab', {name: 'Tab 1'}) + const firstPanel = screen.getByText('Panel 1') + + expect(firstTab).toHaveAttribute('id', 'custom-id-tab-tab-1') + expect(firstPanel).toHaveAttribute('aria-labelledby', 'custom-id-tab-tab-1') + }) + it('renders aria-label', () => { + render() + + const tabList = screen.getByRole('tablist') + expect(tabList).toHaveAccessibleName('Select a tab') + }) + it('renders aria-labelledby', () => { + render( + <> +

Select a tab

+ + , + ) + + const tabList = screen.getByRole('tablist') + expect(tabList).toHaveAccessibleName('Select a tab') + }) + it('updates the selected tab when aria-selected changes', () => { + const {rerender} = render( + {}}> + + Tab 1 + Tab 2 + + Panel 1 + Panel 2 + , + ) + + // Verify that the first tab is selected and second tab is not + let firstTab = screen.getByRole('tab', {name: 'Tab 1'}) + let secondTab = screen.getByRole('tab', {name: 'Tab 2'}) + + expect(firstTab).toHaveAttribute('aria-selected', 'true') + expect(secondTab).toHaveAttribute('aria-selected', 'false') + + // Programmatically select the second tab by updating the value prop + rerender( + {}}> + + Tab 1 + Tab 2 + + Panel 1 + Panel 2 + , + ) + + // Verify the updated aria-selected prop changes which tab is selected + firstTab = screen.getByRole('tab', {name: 'Tab 1'}) + secondTab = screen.getByRole('tab', {name: 'Tab 2'}) + + expect(firstTab).toHaveAttribute('aria-selected', 'false') + expect(secondTab).toHaveAttribute('aria-selected', 'true') + }) + it('calls onSelect when a tab is clicked', async () => { + const onValueChange = vi.fn() + const user = userEvent.setup() + + render( + + + Tab 1 + Tab 2 + + Panel 1 + Panel 2 + , + ) + + await user.click(await screen.findByText('Tab 1')) + + expect(onValueChange).toHaveBeenCalledWith({value: 'tab-1'}) + }) + + it('should support `className` on the outermost element', () => { + const Element = () => ( + + + Tab 1 + Tab 2 + + Panel 1 + Panel 2 + + ) + + const {container} = render() + + expect(container.firstElementChild).toHaveClass('test-class-name') + }) + + describe('SSR', () => { + it('renders correctly on server and hydrates without id mismatch', () => { + const element = + + const container = document.createElement('div') + document.body.appendChild(container) + const htmlString = ReactDOMServer.renderToString(element) + + container.innerHTML = htmlString + render(element, {hydrate: true, container}) + + const firstTab = screen.getByRole('tab', {name: 'Tab 1'}) + const firstPanel = screen.getByText('Panel 1') + + expect(firstTab).toBeInTheDocument() + expect(firstPanel).toBeInTheDocument() + }) + }) +}) diff --git a/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.tsx b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.tsx new file mode 100644 index 00000000000..12fba8969fc --- /dev/null +++ b/packages/react/src/experimental/UnderlinePanels2/UnderlinePanels2.tsx @@ -0,0 +1,170 @@ +import {createContext, useContext, useMemo, useRef, useState} from 'react' +import type {Icon} from '@primer/octicons-react' +import type {TabListProps, TabsProps} from '../Tabs' +import {clsx} from 'clsx' +import styles from './UnderlinePanels2.module.css' +import {Tabs, useTab, useTabList, useTabPanel} from '../Tabs' +import {UnderlineItem, UnderlineItemList, UnderlineWrapper} from '../../internal/components/UnderlineTabbedInterface' +import useIsomorphicLayoutEffect from '../../utils/useIsomorphicLayoutEffect' +import {useResizeObserver, type ResizeObserverEntry} from '../../hooks/useResizeObserver' + +export type UnderlinePanelsProps = TabsProps & { + /** + * Custom prefix to use when generating the IDs of tabs and `aria-labelledby` for the panels + */ + id?: string + + /** + * Whether to show loading state for counters in tabs. Used when counter values are being fetched to prevent layout shifts. + * @default false + */ + loadingCounters?: boolean + + /** + * A single TabList (UnderlinePanels.TabList) and panels (UnderlinePanels.Panel) to render + */ + children: React.ReactNode +} + +export function UnderlinePanels({children, loadingCounters, ...rest}: UnderlinePanelsProps) { + const [iconsVisible, setIconsVisible] = useState(true) + const contextValue = useMemo( + () => ({loadingCounters: loadingCounters ?? false, iconsVisible, setIconsVisible}), + [loadingCounters, iconsVisible], + ) + + return ( + + {children} + + ) +} + +interface UnderlinePanelsContextType { + loadingCounters: boolean + iconsVisible: boolean + setIconsVisible: (visible: boolean) => void +} + +const UnderlinePanelsContext = createContext(undefined) + +export type UnderlinePanelsTabListProps = TabListProps & { + /** + * A list of UnderlinePanels.Tab components + */ + children: React.ReactNode +} & React.HTMLAttributes + +function UnderlinePanelsTabList({className, children, ...props}: UnderlinePanelsTabListProps) { + const listRef = useRef(null) + const wrapperRef = useRef(null) + const {tabListProps} = useTabList({ + ref: listRef, + ...props, + }) + const panelsContext = useContext(UnderlinePanelsContext) + const [listWidth, setListWidth] = useState(0) + + useIsomorphicLayoutEffect(() => { + setListWidth(listRef.current?.getBoundingClientRect().width ?? 0) + }, []) + + useResizeObserver( + (resizeObserverEntries: ResizeObserverEntry[]) => { + const wrapperWidth = resizeObserverEntries[0].contentRect.width + panelsContext?.setIconsVisible(wrapperWidth > listWidth) + }, + wrapperRef, + [], + ) + + return ( + + {children} + + ) +} + +UnderlinePanels.TabList = UnderlinePanelsTabList +UnderlinePanelsTabList.displayName = 'UnderlinePanels.TabList' +UnderlinePanelsTabList.__SLOT__ = Symbol('UnderlinePanels.TabList') + +export type UnderlinePanelsTabProps = { + /** + * Specify whether the tab is disabled + * @default false + */ + disabled?: boolean + + /** + * Provide a value that uniquely identifies the tab. + * This should mirror the value provided to the corresponding TabPanel + */ + value: string + + /** + * Content of CounterLabel rendered after tab text label + */ + counter?: number | string + + /** + * Icon rendered before the tab text label + */ + icon?: Icon + + /** + * Content of the tab + */ + children: React.ReactNode +} + +function UnderlinePanelsTab({children, ...props}: UnderlinePanelsTabProps) { + const {tabProps} = useTab(props) + + const panelsContext = useContext(UnderlinePanelsContext) + const loadingCounters = panelsContext?.loadingCounters ?? false + + return ( + + {children} + + ) +} + +UnderlinePanels.Tab = UnderlinePanelsTab +UnderlinePanelsTab.displayName = 'UnderlinePanels.Tab' +UnderlinePanelsTab.__SLOT__ = Symbol('UnderlinePanels.Tab') + +export type UnderlinePanelsPanelProps = { + /** + * Provide a value that uniquely identifies the tab panel. This should mirror + * the value set for the corresponding tab + */ + value: string + + /** + * Content of the panel + */ + children: React.ReactNode +} + +function UnderlinePanelsPanel({value, ...rest}: UnderlinePanelsPanelProps) { + const {tabPanelProps} = useTabPanel({value}) + + return
+} + +UnderlinePanels.Panel = UnderlinePanelsPanel +UnderlinePanelsPanel.displayName = 'UnderlinePanels.Panel' +UnderlinePanelsPanel.__SLOT__ = Symbol('UnderlinePanels.Panel') diff --git a/packages/react/src/experimental/UnderlinePanels2/index.ts b/packages/react/src/experimental/UnderlinePanels2/index.ts new file mode 100644 index 00000000000..bd4a2674010 --- /dev/null +++ b/packages/react/src/experimental/UnderlinePanels2/index.ts @@ -0,0 +1,3 @@ +export {UnderlinePanels} from './UnderlinePanels2' +export {UnderlinePanels as UnderlinePanels2} from './UnderlinePanels2' +export type {UnderlinePanelsProps, UnderlinePanelsTabProps, UnderlinePanelsPanelProps} from './UnderlinePanels2' diff --git a/packages/react/src/experimental/index.ts b/packages/react/src/experimental/index.ts index c706f004efd..2766fa5003b 100644 --- a/packages/react/src/experimental/index.ts +++ b/packages/react/src/experimental/index.ts @@ -78,6 +78,13 @@ export type {AnnounceProps, AriaStatusProps, AriaAlertProps} from '../live-regio export {UnderlinePanels} from './UnderlinePanels' export type {UnderlinePanelsProps, UnderlinePanelsTabProps, UnderlinePanelsPanelProps} from './UnderlinePanels' +export {UnderlinePanels as UnderlinePanels2} from './UnderlinePanels2' +export type { + UnderlinePanelsProps as UnderlinePanels2Props, + UnderlinePanelsTabProps as UnderlinePanels2TabProps, + UnderlinePanelsPanelProps as UnderlinePanels2PanelProps, +} from './UnderlinePanels2' + export {SkeletonBox} from '../Skeleton' export type {SkeletonBoxProps} from '../Skeleton' export {SkeletonText} from '../SkeletonText'