diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-colorblind-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-colorblind-linux.png index 84bc47b5d3d..be025ee96fb 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-colorblind-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-dimmed-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-dimmed-linux.png index 74a88238272..195d312bde8 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-dimmed-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-high-contrast-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-high-contrast-linux.png index f3aacfd642b..a56e53a3b0a 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-high-contrast-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-linux.png index 2825f451b06..a24d2e156b4 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-tritanopia-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-tritanopia-linux.png index 2825f451b06..be025ee96fb 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-tritanopia-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-colorblind-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-colorblind-linux.png index 2810ee1f85a..a9015d4d37b 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-colorblind-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-high-contrast-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-high-contrast-linux.png index 4316747be6a..c55bf9bcb7e 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-high-contrast-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-linux.png index 2810ee1f85a..a9015d4d37b 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-tritanopia-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-tritanopia-linux.png index c7a0b1d4e68..a9015d4d37b 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-tritanopia-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-responsive-width-light-full-screen-on-narrow--true-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-responsive-width-light-full-screen-on-narrow--true-linux.png index ad1c4f14d4b..c22b4644884 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-responsive-width-light-full-screen-on-narrow--true-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-Default-responsive-width-light-full-screen-on-narrow--true-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-colorblind-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-colorblind-linux.png index 045357e9c09..408a2bad5b9 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-colorblind-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-dimmed-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-dimmed-linux.png index 17cb326e3ae..bb9f7df2f7b 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-dimmed-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-high-contrast-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-high-contrast-linux.png index 04f8b045550..533328d276f 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-high-contrast-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-linux.png index 045357e9c09..408a2bad5b9 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-tritanopia-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-tritanopia-linux.png index 5abc4123846..408a2bad5b9 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-tritanopia-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-colorblind-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-colorblind-linux.png index 4526832173c..42686117360 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-colorblind-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-high-contrast-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-high-contrast-linux.png index bc177b31f27..ac0378e51d0 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-high-contrast-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-linux.png index 621875558fc..42686117360 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-tritanopia-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-tritanopia-linux.png index 621875558fc..42686117360 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-tritanopia-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Css-light-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-colorblind-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-colorblind-linux.png index 6da445bce81..fe075f7c5bf 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-colorblind-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-dimmed-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-dimmed-linux.png index 2a49f45b242..e84e2ed92b5 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-dimmed-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-dimmed-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-high-contrast-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-high-contrast-linux.png index ebd938f7519..59db6eb7fb4 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-high-contrast-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-linux.png index 6da445bce81..fe075f7c5bf 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-tritanopia-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-tritanopia-linux.png index 6da445bce81..fe075f7c5bf 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-tritanopia-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-dark-tritanopia-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-colorblind-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-colorblind-linux.png index 0f2c904f5bc..f48a70315c0 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-colorblind-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-colorblind-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-high-contrast-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-high-contrast-linux.png index 7e82e8cea15..ee3a3cf3edc 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-high-contrast-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-high-contrast-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-linux.png index 0f2c904f5bc..f48a70315c0 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-linux.png differ diff --git a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-tritanopia-linux.png b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-tritanopia-linux.png index 0f2c904f5bc..f48a70315c0 100644 Binary files a/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-tritanopia-linux.png and b/.playwright/snapshots/components/SelectPanel.test.ts-snapshots/SelectPanel-With-Groups-light-tritanopia-linux.png differ diff --git a/packages/react/src/ActionList/ActionList.module.css b/packages/react/src/ActionList/ActionList.module.css index 29b81e1a630..2e503c37b7b 100644 --- a/packages/react/src/ActionList/ActionList.module.css +++ b/packages/react/src/ActionList/ActionList.module.css @@ -87,7 +87,7 @@ } /* if a list has a mix of items with and without descriptions, reset the label font-weight to normal */ - &:has([data-has-description='true']):has([data-has-description='false']) { + &[data-mixed-descriptions='true'] { & .ItemLabel { font-weight: var(--base-text-weight-normal); } diff --git a/packages/react/src/ActionList/ActionList.stress.dev.stories.tsx b/packages/react/src/ActionList/ActionList.stress.dev.stories.tsx index 352ce000368..6c633eb32d4 100644 --- a/packages/react/src/ActionList/ActionList.stress.dev.stories.tsx +++ b/packages/react/src/ActionList/ActionList.stress.dev.stories.tsx @@ -16,6 +16,11 @@ const projects = Array.from({length: totalIterations}, (_, i) => ({ scope: `Scope ${i + 1}`, })) +const mixedProjects = Array.from({length: totalIterations}, (_, i) => ({ + name: `Project ${i + 1}`, + scope: i % 2 === 0 ? `Scope ${i + 1}` : undefined, +})) + export const SingleSelect = () => { return ( { /> ) } + +export const MixedDescriptions = () => { + return ( + { + return ( + <> + + {mixedProjects.map((project, index) => ( + + + + + {project.name} + {project.scope ? ( + {project.scope} + ) : null} + + ))} + + + ) + }} + /> + ) +} diff --git a/packages/react/src/ActionList/List.tsx b/packages/react/src/ActionList/List.tsx index ee9213fcb50..ffd597ec906 100644 --- a/packages/react/src/ActionList/List.tsx +++ b/packages/react/src/ActionList/List.tsx @@ -9,6 +9,7 @@ import {useProvidedRefOrCreate} from '../hooks' import {FocusKeys, useFocusZone} from '../hooks/useFocusZone' import {clsx} from 'clsx' import classes from './ActionList.module.css' +import useIsomorphicLayoutEffect from '../utils/useIsomorphicLayoutEffect' const UnwrappedList = ( props: ActionListProps, @@ -66,6 +67,34 @@ const UnwrappedList = ( [variant, selectionVariant, containerSelectionVariant, showDividers, listRole, headingId], ) + // Replaces a CSS `:has([data-has-description])` selector that caused full-subtree + // style recalculation on every DOM mutation (~674ms on 100 items, 10-20s freezes on Safari). + // + // Ideally we'd derive this from children during render, but each Item's description is + // detected via `useSlots` at render time, so the List can't know which Items have + // descriptions without duplicating slot detection or deeply inspecting children trees + // (fragile with Groups, conditional rendering, wrapper components, etc.). + // + // A context-based approach (Items registering their description state with the List) would + // work but adds registration/unregistration callbacks, a new provider, and re-renders when + // the count changes. Not worth the complexity for a derived boolean. + // + // Two querySelector calls after render is trivially cheap compared to what the browser + // was doing on every DOM mutation with `:has()`. + useIsomorphicLayoutEffect(() => { + const list = listRef.current + if (!list) return + const hasMixed = + list.querySelector('[data-has-description="true"]') !== null && + list.querySelector('[data-has-description="false"]') !== null + const current = list.getAttribute('data-mixed-descriptions') + if (hasMixed && current !== 'true') { + list.setAttribute('data-mixed-descriptions', 'true') + } else if (!hasMixed && current !== null) { + list.removeAttribute('data-mixed-descriptions') + } + }) + return ( {slots.heading}