diff --git a/.changeset/ten-gifts-own.md b/.changeset/ten-gifts-own.md new file mode 100644 index 00000000000..1d743aecde9 --- /dev/null +++ b/.changeset/ten-gifts-own.md @@ -0,0 +1,5 @@ +--- +"@primer/react": patch +--- + +SelectPanel: Fix focus and selection styles for Windows high contrast themes (behind feature flag `primer_react_select_panel_with_modern_action_list`) diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-dark-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-dark-modern-action-list--true-linux.png new file mode 100644 index 00000000000..25d8a0cf18b Binary files /dev/null and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-dark-modern-action-list--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-light-modern-action-list--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-light-modern-action-list--true-linux.png new file mode 100644 index 00000000000..2c12a24a104 Binary files /dev/null and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-forced-colors-light-modern-action-list--true-linux.png differ diff --git a/e2e/components/SelectPanel.test.ts b/e2e/components/SelectPanel.test.ts index e4f61864b17..bc6614cee1e 100644 --- a/e2e/components/SelectPanel.test.ts +++ b/e2e/components/SelectPanel.test.ts @@ -60,4 +60,27 @@ test.describe('SelectPanel', () => { await expect(page).toHaveNoViolations() }) } + + test(`Default @vrt forced-colors .modern-action-list--true`, async ({page}) => { + await visit(page, { + id: 'components-selectpanel--default', + globals: {featureFlags: {primer_react_select_panel_with_modern_action_list: true}}, + }) + + // Open select panel + await page.keyboard.press('Tab') + await page.keyboard.press('Enter') + + // windows high contrast mode: light + await page.emulateMedia({forcedColors: 'active', colorScheme: 'light'}) + expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( + `SelectPanel-Default-forced-colors-light-modern-action-list--true.png`, + ) + + // windows high contrast mode: dark + await page.emulateMedia({forcedColors: 'active', colorScheme: 'dark'}) + expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot( + `SelectPanel-Default-forced-colors-dark-modern-action-list--true.png`, + ) + }) }) diff --git a/packages/react/src/ActionList/Item.tsx b/packages/react/src/ActionList/Item.tsx index 8e3da1de68a..629e1d3b5c1 100644 --- a/packages/react/src/ActionList/Item.tsx +++ b/packages/react/src/ActionList/Item.tsx @@ -196,7 +196,7 @@ export const Item = React.forwardRef( marginY: 'unset', '@media (forced-colors: active)': { - ':focus, &:focus-visible, > a.focus-visible': { + ':focus, &:focus-visible, > a.focus-visible, &[data-is-active-descendant]': { // Support for Windows high contrast https://sarahmhigley.com/writing/whcm-quick-tips outline: 'solid 1px transparent !important', }, diff --git a/packages/react/src/ActionList/Selection.tsx b/packages/react/src/ActionList/Selection.tsx index e5b9c3e1617..4d705e2faf4 100644 --- a/packages/react/src/ActionList/Selection.tsx +++ b/packages/react/src/ActionList/Selection.tsx @@ -97,6 +97,11 @@ export const Selection: React.FC> = ({se '@keyframes checkmarkIn': checkmarkIn, '@keyframes checkmarkOut': checkmarkOut, }, + '@media (forced-colors: active)': { + // Support for Windows high contrast https://sarahmhigley.com/writing/whcm-quick-tips + // background-color will be overriden but border-width is a workaround + borderWidth: selected ? '8px' : '1px', + }, }} data-component="ActionList.Checkbox" /> diff --git a/packages/react/src/NavList/__snapshots__/NavList.test.tsx.snap b/packages/react/src/NavList/__snapshots__/NavList.test.tsx.snap index 76ad7525713..339503e6711 100644 --- a/packages/react/src/NavList/__snapshots__/NavList.test.tsx.snap +++ b/packages/react/src/NavList/__snapshots__/NavList.test.tsx.snap @@ -304,7 +304,8 @@ exports[`NavList renders a simple list 1`] = ` @media (forced-colors:active) { .c2:focus, .c2:focus-visible, - .c2 > a.focus-visible { + .c2 > a.focus-visible, + .c2[data-is-active-descendant] { outline: solid 1px transparent !important; } } @@ -333,7 +334,8 @@ exports[`NavList renders a simple list 1`] = ` @media (forced-colors:active) { .c7:focus, .c7:focus-visible, - .c7 > a.focus-visible { + .c7 > a.focus-visible, + .c7[data-is-active-descendant] { outline: solid 1px transparent !important; } } @@ -794,7 +796,8 @@ exports[`NavList renders with groups 1`] = ` @media (forced-colors:active) { .c6:focus, .c6:focus-visible, - .c6 > a.focus-visible { + .c6 > a.focus-visible, + .c6[data-is-active-descendant] { outline: solid 1px transparent !important; } } @@ -823,7 +826,8 @@ exports[`NavList renders with groups 1`] = ` @media (forced-colors:active) { .c11:focus, .c11:focus-visible, - .c11 > a.focus-visible { + .c11 > a.focus-visible, + .c11[data-is-active-descendant] { outline: solid 1px transparent !important; } } @@ -1313,7 +1317,8 @@ exports[`NavList.Item with NavList.SubNav does not have active styles if SubNav @media (forced-colors:active) { .c11:focus, .c11:focus-visible, - .c11 > a.focus-visible { + .c11 > a.focus-visible, + .c11[data-is-active-descendant] { outline: solid 1px transparent !important; } } @@ -1342,7 +1347,8 @@ exports[`NavList.Item with NavList.SubNav does not have active styles if SubNav @media (forced-colors:active) { .c4:focus, .c4:focus-visible, - .c4 > a.focus-visible { + .c4 > a.focus-visible, + .c4[data-is-active-descendant] { outline: solid 1px transparent !important; } } @@ -1837,7 +1843,8 @@ exports[`NavList.Item with NavList.SubNav has active styles if SubNav contains t @media (forced-colors:active) { .c11:focus, .c11:focus-visible, - .c11 > a.focus-visible { + .c11 > a.focus-visible, + .c11[data-is-active-descendant] { outline: solid 1px transparent !important; } } @@ -1874,7 +1881,8 @@ exports[`NavList.Item with NavList.SubNav has active styles if SubNav contains t @media (forced-colors:active) { .c4:focus, .c4:focus-visible, - .c4 > a.focus-visible { + .c4 > a.focus-visible, + .c4[data-is-active-descendant] { outline: solid 1px transparent !important; } } diff --git a/packages/react/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap b/packages/react/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap index 5317c8136b8..92301474008 100644 --- a/packages/react/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap +++ b/packages/react/src/__tests__/__snapshots__/Autocomplete.test.tsx.snap @@ -527,6 +527,14 @@ exports[`snapshots renders a menu that contains an item to add to the menu 1`] = } +@media (forced-colors:active) { + +} + +@media (forced-colors:active) { + +} + @media (hover:hover) and (pointer:fine) { } @@ -812,10 +820,21 @@ exports[`snapshots renders a menu that contains an item to add to the menu 1`] = --divider-color: transparent; } +@media (forced-colors:active) { + .c6 { + border-width: 1px; + } +} + +@media (forced-colors:active) { + +} + @media (forced-colors:active) { .c3:focus, .c3:focus-visible, - .c3 > a.focus-visible { + .c3 > a.focus-visible, + .c3[data-is-active-descendant] { outline: solid 1px transparent !important; } } @@ -1359,6 +1378,10 @@ exports[`snapshots renders a multiselect input 1`] = ` } +@media (forced-colors:active) { + +} + @media (hover:hover) and (pointer:fine) { } @@ -1595,10 +1618,17 @@ exports[`snapshots renders a multiselect input 1`] = ` border-radius: 6px; } +@media (forced-colors:active) { + .c5 { + border-width: 1px; + } +} + @media (forced-colors:active) { .c3:focus, .c3:focus-visible, - .c3 > a.focus-visible { + .c3 > a.focus-visible, + .c3[data-is-active-descendant] { outline: solid 1px transparent !important; } } @@ -2077,6 +2107,14 @@ exports[`snapshots renders a multiselect input with selected menu items 1`] = ` } +@media (forced-colors:active) { + +} + +@media (forced-colors:active) { + +} + @media (hover:hover) and (pointer:fine) { } @@ -2456,10 +2494,23 @@ exports[`snapshots renders a multiselect input with selected menu items 1`] = ` border-radius: 6px; } +@media (forced-colors:active) { + .c5 { + border-width: 8px; + } +} + +@media (forced-colors:active) { + .c9 { + border-width: 1px; + } +} + @media (forced-colors:active) { .c3:focus, .c3:focus-visible, - .c3 > a.focus-visible { + .c3 > a.focus-visible, + .c3[data-is-active-descendant] { outline: solid 1px transparent !important; } } @@ -2488,7 +2539,8 @@ exports[`snapshots renders a multiselect input with selected menu items 1`] = ` @media (forced-colors:active) { .c8:focus, .c8:focus-visible, - .c8 > a.focus-visible { + .c8 > a.focus-visible, + .c8[data-is-active-descendant] { outline: solid 1px transparent !important; } } @@ -3168,7 +3220,8 @@ exports[`snapshots renders a single select input 1`] = ` @media (forced-colors:active) { .c3:focus, .c3:focus-visible, - .c3 > a.focus-visible { + .c3 > a.focus-visible, + .c3[data-is-active-descendant] { outline: solid 1px transparent !important; } } @@ -3654,7 +3707,8 @@ exports[`snapshots renders with a custom text input component 1`] = ` @media (forced-colors:active) { .c3:focus, .c3:focus-visible, - .c3 > a.focus-visible { + .c3 > a.focus-visible, + .c3[data-is-active-descendant] { outline: solid 1px transparent !important; } }