diff --git a/.changeset/breezy-boxes-jog.md b/.changeset/breezy-boxes-jog.md new file mode 100644 index 00000000000..bce0b690f8f --- /dev/null +++ b/.changeset/breezy-boxes-jog.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +Changes the accessible name of the "toggle" button in `LabelGroup` to contain the visual label diff --git a/.changeset/fuzzy-jobs-deny.md b/.changeset/fuzzy-jobs-deny.md new file mode 100644 index 00000000000..4a63867dc87 --- /dev/null +++ b/.changeset/fuzzy-jobs-deny.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +Add missing `wide` CSS + className to Stack diff --git a/.changeset/olive-donkeys-exercise.md b/.changeset/olive-donkeys-exercise.md new file mode 100644 index 00000000000..638d5ac14ba --- /dev/null +++ b/.changeset/olive-donkeys-exercise.md @@ -0,0 +1,5 @@ +--- +"@primer/react": major +--- + +Refactor ButtonBase component to use CSS modules behine flag diff --git a/.changeset/spicy-eggs-melt.md b/.changeset/spicy-eggs-melt.md new file mode 100644 index 00000000000..d2708ac8eb7 --- /dev/null +++ b/.changeset/spicy-eggs-melt.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +Banner: Update alignment of actions when it is dismissible and has a hidden title diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-colorblind-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-colorblind-linux.png new file mode 100644 index 00000000000..07a1b9a0764 Binary files /dev/null and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-dimmed-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-dimmed-linux.png new file mode 100644 index 00000000000..a0ec27362de Binary files /dev/null and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-high-contrast-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-high-contrast-linux.png new file mode 100644 index 00000000000..9e349c0ed8d Binary files /dev/null and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-linux.png new file mode 100644 index 00000000000..07a1b9a0764 Binary files /dev/null and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-tritanopia-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-tritanopia-linux.png new file mode 100644 index 00000000000..07a1b9a0764 Binary files /dev/null and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-colorblind-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-colorblind-linux.png new file mode 100644 index 00000000000..8c20a8ef9cf Binary files /dev/null and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-high-contrast-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-high-contrast-linux.png new file mode 100644 index 00000000000..554d38cc4ac Binary files /dev/null and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-linux.png new file mode 100644 index 00000000000..8c20a8ef9cf Binary files /dev/null and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-tritanopia-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-tritanopia-linux.png new file mode 100644 index 00000000000..8c20a8ef9cf Binary files /dev/null and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-primer-breakpoint-sm-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-primer-breakpoint-sm-linux.png new file mode 100644 index 00000000000..f196708ecc9 Binary files /dev/null and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-primer-breakpoint-sm-linux.png differ diff --git a/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-primer-breakpoint-xs-linux.png b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-primer-breakpoint-xs-linux.png new file mode 100644 index 00000000000..403db9eb7e2 Binary files /dev/null and b/.playwright/snapshots/components/Banner.test.ts-snapshots/Banner-DismissibleWithHiddenTitleAndActions-primer-breakpoint-xs-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-colorblind-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-colorblind-linux.png index bca6d94948f..c9147dd9b64 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-colorblind-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-dimmed-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-dimmed-linux.png index b250d764e77..f461d4455f2 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-dimmed-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-high-contrast-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-high-contrast-linux.png index 621a3409bc3..efae7629edb 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-high-contrast-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-linux.png index 3ac278df745..177fc0ec2f0 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-tritanopia-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-tritanopia-linux.png index 3ac278df745..177fc0ec2f0 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-tritanopia-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-colorblind-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-colorblind-linux.png index 75fda8d9f8d..bed2e0e9f77 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-colorblind-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-high-contrast-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-high-contrast-linux.png index 2bcdecf16a3..ef4cd37a781 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-high-contrast-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-linux.png index 8caabbe4b8f..fdadbace764 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-tritanopia-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-tritanopia-linux.png index 8caabbe4b8f..fdadbace764 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-tritanopia-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Danger-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-colorblind-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-colorblind-linux.png index ed125d806c8..7f78663535e 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-colorblind-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-dimmed-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-dimmed-linux.png index b931a79c279..6de69e08ec6 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-dimmed-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-high-contrast-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-high-contrast-linux.png index c8a61d2913d..5ccb5bc908c 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-high-contrast-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-linux.png index ed125d806c8..7f78663535e 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-tritanopia-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-tritanopia-linux.png index ed125d806c8..7f78663535e 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-tritanopia-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-colorblind-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-colorblind-linux.png index 9714531b5ee..6bb59c1151a 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-colorblind-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-high-contrast-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-high-contrast-linux.png index 9869a984823..ca43a5df5c3 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-high-contrast-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-linux.png index 9714531b5ee..6bb59c1151a 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-tritanopia-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-tritanopia-linux.png index 9714531b5ee..6bb59c1151a 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-tritanopia-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Full-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-colorblind-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-colorblind-linux.png index 0fd64df8cf0..5f192c40232 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-colorblind-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-dimmed-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-dimmed-linux.png index d63ec575223..fa650e1adfa 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-dimmed-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-high-contrast-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-high-contrast-linux.png index f24be3e60b7..f942c246d4c 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-high-contrast-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-linux.png index 4cf4d1aa994..1a8ec199622 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-tritanopia-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-tritanopia-linux.png index 0fd64df8cf0..5f192c40232 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-tritanopia-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-colorblind-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-colorblind-linux.png index 09e1ec8165b..8ec99419cc2 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-colorblind-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-high-contrast-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-high-contrast-linux.png index 47e8b267d81..f605a38b5cc 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-high-contrast-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-linux.png index 0d34bf701db..d7e242f5903 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-tritanopia-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-tritanopia-linux.png index 09e1ec8165b..8ec99419cc2 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-tritanopia-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Success-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-colorblind-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-colorblind-linux.png index ca4b7c0f1da..ca726620fc5 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-colorblind-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-dimmed-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-dimmed-linux.png index 07e1e25cb53..a02b3bc2a9f 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-dimmed-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-high-contrast-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-high-contrast-linux.png index b0eb3b9bb87..b357628902f 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-high-contrast-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-linux.png index ca4b7c0f1da..ca726620fc5 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-tritanopia-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-tritanopia-linux.png index ca4b7c0f1da..ca726620fc5 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-tritanopia-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-colorblind-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-colorblind-linux.png index 28ad801a9b8..d4e8bdad71e 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-colorblind-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-high-contrast-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-high-contrast-linux.png index 51f2a72a28a..bdaa12e76ef 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-high-contrast-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-linux.png index 28ad801a9b8..d4e8bdad71e 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-linux.png differ diff --git a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-tritanopia-linux.png b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-tritanopia-linux.png index 28ad801a9b8..d4e8bdad71e 100644 Binary files a/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-tritanopia-linux.png and b/.playwright/snapshots/components/Flash.test.ts-snapshots/Flash-Warning-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-colorblind-linux.png b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-colorblind-linux.png index bcd67e76e54..5fb38048303 100644 Binary files a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-colorblind-linux.png and b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-dimmed-linux.png b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-dimmed-linux.png index d8ba4fe4247..2b8a40b09e4 100644 Binary files a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-dimmed-linux.png and b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-high-contrast-linux.png b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-high-contrast-linux.png index 97c3d29d9b5..9ebfcfa0eed 100644 Binary files a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-high-contrast-linux.png and b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-linux.png b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-linux.png index bcd67e76e54..5fb38048303 100644 Binary files a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-linux.png and b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-linux.png differ diff --git a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-tritanopia-linux.png b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-tritanopia-linux.png index bcd67e76e54..5fb38048303 100644 Binary files a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-tritanopia-linux.png and b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-colorblind-linux.png b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-colorblind-linux.png index d28b3947ac2..bfdbc32b377 100644 Binary files a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-colorblind-linux.png and b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-high-contrast-linux.png b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-high-contrast-linux.png index 00b7291867f..c55304bc742 100644 Binary files a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-high-contrast-linux.png and b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-linux.png b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-linux.png index d28b3947ac2..bfdbc32b377 100644 Binary files a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-linux.png and b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-linux.png differ diff --git a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-tritanopia-linux.png b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-tritanopia-linux.png index d28b3947ac2..bfdbc32b377 100644 Binary files a/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-tritanopia-linux.png and b/.playwright/snapshots/components/Pagehead.test.ts-snapshots/Pagehead-Default-light-tritanopia-linux.png differ diff --git a/.vscode/settings.json b/.vscode/settings.json index eb183dfaed1..f92d3119fd1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,6 +10,13 @@ "[typescriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, + "[postcss]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.stylelint": "explicit" + } + }, "json.schemas": [ { "fileMatch": ["*.docs.json"], diff --git a/e2e/components/Banner.test.ts b/e2e/components/Banner.test.ts index 8182e8fe20f..6efdde8d40c 100644 --- a/e2e/components/Banner.test.ts +++ b/e2e/components/Banner.test.ts @@ -51,6 +51,11 @@ const stories: Array<{title: string; id: string; viewports?: Array { - test.describe('Playground', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton--playground', - globals: { - colorScheme: theme, - }, + for (const featureFlagOn of [true, false]) { + test.describe(`Feature flag: ${featureFlagOn ? 'on' : 'off'}`, () => { + test.describe('Playground', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton--playground', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Playground.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton--playground', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Playground.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton--playground', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + } }) - } - }) - - test.describe('Danger', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--danger', - globals: { - colorScheme: theme, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Danger.${theme}.png`) - }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--danger', - globals: { - colorScheme: theme, - }, + test.describe('Danger', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--danger', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Danger.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--danger', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + } }) - } - }) - - test.describe('Default', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton--default', - globals: { - colorScheme: theme, - }, - }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Default.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton--default', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, + test.describe('Default', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton--default', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Default.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton--default', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) - }) + } }) - } - }) - - test.describe('Disabled', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--disabled', - globals: { - colorScheme: theme, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Disabled.${theme}.png`) - }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--disabled', - globals: { - colorScheme: theme, - }, + test.describe('Disabled', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--disabled', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Disabled.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--disabled', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + } }) - } - }) - - test.describe('Invisible', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--invisible', - globals: { - colorScheme: theme, - }, - }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Invisible.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--invisible', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, + test.describe('Invisible', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--invisible', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Invisible.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--invisible', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) - }) + } }) - } - }) - - test.describe('Large', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--large', - globals: { - colorScheme: theme, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Large.${theme}.png`) - }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--large', - globals: { - colorScheme: theme, - }, + test.describe('Large', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--large', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Large.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--large', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + } }) - } - }) - - test.describe('Medium', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--medium', - globals: { - colorScheme: theme, - }, - }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Medium.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--medium', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, + test.describe('Medium', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--medium', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Medium.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--medium', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) - }) + } }) - } - }) - - test.describe('Primary', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--primary', - globals: { - colorScheme: theme, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Primary.${theme}.png`) - }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--primary', - globals: { - colorScheme: theme, - }, + test.describe('Primary', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--primary', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Primary.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--primary', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + } }) - } - }) - - test.describe('Small', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--small', - globals: { - colorScheme: theme, - }, - }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`IconButton.Small.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--small', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, + test.describe('Small', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--small', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`IconButton.Small.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--small', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) }) - }) + } }) - } - }) - test.describe('Keyshortcuts', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--keyshortcuts', - globals: { - colorScheme: theme, - }, + test.describe('Keyshortcuts', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--keyshortcuts', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + await page.keyboard.press('Tab') // focus on icon button + expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( + `IconButton.Keyshortcuts.${theme}.png`, + ) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--keyshortcuts', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await page.keyboard.press('Tab') // focus on icon button + await expect(page).toHaveNoViolations() + }) }) - - // Default state - await page.keyboard.press('Tab') // focus on icon button - expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( - `IconButton.Keyshortcuts.${theme}.png`, - ) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--keyshortcuts', - globals: { - colorScheme: theme, - }, - }) - await page.keyboard.press('Tab') // focus on icon button - await expect(page).toHaveNoViolations() - }) + } }) - } - }) - - test.describe('Keyshortcuts on Description', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--keyshortcuts-on-description', - globals: { - colorScheme: theme, - }, - }) - // Default state - await page.keyboard.press('Tab') // focus on icon button - expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( - `IconButton.Keyshortcuts on Description.${theme}.png`, - ) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-iconbutton-features--keyshortcuts-on-description', - globals: { - colorScheme: theme, - }, + test.describe('Keyshortcuts on Description', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--keyshortcuts-on-description', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + await page.keyboard.press('Tab') // focus on icon button + expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( + `IconButton.Keyshortcuts on Description.${theme}.png`, + ) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-iconbutton-features--keyshortcuts-on-description', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await page.keyboard.press('Tab') // focus on icon button + await expect(page).toHaveNoViolations() + }) }) - await page.keyboard.press('Tab') // focus on icon button - await expect(page).toHaveNoViolations() - }) + } }) - } - }) + }) + } }) diff --git a/e2e/components/LinkButton.test.ts b/e2e/components/LinkButton.test.ts index 98a92c22704..962761f750f 100644 --- a/e2e/components/LinkButton.test.ts +++ b/e2e/components/LinkButton.test.ts @@ -3,377 +3,447 @@ import {visit} from '../test-helpers/storybook' import {themes} from '../test-helpers/themes' test.describe('LinkButton', () => { - test.describe('Playground', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton--playground', - globals: { - colorScheme: theme, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Playground.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton--playground', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + for (const featureFlagOn of [true, false]) { + test.describe(`Feature flag: ${featureFlagOn ? 'on' : 'off'}`, () => { + test.describe('Playground', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton--playground', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Playground.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton--playground', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) + }) + } }) - } - }) - - test.describe('Danger', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--danger', - globals: { - colorScheme: theme, - }, - }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Danger.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--danger', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test.describe('Danger', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--danger', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Danger.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--danger', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) + }) + } }) - } - }) - - test.describe('Default', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton--default', - globals: { - colorScheme: theme, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Default.${theme}.png`) - }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton--default', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test.describe('Default', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton--default', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Default.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton--default', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) + }) + } }) - } - }) - - test.describe('Invisible', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--invisible', - globals: { - colorScheme: theme, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Invisible.${theme}.png`) - }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--invisible', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test.describe('Invisible', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--invisible', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Invisible.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--invisible', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) + }) + } }) - } - }) - - test.describe('Large', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--large', - globals: { - colorScheme: theme, - }, - }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Large.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--large', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test.describe('Large', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--large', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Large.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--large', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) + }) + } }) - } - }) - - test.describe('Leading Visual', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--leading-visual', - globals: { - colorScheme: theme, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Leading Visual.${theme}.png`) - }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--leading-visual', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test.describe('Leading Visual', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--leading-visual', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Leading Visual.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--leading-visual', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) + }) + } }) - } - }) - - test.describe('Medium', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--medium', - globals: { - colorScheme: theme, - }, - }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Medium.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--medium', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test.describe('Medium', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--medium', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Medium.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--medium', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) + }) + } }) - } - }) - - test.describe('Primary', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--primary', - globals: { - colorScheme: theme, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Primary.${theme}.png`) - }) - test.fixme('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--primary', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test.describe('Primary', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--primary', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Primary.${theme}.png`) + }) + + test.fixme('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--primary', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) + }) + } }) - } - }) - - test.describe('Small', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--small', - globals: { - colorScheme: theme, - }, - }) - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Small.${theme}.png`) - }) - - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--small', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test.describe('Small', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--small', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Small.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--small', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) + }) + } }) - } - }) - - test.describe('Trailing Visual', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--trailing-visual', - globals: { - colorScheme: theme, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Trailing Visual.${theme}.png`) - }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--trailing-visual', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test.describe('Trailing Visual', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--trailing-visual', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.Trailing Visual.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--trailing-visual', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) + }) + } }) - } - }) - - test.describe('With React Router', () => { - for (const theme of themes) { - test.describe(theme, () => { - test('default @vrt', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--with-react-router', - globals: { - colorScheme: theme, - }, - }) - - // Default state - expect(await page.screenshot()).toMatchSnapshot(`LinkButton.With React Router.${theme}.png`) - }) - test('axe @aat', async ({page}) => { - await visit(page, { - id: 'components-linkbutton-features--with-react-router', - globals: { - colorScheme: theme, - }, - }) - await expect(page).toHaveNoViolations({ - rules: { - 'color-contrast': { - enabled: theme !== 'dark_dimmed', - }, - }, - }) - }) + test.describe('With React Router', () => { + for (const theme of themes) { + test.describe(theme, () => { + test('default @vrt', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--with-react-router', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + + // Default state + expect(await page.screenshot()).toMatchSnapshot(`LinkButton.With React Router.${theme}.png`) + }) + + test('axe @aat', async ({page}) => { + await visit(page, { + id: 'components-linkbutton-features--with-react-router', + globals: { + colorScheme: theme, + featureFlags: { + primer_react_css_modules_team: featureFlagOn, + }, + }, + }) + await expect(page).toHaveNoViolations({ + rules: { + 'color-contrast': { + enabled: theme !== 'dark_dimmed', + }, + }, + }) + }) + }) + } }) - } - }) + }) + } }) diff --git a/package-lock.json b/package-lock.json index 152a8075b0c..f17bb879c38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1708,11 +1708,13 @@ } }, "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.24.1", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", + "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -9836,15 +9838,17 @@ "license": "ISC" }, "node_modules/@vitejs/plugin-react": { - "version": "4.2.1", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz", + "integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.23.5", - "@babel/plugin-transform-react-jsx-self": "^7.23.3", - "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@babel/core": "^7.24.5", + "@babel/plugin-transform-react-jsx-self": "^7.24.5", + "@babel/plugin-transform-react-jsx-source": "^7.24.1", "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.0" + "react-refresh": "^0.14.2" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -26871,7 +26875,9 @@ } }, "node_modules/react-refresh": { - "version": "0.14.0", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", "dev": true, "license": "MIT", "engines": { @@ -34214,6 +34220,7 @@ "@types/react-test-renderer": "18.3.0", "@types/semver": "7.5.8", "@types/styled-components": "^5.1.26", + "@vitejs/plugin-react": "4.3.1", "ajv": "8.16.0", "axe-core": "4.9.1", "babel-core": "7.0.0-bridge.0", diff --git a/packages/react/.storybook/main.ts b/packages/react/.storybook/main.ts index 068623bed8d..3cd7c2ffcaf 100644 --- a/packages/react/.storybook/main.ts +++ b/packages/react/.storybook/main.ts @@ -1,5 +1,6 @@ import {createRequire} from 'node:module' import path from 'node:path' +import react from '@vitejs/plugin-react' import postcssPresetPrimer from 'postcss-preset-primer' import type {StorybookConfig} from '@storybook/react-vite' @@ -48,12 +49,14 @@ const config: StorybookConfig = { }, } + config.plugins = [...(config.plugins ?? []), react()] + return config }, } export default config -function getAbsolutePath(value) { +function getAbsolutePath(value: string) { return path.dirname(require.resolve(path.join(value, 'package.json'))) } diff --git a/packages/react/.storybook/storybook.css b/packages/react/.storybook/storybook.css index b495d3c6b23..21e5d2d88b4 100644 --- a/packages/react/.storybook/storybook.css +++ b/packages/react/.storybook/storybook.css @@ -54,3 +54,7 @@ font: var(--text-caption-shorthand); margin: 0; } + +.testCustomClassname { + color: var(--fgColor-sponsors); +} diff --git a/packages/react/package.json b/packages/react/package.json index 7b9331e71c5..a269875753a 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -163,6 +163,7 @@ "@types/react-test-renderer": "18.3.0", "@types/semver": "7.5.8", "@types/styled-components": "^5.1.26", + "@vitejs/plugin-react": "^4.3.1", "ajv": "8.16.0", "axe-core": "4.9.1", "babel-core": "7.0.0-bridge.0", diff --git a/packages/react/src/ActionMenu/ActionMenu.figma.tsx b/packages/react/src/ActionMenu/ActionMenu.figma.tsx new file mode 100644 index 00000000000..3e2f971401e --- /dev/null +++ b/packages/react/src/ActionMenu/ActionMenu.figma.tsx @@ -0,0 +1,28 @@ +import React from 'react' +import {ActionMenu} from '../../src' +import figma from '@figma/code-connect' + +figma.connect( + ActionMenu, + 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=26998-2424&t=GFf1GorpZXk4F8Mq-4', + { + props: { + trigger: figma.children('trigger'), + open: figma.boolean('open'), + align: figma.enum('align', { + right: 'end', + left: 'start', + center: 'center', + }), + actionList: figma.nestedProps('ActionMenu/Content', { + items: figma.children('*'), + }), + }, + example: ({trigger, open, align, actionList}) => ( + + {trigger} + {actionList.items} + + ), + }, +) diff --git a/packages/react/src/Banner/Banner.features.stories.tsx b/packages/react/src/Banner/Banner.features.stories.tsx index 04f98d78948..1d1123d5260 100644 --- a/packages/react/src/Banner/Banner.features.stories.tsx +++ b/packages/react/src/Banner/Banner.features.stories.tsx @@ -184,6 +184,28 @@ export const WithHiddenTitleAndActions = () => { ) } +export const DismissibleWithHiddenTitleAndActions = () => { + return ( + + GitHub users are{' '} + + now required + {' '} + to enable two-factor authentication as an additional security measure. + + } + onDismiss={action('onDismiss')} + variant="warning" + primaryAction={Button} + secondaryAction={Button} + /> + ) +} + export const WithActions = () => { return ( ( + + {leadingVisual.item} + {heading} + {description} + + ), +}) +figma.connect(Blankslate, 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=4398-2383&m=dev', { + props: { + leadingVisual: figma.nestedProps('_BlankslateVisual', { + item: figma.children('leadingVisual'), + }), + narrow: figma.boolean('narrow?'), + spacious: figma.boolean('spacious?'), + border: figma.boolean('border?'), + heading: figma.textContent('Text: Heading'), + description: figma.textContent('Text: Description'), + primaryAction: figma.nestedProps('Primary action', { + text: figma.textContent('Button'), + }), + }, + variant: {primaryAction: 'true', secondaryAction: 'false'}, + example: ({leadingVisual, border, spacious, narrow, description, heading, primaryAction}) => ( + + {leadingVisual.item} + {heading} + {description} + {primaryAction.text} + + ), +}) +figma.connect(Blankslate, 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=4398-2383&m=dev', { + props: { + leadingVisual: figma.nestedProps('_BlankslateVisual', { + item: figma.children('leadingVisual'), + }), + narrow: figma.boolean('narrow?'), + spacious: figma.boolean('spacious?'), + border: figma.boolean('border?'), + heading: figma.textContent('Text: Heading'), + description: figma.textContent('Text: Description'), + primaryAction: figma.nestedProps('Primary action', { + text: figma.textContent('Button'), + }), + secondaryAction: figma.textContent('Secondary action link'), + }, + variant: {primaryAction: 'true', secondaryAction: 'true'}, + example: ({leadingVisual, border, spacious, narrow, description, heading, primaryAction, secondaryAction}) => ( + + {leadingVisual.item} + {heading} + {description} + {primaryAction.text} + {secondaryAction} + + ), +}) +figma.connect(Blankslate, 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=4398-2383&m=dev', { + props: { + leadingVisual: figma.nestedProps('_BlankslateVisual', { + item: figma.children('leadingVisual'), + }), + narrow: figma.boolean('narrow?'), + spacious: figma.boolean('spacious?'), + border: figma.boolean('border?'), + heading: figma.textContent('Text: Heading'), + description: figma.textContent('Text: Description'), + secondaryAction: figma.textContent('Secondary action link'), + }, + variant: {primaryAction: 'false', secondaryAction: 'true'}, + example: ({leadingVisual, border, spacious, narrow, description, heading, secondaryAction}) => ( + + {leadingVisual.item} + {heading} + {description} + {secondaryAction} + + ), +}) diff --git a/packages/react/src/Button/ButtonBase.module.css b/packages/react/src/Button/ButtonBase.module.css new file mode 100644 index 00000000000..7ce72d8adcd --- /dev/null +++ b/packages/react/src/Button/ButtonBase.module.css @@ -0,0 +1,501 @@ +/* Base styles */ +:where(.ButtonBase) { + display: flex; + min-width: max-content; + height: var(--control-medium-size); + /* stylelint-disable-next-line primer/spacing */ + padding: 0 var(--control-medium-paddingInline-normal); + font-family: inherit; + font-size: var(--text-body-size-medium); + font-weight: var(--base-text-weight-medium); + color: var(--button-default-fgColor-rest); + text-align: center; + text-decoration: none; + cursor: pointer; + user-select: none; + background-color: transparent; + border: var(--borderWidth-thin) solid; + border-color: var(--button-default-borderColor-rest); + border-radius: var(--borderRadius-medium); + transition: 80ms cubic-bezier(0.65, 0, 0.35, 1); + transition-property: color, fill, background-color, border-color; + appearance: none; + align-items: center; + justify-content: space-between; + gap: var(--base-size-8); + + &:hover { + transition-duration: 80ms; + } + + &:focus-visible { + outline: 2px solid var(--focus-outlineColor); + outline-offset: -2px; + box-shadow: none; + } + + &:active { + transition: none; + } + + &:disabled { + cursor: not-allowed; + box-shadow: none; + + & .Visual, + & .CounterLabel { + color: inherit; + } + } + + @media (forced-colors: active) { + &:focus { + outline: solid 1px transparent; + } + } + + /* Visuals */ + & .Visual { + display: flex; + color: var(--fgColor-muted); + pointer-events: none; + } + + /* mostly for CounterLabel */ + & .VisualWrap { + display: flex; + pointer-events: none; + } + + /* IconButton */ + + &:where(.IconButton) { + display: inline-grid; + width: var(--control-medium-size); + min-width: var(--control-medium-size); + /* stylelint-disable-next-line primer/spacing */ + padding: unset; + place-content: center; + + &:where([data-size='small']) { + width: var(--control-small-size); + min-width: var(--control-small-size); + } + + &:where([data-size='large']) { + width: var(--control-large-size); + min-width: var(--control-large-size); + } + } + + /* LinkButton */ + + &[href] { + display: inline-flex; + + &:hover { + text-decoration: none; + } + } + + /* Button layout */ + + & .ButtonContent { + flex: 1 0 auto; + display: grid; + grid-template-areas: 'leadingVisual text trailingVisual'; + grid-template-columns: min-content minmax(0, auto) min-content; + align-items: center; + align-content: center; + + & > :not(:last-child) { + margin-right: var(--base-size-8); + } + + /* Content alignment */ + + &:where([data-align='center']) { + justify-content: center; + } + + &:where([data-align='start']) { + justify-content: flex-start; + } + } + + & :where([data-component='leadingVisual']) { + grid-area: leadingVisual; + } + + & .Label { + line-height: 1.4285714; /* temporary until we use Text component with --text-body-lineHeight-medium */ + white-space: nowrap; + grid-area: text; + } + + & :where([data-component='trailingVisual']) { + grid-area: trailingVisual; + } + + & :where([data-component='trailingAction']) { + margin-right: calc(var(--base-size-4) * -1); + } + + /* Size */ + + &:where([data-size='small']) { + height: var(--control-small-size); + /* stylelint-disable-next-line primer/spacing */ + padding: 0 var(--control-small-paddingInline-condensed); + gap: var(--control-small-gap); + font-size: var(--text-body-size-small); + + & .ButtonContent > :not(:last-child) { + /* stylelint-disable-next-line primer/spacing */ + margin-right: var(--control-small-gap); + } + + & .Label { + line-height: 1.6666667; /* temporary until we use Text component with --text-body-lineHeight-small */ + } + } + + &:where([data-size='large']) { + height: var(--control-large-size); + /* stylelint-disable-next-line primer/spacing */ + padding: 0 var(--control-large-paddingInline-spacious); + gap: var(--control-large-gap); + + & .ButtonContent > :not(:last-child) { + /* stylelint-disable-next-line primer/spacing */ + margin-right: var(--control-large-gap); + } + } + + /* Full width */ + + &:where([data-block='block']) { + width: 100%; + } + + /* Wrap label text */ + + &:where([data-label-wrap='true']) { + min-width: fit-content; + height: unset; + min-height: var(--control-medium-size); + + & .ButtonContent { + flex: 1 1 auto; + align-self: stretch; + /* stylelint-disable-next-line primer/spacing */ + padding-block: calc(var(--control-medium-paddingBlock) - var(--base-size-2)); + } + + & .Label { + word-break: break-word; + white-space: unset; + } + + &:where([data-size='small']) { + height: unset; + min-height: var(--control-small-size); + + & .ButtonContent { + /* stylelint-disable-next-line primer/spacing */ + padding-block: calc(var(--control-small-paddingBlock) - var(--base-size-2)); + } + } + + &:where([data-size='large']) { + height: unset; + min-height: var(--control-large-size); + /* stylelint-disable-next-line primer/spacing */ + padding-inline: var(--control-large-paddingInline-spacious); + + & .ButtonContent { + /* stylelint-disable-next-line primer/spacing */ + padding-block: calc(var(--control-large-paddingBlock) - var(--base-size-2)); + } + } + } + + /* Loading */ + + /* only hide label if there's no leading/trailing visuals + * move spinner to label spot if not leading/trailing visuals + */ + + &:where([data-loading='true']) { + & + .loadingSpinner:not( + [data-component='leadingVisual'], + [data-component='trailingVisual'], + [data-component='trailingAction'] + ) { + grid-area: text; + margin-right: 0 !important; + place-self: center; + + & + .Label { + visibility: hidden; + } + } + } + + /* Default Variant */ + + &:where([data-variant='default']) { + color: var(--button-default-fgColor-rest); + background-color: var(--button-default-bgColor-rest); + box-shadow: var(--button-default-shadow-resting); + + &:hover { + background-color: var(--button-default-bgColor-hover); + border-color: var(--button-default-borderColor-hover); + } + + &:active { + background-color: var(--button-default-bgColor-active); + border-color: var(--button-default-borderColor-active); + } + + &:disabled { + color: var(--control-fgColor-disabled); + background-color: var(--button-default-bgColor-disabled); + border-color: var(--button-default-borderColor-disabled); + box-shadow: none; + } + + &[aria-expanded='true'] { + background-color: var(--button-default-bgColor-active); + border-color: var(--button-default-borderColor-active); + } + + & .CounterLabel { + background-color: var(--buttonCounter-default-bgColor-rest) !important; /* temporarily override our own sx prop */ + } + + &:where(.IconButton) { + color: var(--fgColor-muted); + } + } + + /* Primary variant */ + + &:where([data-variant='primary']) { + color: var(--button-primary-fgColor-rest); + background-color: var(--button-primary-bgColor-rest); + border-color: var(--button-primary-borderColor-rest); + box-shadow: var(--shadow-resting-small); + + &:hover { + background-color: var(--button-primary-bgColor-hover); + border-color: var(--button-primary-borderColor-hover); + } + + &:focus-visible { + outline: 2px solid var(--focus-outlineColor); + outline-offset: -2px; + box-shadow: inset 0 0 0 3px var(--fgColor-onEmphasis); + } + + &:active { + background-color: var(--button-primary-bgColor-active); + box-shadow: var(--button-primary-shadow-selected); + } + + &:disabled { + color: var(--button-primary-fgColor-disabled); + background-color: var(--button-primary-bgColor-disabled); + border-color: var(--button-primary-borderColor-disabled); + box-shadow: none; + } + + &[aria-expanded='true'] { + background-color: var(--button-primary-bgColor-active); + box-shadow: var(--button-primary-shadow-selected); + } + + & .CounterLabel { + color: var(--button-primary-fgColor-rest) !important; /* temporarily override our own sx prop */ + background-color: var(--buttonCounter-primary-bgColor-rest) !important; /* temporarily override our own sx prop */ + } + + /* temporarily using the fgColor to match legacy and reduce visual changes- will eventually be iconColor */ + & .Visual { + color: var(--button-primary-fgColor-rest); + } + } + + /* Danger variant */ + + &:where([data-variant='danger']) { + color: var(--button-danger-fgColor-rest); + background-color: var(--button-danger-bgColor-rest); + box-shadow: var(--button-default-shadow-resting); + + &:hover { + color: var(--button-danger-fgColor-hover); + background-color: var(--button-danger-bgColor-hover); + border-color: var(--button-danger-borderColor-hover); + box-shadow: var(--shadow-resting-small); + + & .CounterLabel { + color: var(--buttonCounter-danger-fgColor-hover) !important; /* temporarily override our own sx prop */ + background-color: var(--buttonCounter-danger-bgColor-hover) !important; + } + + & .Visual { + color: var(--button-danger-iconColor-hover); + } + } + + &:active { + color: var(--button-danger-fgColor-active); + background-color: var(--button-danger-bgColor-active); + border-color: var(--button-danger-borderColor-active); + box-shadow: var(--button-danger-shadow-selected); + + & .CounterLabel { + color: var(--buttonCounter-danger-fgColor-hover) !important; /* temporarily override our own sx prop */ + background-color: var(--buttonCounter-danger-bgColor-hover) !important; + } + } + + &:disabled { + color: var(--button-danger-fgColor-disabled); + background-color: var(--button-danger-bgColor-disabled); + border-color: var(--button-default-borderColor-disabled); + box-shadow: none; + + & .CounterLabel { + color: var(--buttonCounter-danger-fgColor-disabled) !important; /* temporarily override our own sx prop */ + background-color: var(--buttonCounter-danger-bgColor-disabled) !important; + } + } + + &[aria-expanded='true'] { + color: var(--button-danger-fgColor-active); + background-color: var(--button-danger-bgColor-active); + border-color: var(--button-danger-borderColor-active); + box-shadow: var(--button-danger-shadow-selected); + } + + & .CounterLabel { + color: var(--buttonCounter-danger-fgColor-rest) !important; /* temporarily override our own sx prop */ + background-color: var(--buttonCounter-danger-bgColor-rest) !important; + } + + & .Visual { + color: var(--button-danger-iconColor-rest); + } + } + + /* Invisible variant */ + + &:where([data-variant='invisible']) { + color: var(--button-default-fgColor-rest); + border-color: transparent; + box-shadow: none; + + &:hover { + background-color: var(--button-invisible-bgColor-hover); + + & .Visual { + color: var(--button-invisible-iconColor-hover); + } + } + + &:active { + background-color: var(--button-invisible-bgColor-active); + + & .Visual { + color: var(--button-invisible-iconColor-hover); + } + } + + &:disabled { + color: var(--button-invisible-fgColor-disabled); + background-color: var(--button-invisible-bgColor-disabled); + border-color: var(--button-invisible-borderColor-disabled); + box-shadow: none; + } + + &[aria-expanded='true'] { + background-color: var(--button-invisible-bgColor-active); + } + + & .Visual { + color: var(--button-invisible-iconColor-rest); + } + + & .CounterLabel { + background-color: var(--buttonCounter-invisible-bgColor-rest) !important; + } + + &:where(.IconButton) { + color: var(--button-invisible-iconColor-rest); + } + } + + /* Link variant */ + + &:where([data-variant='link']) { + display: inline-flex; + min-width: fit-content; + height: unset; + padding: 0; + font-size: inherit; + color: var(--fgColor-link); + text-align: left; + border: unset; + + &:hover:not(:disabled, [data-inactive]) { + text-decoration: underline; + } + + &:focus-visible, + &:focus { + outline-offset: 2px; + } + + &:disabled { + color: var(--control-fgColor-disabled); + background-color: transparent; + border-color: transparent; + } + + & .Label { + white-space: unset; + } + + &:where([data-inactive]) { + color: var(--button-inactive-fgColor); + background: transparent !important; + } + + & .Visual { + color: var(--fgColor-link); + } + } + + /* Inactive */ + + &:where([data-inactive]), + &:where([data-inactive]):hover { + color: var(--button-inactive-fgColor); + cursor: auto; + background-color: var(--button-inactive-bgColor); + border-color: var(--button-inactive-bgColor); + + & .Visual, + & .CounterLabel { + color: inherit !important; + } + } +} + +.ConditionalWrapper { + display: block; +} diff --git a/packages/react/src/Button/ButtonBase.tsx b/packages/react/src/Button/ButtonBase.tsx index 8b66fb72394..8f1bc8b856c 100644 --- a/packages/react/src/Button/ButtonBase.tsx +++ b/packages/react/src/Button/ButtonBase.tsx @@ -16,6 +16,9 @@ import CounterLabel from '../CounterLabel' import {useId} from '../hooks' import {ConditionalWrapper} from '../internal/components/ConditionalWrapper' import {AriaStatus} from '../live-region' +import {clsx} from 'clsx' +import classes from './ButtonBase.module.css' +import {useFeatureFlag} from '../FeatureFlags' const iconWrapStyles = { display: 'flex', @@ -28,6 +31,15 @@ const renderVisual = (Visual: React.ElementType, loading: boolean, visualName: s ) +const renderModuleVisual = (Visual: React.ElementType, loading: boolean, visualName: string, counterLabel: boolean) => ( + + {loading ? : } + +) + const ButtonBase = forwardRef( ({children, as: Component = 'button', sx: sxProp = defaultSxProp, ...props}, forwardedRef): JSX.Element => { const { @@ -48,9 +60,11 @@ const ButtonBase = forwardRef( inactive, onClick, labelWrap, + className, ...rest } = props + const enabled = useFeatureFlag('primer_react_css_modules_team') const innerRef = React.useRef(null) useRefObjectAsForwardedRef(forwardedRef, innerRef) @@ -84,6 +98,239 @@ const ButtonBase = forwardRef( }, [innerRef]) } + if (enabled) { + if (sxProp !== defaultSxProp) { + return ( + + Boolean(descriptionID)) + .join(' ')} + // aria-labelledby is needed because the accessible name becomes unset when the button is in a loading state. + // We only set it when the button is in a loading state because it will supercede the aria-label when the screen + // reader announces the button name. + aria-labelledby={ + loading + ? [`${uuid}-label`, ariaLabelledBy].filter(labelID => Boolean(labelID)).join(' ') + : ariaLabelledBy + } + id={id} + onClick={loading ? undefined : onClick} + > + {Icon ? ( + loading ? ( + + ) : ( + + ) + ) : ( + <> + + { + /* If there are no leading/trailing visuals/actions to replace with a loading spinner, + render a loading spiner in place of the button content. */ + loading && + !LeadingVisual && + !TrailingVisual && + !TrailingAction && + renderModuleVisual(Spinner, loading, 'loadingSpinner', false) + } + { + /* Render a leading visual unless the button is in a loading state. + Then replace the leading visual with a loading spinner. */ + LeadingVisual && renderModuleVisual(LeadingVisual, Boolean(loading), 'leadingVisual', false) + } + {children && ( + + {children} + + )} + { + /* If there is a count, render a counter label unless there is a trailing visual. + Then render the counter label as a trailing visual. + Replace the counter label or the trailing visual with a loading spinner if: + - the button is in a loading state + - there is no leading visual to replace with a loading spinner + */ + count !== undefined && !TrailingVisual + ? renderModuleVisual( + () => ( + + {count} + + ), + Boolean(loading) && !LeadingVisual, + 'trailingVisual', + true, + ) + : TrailingVisual + ? renderModuleVisual( + TrailingVisual, + Boolean(loading) && !LeadingVisual, + 'trailingVisual', + false, + ) + : null + } + + { + /* If there is a trailing action, render it unless the button is in a loading state + and there is no leading or trailing visual to replace with a loading spinner. */ + TrailingAction && + renderModuleVisual( + TrailingAction, + Boolean(loading) && !LeadingVisual && !TrailingVisual, + 'trailingAction', + false, + ) + } + + )} + + {loading && ( + + {loadingAnnouncement} + + )} + + ) + } + return ( + + Boolean(descriptionID)) + .join(' ')} + // aria-labelledby is needed because the accessible name becomes unset when the button is in a loading state. + // We only set it when the button is in a loading state because it will supercede the aria-label when the screen + // reader announces the button name. + aria-labelledby={ + loading ? [`${uuid}-label`, ariaLabelledBy].filter(labelID => Boolean(labelID)).join(' ') : ariaLabelledBy + } + id={id} + // @ts-ignore temporary disable as we migrate to css modules, until we remove PolymorphicForwardRefComponent + onClick={loading ? undefined : onClick} + > + {Icon ? ( + loading ? ( + + ) : ( + + ) + ) : ( + <> + + { + /* If there are no leading/trailing visuals/actions to replace with a loading spinner, + render a loading spiner in place of the button content. */ + loading && + !LeadingVisual && + !TrailingVisual && + !TrailingAction && + renderModuleVisual(Spinner, loading, 'loadingSpinner', false) + } + { + /* Render a leading visual unless the button is in a loading state. + Then replace the leading visual with a loading spinner. */ + LeadingVisual && renderModuleVisual(LeadingVisual, Boolean(loading), 'leadingVisual', false) + } + {children && ( + + {children} + + )} + { + /* If there is a count, render a counter label unless there is a trailing visual. + Then render the counter label as a trailing visual. + Replace the counter label or the trailing visual with a loading spinner if: + - the button is in a loading state + - there is no leading visual to replace with a loading spinner + */ + count !== undefined && !TrailingVisual + ? renderModuleVisual( + () => ( + + {count} + + ), + Boolean(loading) && !LeadingVisual, + 'trailingVisual', + true, + ) + : TrailingVisual + ? renderModuleVisual(TrailingVisual, Boolean(loading) && !LeadingVisual, 'trailingVisual', false) + : null + } + + { + /* If there is a trailing action, render it unless the button is in a loading state + and there is no leading or trailing visual to replace with a loading spinner. */ + TrailingAction && + renderModuleVisual( + TrailingAction, + Boolean(loading) && !LeadingVisual && !TrailingVisual, + 'trailingAction', + false, + ) + } + + )} + + {loading && ( + + {loadingAnnouncement} + + )} + + ) + } + return ( { expect(tooltipEl).toBeInTheDocument() expect(triggerEl.getAttribute('aria-describedby')).toEqual(expect.stringContaining(tooltipEl.id)) }) + + describe('with primer_react_css_modules_staff enabled', () => { + it('iconbutton should support custom `className` along with default classnames', () => { + const {container} = render( + + + , + ) + expect(container.firstChild).toHaveClass('IconButton') + }) + + it('button should support custom `className` along with default classnames', () => { + const {container} = render( + + + , + ) + expect(container.firstChild).toHaveClass('ButtonBase') + }) + + it('linkbutton should support custom `className` along with default classnames', () => { + const {container} = render( + + Hello + , + ) + expect(container.firstChild).toHaveClass('ButtonBase') + }) + }) }) diff --git a/packages/react/src/Button/__tests__/__snapshots__/Button.test.tsx.snap b/packages/react/src/Button/__tests__/__snapshots__/Button.test.tsx.snap index f070f6eb26c..3d13c559732 100644 --- a/packages/react/src/Button/__tests__/__snapshots__/Button.test.tsx.snap +++ b/packages/react/src/Button/__tests__/__snapshots__/Button.test.tsx.snap @@ -128,7 +128,7 @@ exports[`Button respects block prop 1`] = ` } .c0[data-size="small"] [data-component="text"] { - line-height: calc(20 / 12); + line-height: 1.6666667; } .c0[data-size="small"] [data-component=ButtonCounter] { @@ -221,7 +221,7 @@ exports[`Button respects block prop 1`] = ` .c0 [data-component="text"] { grid-area: text; - line-height: calc(20/14); + line-height: 1.4285714; white-space: nowrap; } @@ -445,7 +445,7 @@ exports[`Button respects the alignContent prop 1`] = ` } .c0[data-size="small"] [data-component="text"] { - line-height: calc(20 / 12); + line-height: 1.6666667; } .c0[data-size="small"] [data-component=ButtonCounter] { @@ -538,7 +538,7 @@ exports[`Button respects the alignContent prop 1`] = ` .c0 [data-component="text"] { grid-area: text; - line-height: calc(20/14); + line-height: 1.4285714; white-space: nowrap; } @@ -761,7 +761,7 @@ exports[`Button respects the large size prop 1`] = ` } .c0[data-size="small"] [data-component="text"] { - line-height: calc(20 / 12); + line-height: 1.6666667; } .c0[data-size="small"] [data-component=ButtonCounter] { @@ -854,7 +854,7 @@ exports[`Button respects the large size prop 1`] = ` .c0 [data-component="text"] { grid-area: text; - line-height: calc(20/14); + line-height: 1.4285714; white-space: nowrap; } @@ -1078,7 +1078,7 @@ exports[`Button respects the small size prop 1`] = ` } .c0[data-size="small"] [data-component="text"] { - line-height: calc(20 / 12); + line-height: 1.6666667; } .c0[data-size="small"] [data-component=ButtonCounter] { @@ -1171,7 +1171,7 @@ exports[`Button respects the small size prop 1`] = ` .c0 [data-component="text"] { grid-area: text; - line-height: calc(20/14); + line-height: 1.4285714; white-space: nowrap; } @@ -1397,7 +1397,7 @@ exports[`Button styles danger button appropriately 1`] = ` } .c0[data-size="small"] [data-component="text"] { - line-height: calc(20 / 12); + line-height: 1.6666667; } .c0[data-size="small"] [data-component=ButtonCounter] { @@ -1490,7 +1490,7 @@ exports[`Button styles danger button appropriately 1`] = ` .c0 [data-component="text"] { grid-area: text; - line-height: calc(20/14); + line-height: 1.4285714; white-space: nowrap; } @@ -1714,7 +1714,7 @@ exports[`Button styles invisible button appropriately 1`] = ` } .c0[data-size="small"] [data-component="text"] { - line-height: calc(20 / 12); + line-height: 1.6666667; } .c0[data-size="small"] [data-component=ButtonCounter] { @@ -1808,7 +1808,7 @@ exports[`Button styles invisible button appropriately 1`] = ` .c0 [data-component="text"] { grid-area: text; - line-height: calc(20/14); + line-height: 1.4285714; white-space: nowrap; } @@ -2041,7 +2041,7 @@ exports[`Button styles primary button appropriately 1`] = ` } .c0[data-size="small"] [data-component="text"] { - line-height: calc(20 / 12); + line-height: 1.6666667; } .c0[data-size="small"] [data-component=ButtonCounter] { @@ -2134,7 +2134,7 @@ exports[`Button styles primary button appropriately 1`] = ` .c0 [data-component="text"] { grid-area: text; - line-height: calc(20/14); + line-height: 1.4285714; white-space: nowrap; } diff --git a/packages/react/src/Button/styles.ts b/packages/react/src/Button/styles.ts index 0706510094e..dafe8a8050a 100644 --- a/packages/react/src/Button/styles.ts +++ b/packages/react/src/Button/styles.ts @@ -299,7 +299,7 @@ export const getBaseStyles = (theme?: Theme) => ({ fontSize: '0', '[data-component="text"]': { - lineHeight: 'calc(20 / 12)', + lineHeight: '1.6666667', }, '[data-component=ButtonCounter]': { @@ -385,7 +385,7 @@ export const getButtonStyles = (theme?: Theme) => { }, '[data-component="text"]': { gridArea: 'text', - lineHeight: 'calc(20/14)', + lineHeight: '1.4285714', whiteSpace: 'nowrap', }, '[data-component="trailingVisual"]': { diff --git a/packages/react/src/ButtonGroup/ButtonGroup.figma.tsx b/packages/react/src/ButtonGroup/ButtonGroup.figma.tsx new file mode 100644 index 00000000000..72f6026b9b4 --- /dev/null +++ b/packages/react/src/ButtonGroup/ButtonGroup.figma.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import {ButtonGroup} from '../../src' +import figma from '@figma/code-connect' + +figma.connect(ButtonGroup, 'https://www.figma.com/design/GCvY3Qv8czRgZgvl1dG6lp/Primer-Web?node-id=36325-3634&m=dev', { + props: { + children: figma.children('*'), + }, + example: ({children}) => {children}, +}) diff --git a/packages/react/src/CounterLabel/CounterLabel.tsx b/packages/react/src/CounterLabel/CounterLabel.tsx index d90e08c3a4a..dad3e633847 100644 --- a/packages/react/src/CounterLabel/CounterLabel.tsx +++ b/packages/react/src/CounterLabel/CounterLabel.tsx @@ -9,15 +9,17 @@ import {defaultSxProp} from '../utils/defaultSxProp' export type CounterLabelProps = React.PropsWithChildren< HTMLAttributes & { scheme?: 'primary' | 'secondary' + className?: string } & SxProp > const CounterLabel = forwardRef( - ({scheme = 'secondary', sx = defaultSxProp, children, ...props}, forwardedRef) => { + ({scheme = 'secondary', sx = defaultSxProp, children, className, ...props}, forwardedRef) => { return ( <>