From 1705d269d6019bf165ba41bd868a19dd57136135 Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Tue, 12 Nov 2024 15:34:52 +0000 Subject: [PATCH 01/17] replace sx with Primer CSS utility classes where possible As of https://github.com/primer/react/blob/fca4ec98f2e3ef5e5c3298320e3ab2050593709c/contributor-docs/adrs/adr-016-css.md, Primer has decided to move away from using styled system props and prefers CSS for styling over styled system props due to performance concerns with `sx` props. See linked ADR for full details. --- packages/react/src/TreeView/TreeView.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/react/src/TreeView/TreeView.tsx b/packages/react/src/TreeView/TreeView.tsx index fdf262d36ce5..ccc4d77bbf84 100644 --- a/packages/react/src/TreeView/TreeView.tsx +++ b/packages/react/src/TreeView/TreeView.tsx @@ -16,8 +16,6 @@ import {useControllableState} from '../hooks/useControllableState' import {useId} from '../hooks/useId' import useSafeTimeout from '../hooks/useSafeTimeout' import {useSlots} from '../hooks/useSlots' -import type {SxProp} from '../sx' -import sx from '../sx' import {getAccessibleName} from './shared' import {getFirstChildElement, useRovingTabIndex} from './useRovingTabIndex' import {useTypeahead} from './useTypeahead' @@ -73,7 +71,7 @@ export type TreeViewProps = { /* Size of toggle icon in pixels. */ const TOGGLE_ICON_SIZE = 12 -const UlBox = styled.ul` +const UlBox = styled.ul` list-style: none; padding: 0; margin: 0; @@ -280,8 +278,6 @@ const UlBox = styled.ul` white-space: nowrap; border-width: 0; } - - ${sx} ` const Root: React.FC = ({ @@ -795,7 +791,7 @@ const LoadingItem = React.forwardRef(({count}, re - Loading... + Loading... ) }) @@ -803,7 +799,7 @@ const LoadingItem = React.forwardRef(({count}, re const EmptyItem = React.forwardRef((props, ref) => { return ( - No items found + No items found ) }) From bc8a555b2bead368ba91533ffd5dd8f80718c079 Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Tue, 12 Nov 2024 16:28:05 +0000 Subject: [PATCH 02/17] add support for style prop to TreeView Root --- packages/react/src/TreeView/TreeView.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react/src/TreeView/TreeView.tsx b/packages/react/src/TreeView/TreeView.tsx index ccc4d77bbf84..a4e9e70ca3cd 100644 --- a/packages/react/src/TreeView/TreeView.tsx +++ b/packages/react/src/TreeView/TreeView.tsx @@ -66,6 +66,7 @@ export type TreeViewProps = { flat?: boolean truncate?: boolean className?: string + style?: React.CSSProperties } /* Size of toggle icon in pixels. */ @@ -287,6 +288,7 @@ const Root: React.FC = ({ flat, truncate = true, className, + style, }) => { const containerRef = React.useRef(null) const mouseDownRef = React.useRef(false) @@ -345,6 +347,7 @@ const Root: React.FC = ({ data-truncate-text={truncate || false} onMouseDown={onMouseDown} className={className} + style={style} > {children} From 6db4c49f174c8527a2972e6cea0245779dbb6165 Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Tue, 12 Nov 2024 16:24:03 +0000 Subject: [PATCH 03/17] Convert ul to css modules Per instructions: https://github.com/primer/react/blob/ac6ddcd4b15526dd6f5ad6072a4daa57087eb1e7/contributor-docs/migrating-to-css-modules.md --- contributor-docs/migrating-to-css-modules.md | 2 +- .../react/src/TreeView/TreeView.module.css | 208 ++++++++++ packages/react/src/TreeView/TreeView.tsx | 363 +++++++++--------- 3 files changed, 397 insertions(+), 176 deletions(-) create mode 100644 packages/react/src/TreeView/TreeView.module.css diff --git a/contributor-docs/migrating-to-css-modules.md b/contributor-docs/migrating-to-css-modules.md index 50ab7c0781f0..c72df1d78007 100644 --- a/contributor-docs/migrating-to-css-modules.md +++ b/contributor-docs/migrating-to-css-modules.md @@ -53,7 +53,7 @@ This guide outlines the steps to follow when refactoring Primer React components - Add a feature flag to toggle the `sx` prop for controlled rollout (staff shipping). How it's used will be based on the implementation of the component. For most you'll be able to `useFeatureFlag` and toggle between components. For more complex styled components, you can use the utility `toggleStyledComponent` which will render based on the feature flag string provided. ```jsx - /* When there is an exisiting styled component, use the `toggleStyledComponent` utility. */ + /* When there is an existing styled component, use the `toggleStyledComponent` utility. */ const StyledDiv = toggleStyledComponent( 'primer_react_css_modules_team', 'div', diff --git a/packages/react/src/TreeView/TreeView.module.css b/packages/react/src/TreeView/TreeView.module.css new file mode 100644 index 000000000000..9a41a4bc0134 --- /dev/null +++ b/packages/react/src/TreeView/TreeView.module.css @@ -0,0 +1,208 @@ +.TreeViewRootUlStyles { + list-style: none; + padding: 0; + margin: 0; + + /* + * WARNING: This is a performance optimization. + * + * We define styles for the tree items at the root level of the tree + * to avoid recomputing the styles for each item when the tree updates. + * We're sacraficing maintainability for performance because TreeView + * needs to be performant enough to handle large trees (thousands of items). + * + * This is intended to be a temporary solution until we can improve the + * performance of our styling patterns. + * + * Do NOT copy this pattern without understanding the tradeoffs. + * Do NOT reference PRIVATE_* classnames outside of this file. + */ + .PRIVATE_TreeView-item { + outline: none; + + &:focus-visible > div, + &.focus-visible > div { + box-shadow: inset 0 0 0 2px var(--fgColor-accent); + @media (forced-colors: active) { + outline: 2px solid HighlightText; + outline-offset: -2; + } + } + &[data-has-leading-action] { + --has-leading-action: 1; + } + } + + .PRIVATE_TreeView-item-container { + --level: 1; /* default level */ + --toggle-width: 1rem; /* 16px */ + --min-item-height: 2rem; /* 32px */ + position: relative; + display: grid; + --leading-action-width: calc(var(--has-leading-action, 0) * 1.5rem); + --spacer-width: calc(calc(var(--level) - 1) * (var(--toggle-width) / 2)); + grid-template-columns: var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr; + grid-template-areas: 'spacer leadingAction toggle content'; + width: 100%; + font-size: var(--base-size-14); + color: var(--fgColor-default); + border-radius: var(--borderRadius-medium); + cursor: pointer; + + &:hover { + background-color: var(--control-transparent-bgColor-hover); + + @media (forced-colors: active) { + outline: 2px solid transparent; + outline-offset: -2px; + } + } + + @media (pointer: coarse) { + --toggle-width: 1.5rem; /* 24px */ + --min-item-height: 2.75rem; /* 44px */ + } + + &:has(.PRIVATE_TreeView-item-skeleton):hover { + background-color: transparent; + cursor: default; + + @media (forced-colors: active) { + outline: none; + } + } + } + + &[data-omit-spacer='true'] .PRIVATE_TreeView-item-container { + grid-template-columns: 0 0 0 1fr; + } + + .PRIVATE_TreeView-item[aria-current='true'] > .PRIVATE_TreeView-item-container { + background-color: var(--control-transparent-bgColor-selected); + + /* Current item indicator */ + &::after { + content: ''; + position: absolute; + top: calc(50% - 0.75rem); /* 50% - 12px */ + left: calc(-1 * var(--base-size-8)); + width: 0.25rem; /* 4px */ + height: 1.5rem; /* 24px */ + background-color: var(--fgColor-accent); + border-radius: var(--borderRadius-medium); + + @media (forced-colors: active) { + background-color: HighlightText; + } + } + } + + .PRIVATE_TreeView-item-toggle { + grid-area: toggle; + display: flex; + justify-content: center; + align-items: flex-start; + /* The toggle should appear vertically centered for single-line items, but remain at the top for items that wrap + across more lines. */ + padding-top: calc(var(--min-item-height) / 2 - 12px / 2); + height: 100%; + color: var(--fgColor-muted); + } + + .PRIVATE_TreeView-item-toggle--hover:hover { + background-color: var(--color-tree-view-item-chevron-hover-bg); + } + + .PRIVATE_TreeView-item-toggle--end { + border-top-left-radius: var(--borderRadius-medium); + border-bottom-left-radius: var(--borderRadius-medium); + } + + .PRIVATE_TreeView-item-content { + grid-area: content; + display: flex; + height: 100%; + padding: 0 var(--base-size-8); + gap: var(--stack-gap-condensed); + line-height: var(--custom-line-height, var(--text-body-lineHeight-medium, 1.4285)); + /* The dynamic top and bottom padding to maintain the minimum item height for single line items */ + padding-top: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2); + padding-bottom: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2); + } + + .PRIVATE_TreeView-item-content-text { + flex: 1 1 auto; + width: 0; + } + + &[data-truncate-text='true'] .PRIVATE_TreeView-item-content-text { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + &[data-truncate-text='false'] .PRIVATE_TreeView-item-content-text { + word-break: break-word; + } + + .PRIVATE_TreeView-item-visual { + display: flex; + align-items: center; + color: var(--fgColor-muted); + /* The visual icons should appear vertically centered for single-line items, but remain at the top for items that wrap + across more lines. */ + height: var(--custom-line-height, 1.3rem); + } + + .PRIVATE_TreeView-item-leading-action { + display: flex; + color: var(--fgColor-muted); + grid-area: leadingAction; + } + + .PRIVATE_TreeView-item-level-line { + width: 100%; + height: 100%; + border-right: 1px solid; + + /* + * On devices without hover, the nesting indicator lines + * appear at all times. + */ + border-color: var(--borderColor-muted); + } + + /* + * On devices with :hover support, the nesting indicator lines + * fade in when the user mouses over the entire component, + * or when there's focus inside the component. This makes + * sure the component remains simple when not in use. + */ + @media (hover: hover) { + .PRIVATE_TreeView-item-level-line { + border-color: transparent; + } + + &:hover .PRIVATE_TreeView-item-level-line, + &:focus-within .PRIVATE_TreeView-item-level-line { + border-color: var(--borderColor-muted); + } + } + + .PRIVATE_TreeView-directory-icon { + display: grid; + color: var(--treeViewItem-leadingVisual-bgColor-rest); + } + + .PRIVATE_VisuallyHidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; + } +} diff --git a/packages/react/src/TreeView/TreeView.tsx b/packages/react/src/TreeView/TreeView.tsx index a4e9e70ca3cd..28288755b902 100644 --- a/packages/react/src/TreeView/TreeView.tsx +++ b/packages/react/src/TreeView/TreeView.tsx @@ -7,6 +7,7 @@ import { import {clsx} from 'clsx' import React, {useCallback, useEffect} from 'react' import styled from 'styled-components' +import classes from './TreeView.module.css' import {ConfirmationDialog} from '../ConfirmationDialog/ConfirmationDialog' import Spinner from '../Spinner' import Text from '../Text' @@ -16,11 +17,15 @@ import {useControllableState} from '../hooks/useControllableState' import {useId} from '../hooks/useId' import useSafeTimeout from '../hooks/useSafeTimeout' import {useSlots} from '../hooks/useSlots' +import type {SxProp} from '../sx' +import sx from '../sx' import {getAccessibleName} from './shared' import {getFirstChildElement, useRovingTabIndex} from './useRovingTabIndex' import {useTypeahead} from './useTypeahead' import {SkeletonAvatar} from '../experimental/Skeleton/SkeletonAvatar' import {SkeletonText} from '../experimental/Skeleton/SkeletonText' +import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent' +import {useFeatureFlag} from '../FeatureFlags' // ---------------------------------------------------------------------------- // Context @@ -72,214 +77,220 @@ export type TreeViewProps = { /* Size of toggle icon in pixels. */ const TOGGLE_ICON_SIZE = 12 -const UlBox = styled.ul` - list-style: none; - padding: 0; - margin: 0; - - /* - * WARNING: This is a performance optimization. - * - * We define styles for the tree items at the root level of the tree - * to avoid recomputing the styles for each item when the tree updates. - * We're sacraficing maintainability for performance because TreeView - * needs to be performant enough to handle large trees (thousands of items). - * - * This is intended to be a temporary solution until we can improve the - * performance of our styling patterns. - * - * Do NOT copy this pattern without understanding the tradeoffs. - * Do NOT reference PRIVATE_* classnames outside of this file. - */ - .PRIVATE_TreeView-item { - outline: none; - - &:focus-visible > div, - &.focus-visible > div { - box-shadow: inset 0 0 0 2px ${get(`colors.accent.fg`)}; - @media (forced-colors: active) { - outline: 2px solid HighlightText; - outline-offset: -2; - } - } - &[data-has-leading-action] { - --has-leading-action: 1; - } - } +const UlBox = toggleStyledComponent( + 'primer_react_tree_view_css_modules', + 'ul', + styled.ul` + list-style: none; + padding: 0; + margin: 0; - .PRIVATE_TreeView-item-container { - --level: 1; /* default level */ - --toggle-width: 1rem; /* 16px */ - --min-item-height: 2rem; /* 32px */ - position: relative; - display: grid; - --leading-action-width: calc(var(--has-leading-action, 0) * 1.5rem); - --spacer-width: calc(calc(var(--level) - 1) * (var(--toggle-width) / 2)); - grid-template-columns: var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr; - grid-template-areas: 'spacer leadingAction toggle content'; - width: 100%; - font-size: ${get('fontSizes.1')}; - color: ${get('colors.fg.default')}; - border-radius: ${get('radii.2')}; - cursor: pointer; - - &:hover { - background-color: ${get('colors.actionListItem.default.hoverBg')}; - - @media (forced-colors: active) { - outline: 2px solid transparent; - outline-offset: -2px; + /* + * WARNING: This is a performance optimization. + * + * We define styles for the tree items at the root level of the tree + * to avoid recomputing the styles for each item when the tree updates. + * We're sacraficing maintainability for performance because TreeView + * needs to be performant enough to handle large trees (thousands of items). + * + * This is intended to be a temporary solution until we can improve the + * performance of our styling patterns. + * + * Do NOT copy this pattern without understanding the tradeoffs. + * Do NOT reference PRIVATE_* classnames outside of this file. + */ + .PRIVATE_TreeView-item { + outline: none; + + &:focus-visible > div, + &.focus-visible > div { + box-shadow: inset 0 0 0 2px ${get(`colors.accent.fg`)}; + @media (forced-colors: active) { + outline: 2px solid HighlightText; + outline-offset: -2; + } + } + &[data-has-leading-action] { + --has-leading-action: 1; } } - @media (pointer: coarse) { - --toggle-width: 1.5rem; /* 24px */ - --min-item-height: 2.75rem; /* 44px */ - } + .PRIVATE_TreeView-item-container { + --level: 1; /* default level */ + --toggle-width: 1rem; /* 16px */ + --min-item-height: 2rem; /* 32px */ + position: relative; + display: grid; + --leading-action-width: calc(var(--has-leading-action, 0) * 1.5rem); + --spacer-width: calc(calc(var(--level) - 1) * (var(--toggle-width) / 2)); + grid-template-columns: var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr; + grid-template-areas: 'spacer leadingAction toggle content'; + width: 100%; + font-size: ${get('fontSizes.1')}; + color: ${get('colors.fg.default')}; + border-radius: ${get('radii.2')}; + cursor: pointer; - &:has(.PRIVATE_TreeView-item-skeleton):hover { - background-color: transparent; - cursor: default; + &:hover { + background-color: ${get('colors.actionListItem.default.hoverBg')}; - @media (forced-colors: active) { - outline: none; + @media (forced-colors: active) { + outline: 2px solid transparent; + outline-offset: -2px; + } } - } - } - &[data-omit-spacer='true'] .PRIVATE_TreeView-item-container { - grid-template-columns: 0 0 0 1fr; - } + @media (pointer: coarse) { + --toggle-width: 1.5rem; /* 24px */ + --min-item-height: 2.75rem; /* 44px */ + } - .PRIVATE_TreeView-item[aria-current='true'] > .PRIVATE_TreeView-item-container { - background-color: ${get('colors.actionListItem.default.selectedBg')}; + &:has(.PRIVATE_TreeView-item-skeleton):hover { + background-color: transparent; + cursor: default; - /* Current item indicator */ - &::after { - content: ''; - position: absolute; - top: calc(50% - 0.75rem); /* 50% - 12px */ - left: -${get('space.2')}; - width: 0.25rem; /* 4px */ - height: 1.5rem; /* 24px */ - background-color: ${get('colors.accent.fg')}; - border-radius: ${get('radii.2')}; + @media (forced-colors: active) { + outline: none; + } + } + } + + &[data-omit-spacer='true'] .PRIVATE_TreeView-item-container { + grid-template-columns: 0 0 0 1fr; + } - @media (forced-colors: active) { - background-color: HighlightText; + .PRIVATE_TreeView-item[aria-current='true'] > .PRIVATE_TreeView-item-container { + background-color: ${get('colors.actionListItem.default.selectedBg')}; + + /* Current item indicator */ + &::after { + content: ''; + position: absolute; + top: calc(50% - 0.75rem); /* 50% - 12px */ + left: -${get('space.2')}; + width: 0.25rem; /* 4px */ + height: 1.5rem; /* 24px */ + background-color: ${get('colors.accent.fg')}; + border-radius: ${get('radii.2')}; + + @media (forced-colors: active) { + background-color: HighlightText; + } } } - } - .PRIVATE_TreeView-item-toggle { - grid-area: toggle; - display: flex; - justify-content: center; - align-items: flex-start; - /* The toggle should appear vertically centered for single-line items, but remain at the top for items that wrap + .PRIVATE_TreeView-item-toggle { + grid-area: toggle; + display: flex; + justify-content: center; + align-items: flex-start; + /* The toggle should appear vertically centered for single-line items, but remain at the top for items that wrap across more lines. */ - padding-top: calc(var(--min-item-height) / 2 - ${TOGGLE_ICON_SIZE}px / 2); - height: 100%; - color: ${get('colors.fg.muted')}; - } + padding-top: calc(var(--min-item-height) / 2 - ${TOGGLE_ICON_SIZE}px / 2); + height: 100%; + color: ${get('colors.fg.muted')}; + } - .PRIVATE_TreeView-item-toggle--hover:hover { - background-color: ${get('colors.treeViewItem.chevron.hoverBg')}; - } + .PRIVATE_TreeView-item-toggle--hover:hover { + background-color: ${get('colors.treeViewItem.chevron.hoverBg')}; + } - .PRIVATE_TreeView-item-toggle--end { - border-top-left-radius: ${get('radii.2')}; - border-bottom-left-radius: ${get('radii.2')}; - } + .PRIVATE_TreeView-item-toggle--end { + border-top-left-radius: ${get('radii.2')}; + border-bottom-left-radius: ${get('radii.2')}; + } - .PRIVATE_TreeView-item-content { - grid-area: content; - display: flex; - height: 100%; - padding: 0 ${get('space.2')}; - gap: ${get('space.2')}; - line-height: var(--custom-line-height, var(--text-body-lineHeight-medium, 1.4285)); - /* The dynamic top and bottom padding to maintain the minimum item height for single line items */ - padding-top: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2); - padding-bottom: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2); - } + .PRIVATE_TreeView-item-content { + grid-area: content; + display: flex; + height: 100%; + padding: 0 ${get('space.2')}; + gap: ${get('space.2')}; + line-height: var(--custom-line-height, var(--text-body-lineHeight-medium, 1.4285)); + /* The dynamic top and bottom padding to maintain the minimum item height for single line items */ + padding-top: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2); + padding-bottom: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2); + } - .PRIVATE_TreeView-item-content-text { - flex: 1 1 auto; - width: 0; - } + .PRIVATE_TreeView-item-content-text { + flex: 1 1 auto; + width: 0; + } - &[data-truncate-text='true'] .PRIVATE_TreeView-item-content-text { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } + &[data-truncate-text='true'] .PRIVATE_TreeView-item-content-text { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } - &[data-truncate-text='false'] .PRIVATE_TreeView-item-content-text { - word-break: break-word; - } + &[data-truncate-text='false'] .PRIVATE_TreeView-item-content-text { + word-break: break-word; + } - .PRIVATE_TreeView-item-visual { - display: flex; - align-items: center; - color: ${get('colors.fg.muted')}; - /* The visual icons should appear vertically centered for single-line items, but remain at the top for items that wrap + .PRIVATE_TreeView-item-visual { + display: flex; + align-items: center; + color: ${get('colors.fg.muted')}; + /* The visual icons should appear vertically centered for single-line items, but remain at the top for items that wrap across more lines. */ - height: var(--custom-line-height, 1.3rem); - } + height: var(--custom-line-height, 1.3rem); + } - .PRIVATE_TreeView-item-leading-action { - display: flex; - color: ${get('colors.fg.muted')}; - grid-area: leadingAction; - } + .PRIVATE_TreeView-item-leading-action { + display: flex; + color: ${get('colors.fg.muted')}; + grid-area: leadingAction; + } - .PRIVATE_TreeView-item-level-line { - width: 100%; - height: 100%; - border-right: 1px solid; + .PRIVATE_TreeView-item-level-line { + width: 100%; + height: 100%; + border-right: 1px solid; + + /* + * On devices without hover, the nesting indicator lines + * appear at all times. + */ + border-color: ${get('colors.border.subtle')}; + } /* - * On devices without hover, the nesting indicator lines - * appear at all times. + * On devices with :hover support, the nesting indicator lines + * fade in when the user mouses over the entire component, + * or when there's focus inside the component. This makes + * sure the component remains simple when not in use. */ - border-color: ${get('colors.border.subtle')}; - } + @media (hover: hover) { + .PRIVATE_TreeView-item-level-line { + border-color: transparent; + } - /* - * On devices with :hover support, the nesting indicator lines - * fade in when the user mouses over the entire component, - * or when there's focus inside the component. This makes - * sure the component remains simple when not in use. - */ - @media (hover: hover) { - .PRIVATE_TreeView-item-level-line { - border-color: transparent; + &:hover .PRIVATE_TreeView-item-level-line, + &:focus-within .PRIVATE_TreeView-item-level-line { + border-color: ${get('colors.border.subtle')}; + } } - &:hover .PRIVATE_TreeView-item-level-line, - &:focus-within .PRIVATE_TreeView-item-level-line { - border-color: ${get('colors.border.subtle')}; + .PRIVATE_TreeView-directory-icon { + display: grid; + color: ${get('colors.treeViewItem.directory.fill')}; } - } - .PRIVATE_TreeView-directory-icon { - display: grid; - color: ${get('colors.treeViewItem.directory.fill')}; - } + .PRIVATE_VisuallyHidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; + } - .PRIVATE_VisuallyHidden { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; - } -` + ${sx} + `, +) const Root: React.FC = ({ 'aria-label': ariaLabel, @@ -327,6 +338,8 @@ const Root: React.FC = ({ expandedStateCache.current = new Map() } + const cssModulesEnabled = useFeatureFlag('primer_react_tree_view_css_modules') + return ( = ({ data-omit-spacer={flat} data-truncate-text={truncate || false} onMouseDown={onMouseDown} - className={className} + className={clsx(className, {[classes.TreeViewRootUlStyles]: cssModulesEnabled})} style={style} > {children} From dbe480efd9f92fb8ec2e2fba24b382d3543872e2 Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Wed, 13 Nov 2024 04:05:02 +0000 Subject: [PATCH 04/17] Reference CSS module classnames --- .../react/src/TreeView/TreeView.module.css | 130 ++++++++++-------- packages/react/src/TreeView/TreeView.tsx | 83 +++++++++-- 2 files changed, 145 insertions(+), 68 deletions(-) diff --git a/packages/react/src/TreeView/TreeView.module.css b/packages/react/src/TreeView/TreeView.module.css index 9a41a4bc0134..b7562d0cbacf 100644 --- a/packages/react/src/TreeView/TreeView.module.css +++ b/packages/react/src/TreeView/TreeView.module.css @@ -1,7 +1,7 @@ .TreeViewRootUlStyles { - list-style: none; padding: 0; margin: 0; + list-style: none; /* * WARNING: This is a performance optimization. @@ -17,37 +17,44 @@ * Do NOT copy this pattern without understanding the tradeoffs. * Do NOT reference PRIVATE_* classnames outside of this file. */ - .PRIVATE_TreeView-item { + .PRIVATE_TreeViewItem { outline: none; - &:focus-visible > div, - &.focus-visible > div { - box-shadow: inset 0 0 0 2px var(--fgColor-accent); + &:focus-visible>div, + &.focus-visible>div { + box-shadow: var(--boxShadow-thick) var(--fgColor-accent); + @media (forced-colors: active) { outline: 2px solid HighlightText; outline-offset: -2; } } + &[data-has-leading-action] { --has-leading-action: 1; } } - .PRIVATE_TreeView-item-container { - --level: 1; /* default level */ - --toggle-width: 1rem; /* 16px */ - --min-item-height: 2rem; /* 32px */ + .PRIVATE_TreeViewItemContainer { + --level: 1; + /* default level */ + --toggle-width: 1rem; + /* 16px */ + --min-item-height: 2rem; + /* 32px */ + position: relative; display: grid; - --leading-action-width: calc(var(--has-leading-action, 0) * 1.5rem); - --spacer-width: calc(calc(var(--level) - 1) * (var(--toggle-width) / 2)); - grid-template-columns: var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr; - grid-template-areas: 'spacer leadingAction toggle content'; width: 100%; - font-size: var(--base-size-14); + font-size: var(--text-body-size-medium); color: var(--fgColor-default); - border-radius: var(--borderRadius-medium); cursor: pointer; + border-radius: var(--borderRadius-medium); + grid-template-columns: var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr; + grid-template-areas: 'spacer leadingAction toggle content'; + + --leading-action-width: calc(var(--has-leading-action, 0) * 1.5rem); + --spacer-width: calc(calc(var(--level) - 1) * (var(--toggle-width) / 2)); &:hover { background-color: var(--control-transparent-bgColor-hover); @@ -59,13 +66,15 @@ } @media (pointer: coarse) { - --toggle-width: 1.5rem; /* 24px */ - --min-item-height: 2.75rem; /* 44px */ + --toggle-width: 1.5rem; + /* 24px */ + --min-item-height: 2.75rem; + /* 44px */ } - &:has(.PRIVATE_TreeView-item-skeleton):hover { - background-color: transparent; + &:has(.PRIVATE_TreeViewItemSkeleton):hover { cursor: default; + background-color: transparent; @media (forced-colors: active) { outline: none; @@ -73,22 +82,26 @@ } } - &[data-omit-spacer='true'] .PRIVATE_TreeView-item-container { + &[data-omit-spacer='true'] .PRIVATE_TreeViewItemContainer { grid-template-columns: 0 0 0 1fr; } - .PRIVATE_TreeView-item[aria-current='true'] > .PRIVATE_TreeView-item-container { + .PRIVATE_TreeViewItem[aria-current='true']>.PRIVATE_TreeViewItemContainer { background-color: var(--control-transparent-bgColor-selected); /* Current item indicator */ + /* stylelint-disable-next-line selector-max-specificity */ &::after { - content: ''; position: absolute; - top: calc(50% - 0.75rem); /* 50% - 12px */ + top: calc(50% - 0.75rem); + /* 50% - 12px */ left: calc(-1 * var(--base-size-8)); - width: 0.25rem; /* 4px */ - height: 1.5rem; /* 24px */ - background-color: var(--fgColor-accent); + width: 0.25rem; + /* 4px */ + height: 1.5rem; + /* 24px */ + content: ''; + background-color: var(--bgColor-accent-emphasis); border-radius: var(--borderRadius-medium); @media (forced-colors: active) { @@ -97,79 +110,85 @@ } } - .PRIVATE_TreeView-item-toggle { - grid-area: toggle; + .PRIVATE_TreeViewItemToggle { display: flex; - justify-content: center; - align-items: flex-start; + height: 100%; + /* The toggle should appear vertically centered for single-line items, but remain at the top for items that wrap across more lines. */ - padding-top: calc(var(--min-item-height) / 2 - 12px / 2); - height: 100%; + /* stylelint-disable-next-line primer/spacing */ + padding-top: calc(var(--min-item-height) / 2 - var(--base-size-12) / 2); color: var(--fgColor-muted); + grid-area: toggle; + justify-content: center; + align-items: flex-start; } - .PRIVATE_TreeView-item-toggle--hover:hover { + .PRIVATE_TreeViewItemToggleHover:hover { background-color: var(--color-tree-view-item-chevron-hover-bg); } - .PRIVATE_TreeView-item-toggle--end { + .PRIVATE_TreeViewItemToggleEnd { border-top-left-radius: var(--borderRadius-medium); border-bottom-left-radius: var(--borderRadius-medium); } - .PRIVATE_TreeView-item-content { - grid-area: content; + .PRIVATE_TreeViewItemContent { display: flex; height: 100%; padding: 0 var(--base-size-8); - gap: var(--stack-gap-condensed); - line-height: var(--custom-line-height, var(--text-body-lineHeight-medium, 1.4285)); + /* The dynamic top and bottom padding to maintain the minimum item height for single line items */ + /* stylelint-disable-next-line primer/spacing */ padding-top: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2); + /* stylelint-disable-next-line primer/spacing */ padding-bottom: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2); + line-height: var(--custom-line-height, var(--text-body-lineHeight-medium, 1.4285)); + grid-area: content; + gap: var(--stack-gap-condensed); } - .PRIVATE_TreeView-item-content-text { + .PRIVATE_TreeViewItemContentText { flex: 1 1 auto; width: 0; } - &[data-truncate-text='true'] .PRIVATE_TreeView-item-content-text { + &[data-truncate-text='true'] .PRIVATE_TreeViewItemContentText { overflow: hidden; - white-space: nowrap; text-overflow: ellipsis; + white-space: nowrap; } - &[data-truncate-text='false'] .PRIVATE_TreeView-item-content-text { + &[data-truncate-text='false'] .PRIVATE_TreeViewItemContentText { word-break: break-word; } - .PRIVATE_TreeView-item-visual { + .PRIVATE_TreeViewItemVisual { display: flex; - align-items: center; - color: var(--fgColor-muted); + /* The visual icons should appear vertically centered for single-line items, but remain at the top for items that wrap across more lines. */ height: var(--custom-line-height, 1.3rem); + color: var(--fgColor-muted); + align-items: center; } - .PRIVATE_TreeView-item-leading-action { + .PRIVATE_TreeViewItemLeadingAction { display: flex; color: var(--fgColor-muted); grid-area: leadingAction; } - .PRIVATE_TreeView-item-level-line { + .PRIVATE_TreeViewItemLevelLine { width: 100%; height: 100%; - border-right: 1px solid; /* * On devices without hover, the nesting indicator lines * appear at all times. */ border-color: var(--borderColor-muted); + border-right: var(--borderWidth-thin) solid; } /* @@ -179,30 +198,31 @@ * sure the component remains simple when not in use. */ @media (hover: hover) { - .PRIVATE_TreeView-item-level-line { + .PRIVATE_TreeViewItemLevelLine { border-color: transparent; } - &:hover .PRIVATE_TreeView-item-level-line, - &:focus-within .PRIVATE_TreeView-item-level-line { + &:hover .PRIVATE_TreeViewItemLevelLine, + &:focus-within .PRIVATE_TreeViewItemLevelLine { border-color: var(--borderColor-muted); } } - .PRIVATE_TreeView-directory-icon { + .PRIVATE_TreeViewDirectoryIcon { display: grid; - color: var(--treeViewItem-leadingVisual-bgColor-rest); + color: var(--treeViewItem-leadingVisual-iconColor-rest); } - .PRIVATE_VisuallyHidden { + .PRIVATE_TreeViewVisuallyHidden { position: absolute; width: 1px; height: 1px; padding: 0; + /* stylelint-disable-next-line primer/spacing */ margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; } -} +} \ No newline at end of file diff --git a/packages/react/src/TreeView/TreeView.tsx b/packages/react/src/TreeView/TreeView.tsx index 28288755b902..a09d39a1e29a 100644 --- a/packages/react/src/TreeView/TreeView.tsx +++ b/packages/react/src/TreeView/TreeView.tsx @@ -484,6 +484,8 @@ const Item = React.forwardRef( slots.trailingVisual ? trailingVisualId : null, ].filter(Boolean) + const cssModulesEnabled = useFeatureFlag('primer_react_css_modules_team') + return ( ( > {/* @ts-ignore Box doesn't have type support for `ref` used in combination with `as` */}
  • } tabIndex={0} id={itemId} @@ -540,7 +542,9 @@ const Item = React.forwardRef( }} >
    ( 'PRIVATE_TreeView-item-toggle', onSelect && 'PRIVATE_TreeView-item-toggle--hover', level === 1 && 'PRIVATE_TreeView-item-toggle--end', + { + [(classes.PRIVATE_TreeViewItemToggle, + classes.PRIVATE_TreeViewItemToggleHover, + classes.PRIVATE_TreeViewItemToggleEnd)]: cssModulesEnabled, + }, )} onClick={event => { if (onSelect) { @@ -577,9 +586,20 @@ const Item = React.forwardRef( )}
    ) : null} -
    +
    {slots.leadingVisual} - {childrenWithoutSubTree} + + {childrenWithoutSubTree} + {slots.trailingVisual}
    @@ -592,10 +612,16 @@ const Item = React.forwardRef( /** Lines to indicate the depth of an item in a TreeView */ const LevelIndicatorLines: React.FC<{level: number}> = ({level}) => { + const cssModulesEnabled = useFeatureFlag('primer_react_css_modules_team') return (
    {Array.from({length: level - 1}).map((_, index) => ( -
    +
    ))}
    ) @@ -790,6 +816,7 @@ type LoadingItemProps = { const LoadingItem = React.forwardRef(({count}, ref) => { const itemId = useId() + const cssModulesEnabled = useFeatureFlag('primer_react_css_modules_team') if (count) { return ( @@ -797,7 +824,9 @@ const LoadingItem = React.forwardRef(({count}, re {Array.from({length: count}).map((_, i) => { return })} -
    Loading {count} items
    +
    + Loading {count} items +
    ) } @@ -849,14 +878,22 @@ export type TreeViewVisualProps = { } const LeadingVisual: React.FC = props => { + const cssModulesEnabled = useFeatureFlag('primer_react_css_modules_team') const {isExpanded, leadingVisualId} = React.useContext(ItemContext) const children = typeof props.children === 'function' ? props.children({isExpanded}) : props.children return ( <> -
    +
    {props.label}
    -
    +
    {children}
    @@ -866,14 +903,22 @@ const LeadingVisual: React.FC = props => { LeadingVisual.displayName = 'TreeView.LeadingVisual' const TrailingVisual: React.FC = props => { + const cssModulesEnabled = useFeatureFlag('primer_react_css_modules_team') const {isExpanded, trailingVisualId} = React.useContext(ItemContext) const children = typeof props.children === 'function' ? props.children({isExpanded}) : props.children return ( <> -
    +
    {props.label}
    -
    +
    {children}
    @@ -886,14 +931,23 @@ TrailingVisual.displayName = 'TreeView.TrailingVisual' // TreeView.LeadingAction const LeadingAction: React.FC = props => { + const cssModulesEnabled = useFeatureFlag('primer_react_css_modules_team') const {isExpanded} = React.useContext(ItemContext) const children = typeof props.children === 'function' ? props.children({isExpanded}) : props.children return ( <> -
    +
    {props.label}
    -
    +
    {children}
    @@ -905,10 +959,13 @@ LeadingAction.displayName = 'TreeView.LeadingAction' // TreeView.DirectoryIcon const DirectoryIcon = () => { + const cssModulesEnabled = useFeatureFlag('primer_react_css_modules_team') const {isExpanded} = React.useContext(ItemContext) const Icon = isExpanded ? FileDirectoryOpenFillIcon : FileDirectoryFillIcon return ( -
    +
    ) From 4a1c8ab5db0ee82aaa4b948e0442530eb8cf13df Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Tue, 12 Nov 2024 19:22:04 +0000 Subject: [PATCH 05/17] update skeleton components to use css modules --- .../react/src/TreeView/TreeView.module.css | 35 +++++++++ packages/react/src/TreeView/TreeView.tsx | 76 +++++++++++-------- 2 files changed, 81 insertions(+), 30 deletions(-) diff --git a/packages/react/src/TreeView/TreeView.module.css b/packages/react/src/TreeView/TreeView.module.css index b7562d0cbacf..b2cf0ebe30dd 100644 --- a/packages/react/src/TreeView/TreeView.module.css +++ b/packages/react/src/TreeView/TreeView.module.css @@ -225,4 +225,39 @@ white-space: nowrap; border-width: 0; } +} + +.TreeViewSkeletonItemContainerStyle { + display: flex; + align-items: center; + column-gap: 0.5rem; + height: 2rem; + + @media (pointer: coarse) { + height: 2.75rem; + } + + &:nth-of-type(5n + 1) { + --tree-item-loading-width: 67%; + } + + &:nth-of-type(5n + 2) { + --tree-item-loading-width: 47%; + } + + &:nth-of-type(5n + 3) { + --tree-item-loading-width: 73%; + } + + &:nth-of-type(5n + 4) { + --tree-item-loading-width: 64%; + } + + &:nth-of-type(5n + 5) { + --tree-item-loading-width: 50%; + } +} + +.TreeItemSkeletonTextStyles { + width: var(--tree-item-loading-width, 67%); } \ No newline at end of file diff --git a/packages/react/src/TreeView/TreeView.tsx b/packages/react/src/TreeView/TreeView.tsx index a09d39a1e29a..a858aa6739de 100644 --- a/packages/react/src/TreeView/TreeView.tsx +++ b/packages/react/src/TreeView/TreeView.tsx @@ -766,46 +766,62 @@ function usePreviousValue(value: T): T { return ref.current } -const StyledSkeletonItemContainer = styled.span.attrs({className: 'PRIVATE_TreeView-item-skeleton'})` - display: flex; - align-items: center; - column-gap: 0.5rem; - height: 2rem; - - @media (pointer: coarse) { - height: 2.75rem; - } +const StyledSkeletonItemContainer = toggleStyledComponent( + 'primer_react_tree_view_css_modules', + 'span', + styled.span.attrs({ + className: 'PRIVATE_TreeView-item-skeleton', + })` + display: flex; + align-items: center; + column-gap: 0.5rem; + height: 2rem; + + @media (pointer: coarse) { + height: 2.75rem; + } - &:nth-of-type(5n + 1) { - --tree-item-loading-width: 67%; - } + &:nth-of-type(5n + 1) { + --tree-item-loading-width: 67%; + } - &:nth-of-type(5n + 2) { - --tree-item-loading-width: 47%; - } + &:nth-of-type(5n + 2) { + --tree-item-loading-width: 47%; + } - &:nth-of-type(5n + 3) { - --tree-item-loading-width: 73%; - } + &:nth-of-type(5n + 3) { + --tree-item-loading-width: 73%; + } - &:nth-of-type(5n + 4) { - --tree-item-loading-width: 64%; - } + &:nth-of-type(5n + 4) { + --tree-item-loading-width: 64%; + } - &:nth-of-type(5n + 5) { - --tree-item-loading-width: 50%; - } -` + &:nth-of-type(5n + 5) { + --tree-item-loading-width: 50%; + } + `, +) -const StyledSkeletonText = styled(SkeletonText)` - width: var(--tree-item-loading-width, 67%); -` +const StyledSkeletonText = toggleStyledComponent( + 'primer_react_tree_view_css_modules', + SkeletonText, + styled(SkeletonText)` + width: var(--tree-item-loading-width, 67%); + `, +) const SkeletonItem = () => { + const cssModulesEnabled = useFeatureFlag('primer_react_tree_view_css_modules') return ( - + - + ) } From e0795071f4a311649c6d666a1f7a1d3f27ab2e13 Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Tue, 12 Nov 2024 19:58:56 +0000 Subject: [PATCH 06/17] add test for className support --- packages/react/src/TreeView/TreeView.test.tsx | 32 ++++++++++++++++++- packages/react/src/TreeView/TreeView.tsx | 10 +++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/packages/react/src/TreeView/TreeView.test.tsx b/packages/react/src/TreeView/TreeView.test.tsx index eb2329f9b22c..34dc96e5df9f 100644 --- a/packages/react/src/TreeView/TreeView.test.tsx +++ b/packages/react/src/TreeView/TreeView.test.tsx @@ -4,6 +4,7 @@ import React from 'react' import {ThemeProvider} from '../ThemeProvider' import type {SubTreeState} from './TreeView' import {TreeView} from './TreeView' +import {FeatureFlags} from '../FeatureFlags' jest.useFakeTimers() @@ -1364,7 +1365,7 @@ describe('State', () => { }) }) -describe('Asyncronous loading', () => { +describe('Asynchronous loading', () => { it('updates aria live region when loading is done', () => { function TestTree() { const [state, setState] = React.useState('initial') @@ -1640,3 +1641,32 @@ describe('Asyncronous loading', () => { expect(getByRole('treeitem', {name: 'empty child'})).toHaveAttribute('aria-expanded') }) }) + +describe('CSS Module Migration', () => { + it('should support `className` on the outermost element', () => { + const TreeViewTestComponent = () => ( + + Item 1 + Item 2 + Item 3 + + ) + const FeatureFlagElement = () => { + return ( + + + + ) + } + + // Testing on the second child element because the first child element is visually hidden + expect(render().container.children[1]).toHaveClass('test-class-name') + expect(render().container.children[1]).toHaveClass('test-class-name') + }) +}) diff --git a/packages/react/src/TreeView/TreeView.tsx b/packages/react/src/TreeView/TreeView.tsx index a858aa6739de..eb71ba6ae298 100644 --- a/packages/react/src/TreeView/TreeView.tsx +++ b/packages/react/src/TreeView/TreeView.tsx @@ -78,7 +78,7 @@ export type TreeViewProps = { const TOGGLE_ICON_SIZE = 12 const UlBox = toggleStyledComponent( - 'primer_react_tree_view_css_modules', + 'primer_react_css_modules_team', 'ul', styled.ul` list-style: none; @@ -338,7 +338,7 @@ const Root: React.FC = ({ expandedStateCache.current = new Map() } - const cssModulesEnabled = useFeatureFlag('primer_react_tree_view_css_modules') + const cssModulesEnabled = useFeatureFlag('primer_react_css_modules_team') return ( (value: T): T { } const StyledSkeletonItemContainer = toggleStyledComponent( - 'primer_react_tree_view_css_modules', + 'primer_react_css_modules_team', 'span', styled.span.attrs({ className: 'PRIVATE_TreeView-item-skeleton', @@ -804,7 +804,7 @@ const StyledSkeletonItemContainer = toggleStyledComponent( ) const StyledSkeletonText = toggleStyledComponent( - 'primer_react_tree_view_css_modules', + 'primer_react_css_modules_team', SkeletonText, styled(SkeletonText)` width: var(--tree-item-loading-width, 67%); @@ -812,7 +812,7 @@ const StyledSkeletonText = toggleStyledComponent( ) const SkeletonItem = () => { - const cssModulesEnabled = useFeatureFlag('primer_react_tree_view_css_modules') + const cssModulesEnabled = useFeatureFlag('primer_react_css_modules_team') return ( Date: Wed, 13 Nov 2024 02:29:06 +0000 Subject: [PATCH 07/17] add changeset --- .changeset/gentle-yaks-shake.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/gentle-yaks-shake.md diff --git a/.changeset/gentle-yaks-shake.md b/.changeset/gentle-yaks-shake.md new file mode 100644 index 000000000000..c84b39ddca52 --- /dev/null +++ b/.changeset/gentle-yaks-shake.md @@ -0,0 +1,5 @@ +--- +"@primer/react": minor +--- + +Update `TreeView` component to use CSS Modules From 0953ff9711273618cc92dda29d45f432f4ffd7de Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Wed, 13 Nov 2024 04:43:21 +0000 Subject: [PATCH 08/17] auto fix with 'npm run lint:css:fix' --- .../react/src/TreeView/TreeView.module.css | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/packages/react/src/TreeView/TreeView.module.css b/packages/react/src/TreeView/TreeView.module.css index b2cf0ebe30dd..1626fda9b71a 100644 --- a/packages/react/src/TreeView/TreeView.module.css +++ b/packages/react/src/TreeView/TreeView.module.css @@ -20,8 +20,8 @@ .PRIVATE_TreeViewItem { outline: none; - &:focus-visible>div, - &.focus-visible>div { + &:focus-visible > div, + &.focus-visible > div { box-shadow: var(--boxShadow-thick) var(--fgColor-accent); @media (forced-colors: active) { @@ -37,11 +37,8 @@ .PRIVATE_TreeViewItemContainer { --level: 1; - /* default level */ --toggle-width: 1rem; - /* 16px */ --min-item-height: 2rem; - /* 32px */ position: relative; display: grid; @@ -67,9 +64,7 @@ @media (pointer: coarse) { --toggle-width: 1.5rem; - /* 24px */ --min-item-height: 2.75rem; - /* 44px */ } &:has(.PRIVATE_TreeViewItemSkeleton):hover { @@ -86,20 +81,17 @@ grid-template-columns: 0 0 0 1fr; } - .PRIVATE_TreeViewItem[aria-current='true']>.PRIVATE_TreeViewItemContainer { + .PRIVATE_TreeViewItem[aria-current='true'] > .PRIVATE_TreeViewItemContainer { background-color: var(--control-transparent-bgColor-selected); /* Current item indicator */ /* stylelint-disable-next-line selector-max-specificity */ &::after { position: absolute; - top: calc(50% - 0.75rem); - /* 50% - 12px */ + top: calc(50% - var(--base-size-12)); left: calc(-1 * var(--base-size-8)); width: 0.25rem; - /* 4px */ height: 1.5rem; - /* 24px */ content: ''; background-color: var(--bgColor-accent-emphasis); border-radius: var(--borderRadius-medium); @@ -260,4 +252,4 @@ .TreeItemSkeletonTextStyles { width: var(--tree-item-loading-width, 67%); -} \ No newline at end of file +} From c2a6b5627f84ea88103cb6d4c1d0b59eba947123 Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Wed, 13 Nov 2024 05:21:47 +0000 Subject: [PATCH 09/17] fix syntax for multiple modules classes --- packages/react/src/TreeView/TreeView.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/react/src/TreeView/TreeView.tsx b/packages/react/src/TreeView/TreeView.tsx index eb71ba6ae298..ec965653c142 100644 --- a/packages/react/src/TreeView/TreeView.tsx +++ b/packages/react/src/TreeView/TreeView.tsx @@ -568,9 +568,9 @@ const Item = React.forwardRef( onSelect && 'PRIVATE_TreeView-item-toggle--hover', level === 1 && 'PRIVATE_TreeView-item-toggle--end', { - [(classes.PRIVATE_TreeViewItemToggle, - classes.PRIVATE_TreeViewItemToggleHover, - classes.PRIVATE_TreeViewItemToggleEnd)]: cssModulesEnabled, + [classes.PRIVATE_TreeViewItemToggle]: cssModulesEnabled, + [classes.PRIVATE_TreeViewItemToggleHover]: cssModulesEnabled, + [classes.PRIVATE_TreeViewItemToggleEnd]: cssModulesEnabled, }, )} onClick={event => { @@ -816,7 +816,10 @@ const SkeletonItem = () => { return ( From 21adedbc95e39a1b62ca2e0c31e87ac81e11911b Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Wed, 13 Nov 2024 17:16:13 +0000 Subject: [PATCH 10/17] update variable to prevent regression test failures --- packages/react/src/TreeView/TreeView.module.css | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/react/src/TreeView/TreeView.module.css b/packages/react/src/TreeView/TreeView.module.css index 1626fda9b71a..d762081a0aeb 100644 --- a/packages/react/src/TreeView/TreeView.module.css +++ b/packages/react/src/TreeView/TreeView.module.css @@ -93,7 +93,13 @@ width: 0.25rem; height: 1.5rem; content: ''; - background-color: var(--bgColor-accent-emphasis); + + /* + * Use fgColor accent for consistency across all themes. Using the "correct" variable, + * --bgColor-accent-emphasis, causes vrt failures for dark high contrast mode + */ + /* stylelint-disable-next-line primer/colors */ + background-color: var(--fgColor-accent); border-radius: var(--borderRadius-medium); @media (forced-colors: active) { From e97cf727641632e763b5e01966786316095040d2 Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Wed, 13 Nov 2024 21:00:27 +0000 Subject: [PATCH 11/17] workaround for directory icon color For the directory icon color, [previously, we were using](https://github.com/primer/react/blob/21adedbc95e39a1b62ca2e0c31e87ac81e11911b/packages/react/src/TreeView/TreeView.module.css#L211): ``` var(--treeViewItem-leadingVisual-bgColor-rest, var(--color-tree-view-item-chevron-directory-fill, #CUSTOM_FALLBACK_FOR_EACH_MODE)) ``` `--treeViewItem-leadingVisual-bgColor-rest` was replaced by `--treeViewItem-leadingVisual-iconColor-rest` in https://github.com/primer/primitives/pull/686. When that replacement was made, we didn't update the legacy theme in this repo (makes sense), so since that variable no longer existed, we always use the fallback hex code. With these changes, we're now using `--treeViewItem-leadingVisual-iconColor-rest`. That variable works for all modes except dark high contrast. I believe this is because whatever [hex code that variable represents in dark high contrast mode](https://github.com/primer/primitives/blob/9f1033462619f7a3e3a191dcfc0a50cf7708c79a/src/tokens/functional/color/dark/patterns-dark.json5#L2081) (#b7bdc8) is different than [this repo's custom legacy theme dark high contrast hex code](https://github.com/primer/react/blob/21adedbc95e39a1b62ca2e0c31e87ac81e11911b/packages/react/src/legacy-theme/ts/color-schemes.ts#L3535) (#f0f3f6). As a workaround, I've added this workaround for dark high contrast mode specifically. We should implement a more robust solution in the future, either updating `--treeViewItem-leadingVisual-iconColor-rest` to support the expected color for dark high contrast mode, or updating the expected color to match the current dark high contrast mode color. --- packages/react/src/TreeView/TreeView.module.css | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/react/src/TreeView/TreeView.module.css b/packages/react/src/TreeView/TreeView.module.css index d762081a0aeb..3ca7deaedb98 100644 --- a/packages/react/src/TreeView/TreeView.module.css +++ b/packages/react/src/TreeView/TreeView.module.css @@ -225,6 +225,17 @@ } } +/* + * Using "legacy" variable and hex code fallback as a workaround for dark high + * contrast mode, which currently does not support the expected color for + * `--treeViewItem-leadingVisual-iconColor-rest` variable. + */ +/* stylelint-disable-next-line selector-no-qualifying-type */ +body[data-dark-theme='dark_high_contrast'] .PRIVATE_TreeViewDirectoryIcon { + /* stylelint-disable-next-line primer/colors */ + color: var(--color-tree-view-item-directory-fill, #f0f3f6); +} + .TreeViewSkeletonItemContainerStyle { display: flex; align-items: center; From c1cf6e3f8683b22e529e6baf9fd58332084aa125 Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Wed, 13 Nov 2024 22:30:02 -0500 Subject: [PATCH 12/17] use `where` with attribute selector Co-authored-by: Jon Rohan --- packages/react/src/TreeView/TreeView.module.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/TreeView/TreeView.module.css b/packages/react/src/TreeView/TreeView.module.css index 3ca7deaedb98..7c9004ff3b46 100644 --- a/packages/react/src/TreeView/TreeView.module.css +++ b/packages/react/src/TreeView/TreeView.module.css @@ -77,7 +77,7 @@ } } - &[data-omit-spacer='true'] .PRIVATE_TreeViewItemContainer { + &:where([data-omit-spacer='true']) .PRIVATE_TreeViewItemContainer { grid-template-columns: 0 0 0 1fr; } From a4529222ea5b31aa6378b21081dbf5c154cb31da Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Wed, 13 Nov 2024 22:30:23 -0500 Subject: [PATCH 13/17] use up-to-date color variable Co-authored-by: Katie Langerman <18661030+langermank@users.noreply.github.com> --- packages/react/src/TreeView/TreeView.module.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/TreeView/TreeView.module.css b/packages/react/src/TreeView/TreeView.module.css index 7c9004ff3b46..a24d5fba69b8 100644 --- a/packages/react/src/TreeView/TreeView.module.css +++ b/packages/react/src/TreeView/TreeView.module.css @@ -123,7 +123,7 @@ } .PRIVATE_TreeViewItemToggleHover:hover { - background-color: var(--color-tree-view-item-chevron-hover-bg); + background-color: var(--control-transparent-bgColor-hover); } .PRIVATE_TreeViewItemToggleEnd { From 1f6b6bcf0abdf7f567ff842e753315e3dcbea0ff Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Wed, 13 Nov 2024 22:31:59 -0500 Subject: [PATCH 14/17] Use `where` with attr selectors Co-authored-by: Jon Rohan --- packages/react/src/TreeView/TreeView.module.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react/src/TreeView/TreeView.module.css b/packages/react/src/TreeView/TreeView.module.css index a24d5fba69b8..2c7bc06deaa7 100644 --- a/packages/react/src/TreeView/TreeView.module.css +++ b/packages/react/src/TreeView/TreeView.module.css @@ -151,13 +151,13 @@ width: 0; } - &[data-truncate-text='true'] .PRIVATE_TreeViewItemContentText { + &:where([data-truncate-text='true']) .PRIVATE_TreeViewItemContentText { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } - &[data-truncate-text='false'] .PRIVATE_TreeViewItemContentText { + &:where([data-truncate-text='false']) .PRIVATE_TreeViewItemContentText { word-break: break-word; } From 0718102c37b6ada9e85eb4de2dced310f2c62985 Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Thu, 14 Nov 2024 03:53:11 +0000 Subject: [PATCH 15/17] drop PRIVATE_ prefix from css module classnames --- .../react/src/TreeView/TreeView.module.css | 45 +++++++++---------- packages/react/src/TreeView/TreeView.tsx | 36 +++++++-------- 2 files changed, 39 insertions(+), 42 deletions(-) diff --git a/packages/react/src/TreeView/TreeView.module.css b/packages/react/src/TreeView/TreeView.module.css index 2c7bc06deaa7..bc212bd58202 100644 --- a/packages/react/src/TreeView/TreeView.module.css +++ b/packages/react/src/TreeView/TreeView.module.css @@ -8,16 +8,15 @@ * * We define styles for the tree items at the root level of the tree * to avoid recomputing the styles for each item when the tree updates. - * We're sacraficing maintainability for performance because TreeView + * We're sacrificing maintainability for performance because TreeView * needs to be performant enough to handle large trees (thousands of items). * * This is intended to be a temporary solution until we can improve the * performance of our styling patterns. * * Do NOT copy this pattern without understanding the tradeoffs. - * Do NOT reference PRIVATE_* classnames outside of this file. */ - .PRIVATE_TreeViewItem { + .TreeViewItem { outline: none; &:focus-visible > div, @@ -35,7 +34,7 @@ } } - .PRIVATE_TreeViewItemContainer { + .TreeViewItemContainer { --level: 1; --toggle-width: 1rem; --min-item-height: 2rem; @@ -67,7 +66,7 @@ --min-item-height: 2.75rem; } - &:has(.PRIVATE_TreeViewItemSkeleton):hover { + &:has(.TreeViewItemSkeleton):hover { cursor: default; background-color: transparent; @@ -77,11 +76,11 @@ } } - &:where([data-omit-spacer='true']) .PRIVATE_TreeViewItemContainer { + &:where([data-omit-spacer='true']) .TreeViewItemContainer { grid-template-columns: 0 0 0 1fr; } - .PRIVATE_TreeViewItem[aria-current='true'] > .PRIVATE_TreeViewItemContainer { + .TreeViewItem[aria-current='true'] > .TreeViewItemContainer { background-color: var(--control-transparent-bgColor-selected); /* Current item indicator */ @@ -108,7 +107,7 @@ } } - .PRIVATE_TreeViewItemToggle { + .TreeViewItemToggle { display: flex; height: 100%; @@ -122,16 +121,16 @@ align-items: flex-start; } - .PRIVATE_TreeViewItemToggleHover:hover { + .TreeViewItemToggleHover:hover { background-color: var(--control-transparent-bgColor-hover); } - .PRIVATE_TreeViewItemToggleEnd { + .TreeViewItemToggleEnd { border-top-left-radius: var(--borderRadius-medium); border-bottom-left-radius: var(--borderRadius-medium); } - .PRIVATE_TreeViewItemContent { + .TreeViewItemContent { display: flex; height: 100%; padding: 0 var(--base-size-8); @@ -146,22 +145,22 @@ gap: var(--stack-gap-condensed); } - .PRIVATE_TreeViewItemContentText { + .TreeViewItemContentText { flex: 1 1 auto; width: 0; } - &:where([data-truncate-text='true']) .PRIVATE_TreeViewItemContentText { + &:where([data-truncate-text='true']) .TreeViewItemContentText { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } - &:where([data-truncate-text='false']) .PRIVATE_TreeViewItemContentText { + &:where([data-truncate-text='false']) .TreeViewItemContentText { word-break: break-word; } - .PRIVATE_TreeViewItemVisual { + .TreeViewItemVisual { display: flex; /* The visual icons should appear vertically centered for single-line items, but remain at the top for items that wrap @@ -171,13 +170,13 @@ align-items: center; } - .PRIVATE_TreeViewItemLeadingAction { + .TreeViewItemLeadingAction { display: flex; color: var(--fgColor-muted); grid-area: leadingAction; } - .PRIVATE_TreeViewItemLevelLine { + .TreeViewItemLevelLine { width: 100%; height: 100%; @@ -196,22 +195,22 @@ * sure the component remains simple when not in use. */ @media (hover: hover) { - .PRIVATE_TreeViewItemLevelLine { + .TreeViewItemLevelLine { border-color: transparent; } - &:hover .PRIVATE_TreeViewItemLevelLine, - &:focus-within .PRIVATE_TreeViewItemLevelLine { + &:hover .TreeViewItemLevelLine, + &:focus-within .TreeViewItemLevelLine { border-color: var(--borderColor-muted); } } - .PRIVATE_TreeViewDirectoryIcon { + .TreeViewDirectoryIcon { display: grid; color: var(--treeViewItem-leadingVisual-iconColor-rest); } - .PRIVATE_TreeViewVisuallyHidden { + .TreeViewVisuallyHidden { position: absolute; width: 1px; height: 1px; @@ -231,7 +230,7 @@ * `--treeViewItem-leadingVisual-iconColor-rest` variable. */ /* stylelint-disable-next-line selector-no-qualifying-type */ -body[data-dark-theme='dark_high_contrast'] .PRIVATE_TreeViewDirectoryIcon { +body[data-dark-theme='dark_high_contrast'] .TreeViewDirectoryIcon { /* stylelint-disable-next-line primer/colors */ color: var(--color-tree-view-item-directory-fill, #f0f3f6); } diff --git a/packages/react/src/TreeView/TreeView.tsx b/packages/react/src/TreeView/TreeView.tsx index ec965653c142..7cec5d002c3e 100644 --- a/packages/react/src/TreeView/TreeView.tsx +++ b/packages/react/src/TreeView/TreeView.tsx @@ -501,7 +501,7 @@ const Item = React.forwardRef( > {/* @ts-ignore Box doesn't have type support for `ref` used in combination with `as` */}
  • } tabIndex={0} id={itemId} @@ -543,7 +543,7 @@ const Item = React.forwardRef( >
    ( onSelect && 'PRIVATE_TreeView-item-toggle--hover', level === 1 && 'PRIVATE_TreeView-item-toggle--end', { - [classes.PRIVATE_TreeViewItemToggle]: cssModulesEnabled, - [classes.PRIVATE_TreeViewItemToggleHover]: cssModulesEnabled, - [classes.PRIVATE_TreeViewItemToggleEnd]: cssModulesEnabled, + [classes.TreeViewItemToggle]: cssModulesEnabled, + [classes.TreeViewItemToggleHover]: cssModulesEnabled, + [classes.TreeViewItemToggleEnd]: cssModulesEnabled, }, )} onClick={event => { @@ -589,13 +589,13 @@ const Item = React.forwardRef(
    {slots.leadingVisual} {childrenWithoutSubTree} @@ -619,7 +619,7 @@ const LevelIndicatorLines: React.FC<{level: number}> = ({level}) => {
    ))} @@ -818,7 +818,7 @@ const SkeletonItem = () => { className={clsx( { [classes.TreeViewSkeletonItemContainerStyles]: cssModulesEnabled, - [classes.PRIVATE_TreeViewItemSkeleton]: cssModulesEnabled, + [classes.TreeViewItemSkeleton]: cssModulesEnabled, }, 'PRIVATE_TreeView-item-skeleton', )} @@ -843,7 +843,7 @@ const LoadingItem = React.forwardRef(({count}, re {Array.from({length: count}).map((_, i) => { return })} -
    +
    Loading {count} items
    @@ -903,14 +903,14 @@ const LeadingVisual: React.FC = props => { return ( <>
    {props.label}
    {children} @@ -928,14 +928,14 @@ const TrailingVisual: React.FC = props => { return ( <>
    {props.label}
    {children} @@ -956,14 +956,14 @@ const LeadingAction: React.FC = props => { return ( <>
    {props.label}
    @@ -982,9 +982,7 @@ const DirectoryIcon = () => { const {isExpanded} = React.useContext(ItemContext) const Icon = isExpanded ? FileDirectoryOpenFillIcon : FileDirectoryFillIcon return ( -
    +
    ) From fbe385d195e0a221c63b860731820a7ef4047424 Mon Sep 17 00:00:00 2001 From: Kate Travers <8152930+ktravers@users.noreply.github.com> Date: Thu, 14 Nov 2024 04:03:53 +0000 Subject: [PATCH 16/17] Remove unnecessary workaround for dark high contrast mode Variable problem referenced in https://github.com/primer/react/pull/5267/commits/e97cf727641632e763b5e01966786316095040d2 was resolved by https://github.com/primer/react/pull/5277. --- .../react/src/TreeView/TreeView.module.css | 11 ----------- .../react/src/legacy-theme/ts/color-schemes.ts | 18 +++++++++--------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/packages/react/src/TreeView/TreeView.module.css b/packages/react/src/TreeView/TreeView.module.css index bc212bd58202..70be89a0310f 100644 --- a/packages/react/src/TreeView/TreeView.module.css +++ b/packages/react/src/TreeView/TreeView.module.css @@ -224,17 +224,6 @@ } } -/* - * Using "legacy" variable and hex code fallback as a workaround for dark high - * contrast mode, which currently does not support the expected color for - * `--treeViewItem-leadingVisual-iconColor-rest` variable. - */ -/* stylelint-disable-next-line selector-no-qualifying-type */ -body[data-dark-theme='dark_high_contrast'] .TreeViewDirectoryIcon { - /* stylelint-disable-next-line primer/colors */ - color: var(--color-tree-view-item-directory-fill, #f0f3f6); -} - .TreeViewSkeletonItemContainerStyle { display: flex; align-items: center; diff --git a/packages/react/src/legacy-theme/ts/color-schemes.ts b/packages/react/src/legacy-theme/ts/color-schemes.ts index 61b885caa3df..3327c9e84442 100644 --- a/packages/react/src/legacy-theme/ts/color-schemes.ts +++ b/packages/react/src/legacy-theme/ts/color-schemes.ts @@ -385,7 +385,7 @@ const colors = { "hoverBg": "var(--control-transparent-bgColor-hover, var(--color-tree-view-item-chevron-hover-bg, rgba(208,215,222,0.32)))" }, "directory": { - "fill": "var(--treeViewItem-leadingVisual-bgColor-rest, var(--color-tree-view-item-chevron-directory-fill, #54aeff))" + "fill": "var(--treeViewItem-leadingVisual-iconColor-rest, var(--color-tree-view-item-chevron-directory-fill, #54aeff))" } }, "fg": { @@ -909,7 +909,7 @@ const colors = { "hoverBg": "var(--control-transparent-bgColor-hover, var(--color-tree-view-item-chevron-hover-bg, #ced5dc))" }, "directory": { - "fill": "var(--treeViewItem-leadingVisual-bgColor-rest, var(--color-tree-view-item-chevron-directory-fill, #368cf9))" + "fill": "var(--treeViewItem-leadingVisual-iconColor-rest, var(--color-tree-view-item-chevron-directory-fill, #368cf9))" } }, "fg": { @@ -1433,7 +1433,7 @@ const colors = { "hoverBg": "var(--control-transparent-bgColor-hover, var(--color-tree-view-item-chevron-hover-bg, rgba(208,215,222,0.32)))" }, "directory": { - "fill": "var(--treeViewItem-leadingVisual-bgColor-rest, var(--color-tree-view-item-chevron-directory-fill, #54aeff))" + "fill": "var(--treeViewItem-leadingVisual-iconColor-rest, var(--color-tree-view-item-chevron-directory-fill, #54aeff))" } }, "fg": { @@ -1957,7 +1957,7 @@ const colors = { "hoverBg": "var(--control-transparent-bgColor-hover, var(--color-tree-view-item-chevron-hover-bg, rgba(208,215,222,0.32)))" }, "directory": { - "fill": "var(--treeViewItem-leadingVisual-bgColor-rest, var(--color-tree-view-item-chevron-directory-fill, #54aeff))" + "fill": "var(--treeViewItem-leadingVisual-iconColor-rest, var(--color-tree-view-item-chevron-directory-fill, #54aeff))" } }, "fg": { @@ -2480,7 +2480,7 @@ const colors = { "hoverBg": "var(--control-transparent-bgColor-hover, var(--color-tree-view-item-chevron-hover-bg, rgba(177,186,196,0.12)))" }, "directory": { - "fill": "var(--treeViewItem-leadingVisual-bgColor-rest, var(--color-tree-view-item-directory-fill, #848d97))" + "fill": "var(--treeViewItem-leadingVisual-iconColor-rest, var(--color-tree-view-item-directory-fill, #848d97))" } }, "fg": { @@ -3006,7 +3006,7 @@ const colors = { "hoverBg": "var(--control-transparent-bgColor-hover, var(--color-tree-view-item-chevron-hover-bg, rgba(144,157,171,0.12)))" }, "directory": { - "fill": "var(--treeViewItem-leadingVisual-bgColor-rest, var(--color-tree-view-item-directory-fill, #768390))" + "fill": "var(--treeViewItem-leadingVisual-iconColor-rest, var(--color-tree-view-item-directory-fill, #768390))" } }, "fg": { @@ -3532,7 +3532,7 @@ const colors = { "hoverBg": "var(--control-transparent-bgColor-hover, var(--color-tree-view-item-chevron-hover-bg, #525964))" }, "directory": { - "fill": "var(--treeViewItem-leadingVisual-bgColor-rest, var(--color-tree-view-item-directory-fill, #f0f3f6))" + "fill": "var(--treeViewItem-leadingVisual-iconColor-rest, var(--color-tree-view-item-directory-fill, #f0f3f6))" } }, "fg": { @@ -4058,7 +4058,7 @@ const colors = { "hoverBg": "var(--control-transparent-bgColor-hover, var(--color-tree-view-item-chevron-hover-bg, rgba(177,186,196,0.12)))" }, "directory": { - "fill": "var(--treeViewItem-leadingVisual-bgColor-rest, var(--color-tree-view-item-directory-fill, #8b949e))" + "fill": "var(--treeViewItem-leadingVisual-iconColor-rest, var(--color-tree-view-item-directory-fill, #8b949e))" } }, "fg": { @@ -4584,7 +4584,7 @@ const colors = { "hoverBg": "var(--control-transparent-bgColor-hover, var(--color-tree-view-item-chevron-hover-bg, rgba(177,186,196,0.12)))" }, "directory": { - "fill": "var(--treeViewItem-leadingVisual-bgColor-rest, var(--color-tree-view-item-directory-fill, #8b949e))" + "fill": "var(--treeViewItem-leadingVisual-iconColor-rest, var(--color-tree-view-item-directory-fill, #8b949e))" } }, "fg": { From bdd9ffd435ce7637f5ebd28f184997a9b2181b74 Mon Sep 17 00:00:00 2001 From: langermank Date: Thu, 14 Nov 2024 15:05:50 +0000 Subject: [PATCH 17/17] test(vrt): update snapshots --- ...eView-Default-dark-high-contrast-linux.png | Bin 11529 -> 11538 bytes ...y-Directories-dark-high-contrast-linux.png | Bin 6007 -> 6023 bytes ...Files-Changed-dark-high-contrast-linux.png | Bin 21515 -> 21541 bytes ...reeView-Files-dark-high-contrast-linux.png | Bin 19318 -> 19316 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/.playwright/snapshots/components/TreeView.test.ts-snapshots/TreeView-Default-dark-high-contrast-linux.png b/.playwright/snapshots/components/TreeView.test.ts-snapshots/TreeView-Default-dark-high-contrast-linux.png index 998d0128eb1a11a11de231e5d24d102a58dc439c..41a3d33be6adc737591f11daa28f9d738804f8b1 100644 GIT binary patch literal 11538 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 YLs74}oRi=m8<0~cTz;=P=6~bA00PWyz5oCK literal 11529 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 ab%ex-7&HI60DiLpojK+BYuO3^8~+Xc0BJ`6 diff --git a/.playwright/snapshots/components/TreeView.test.ts-snapshots/TreeView-Empty-Directories-dark-high-contrast-linux.png b/.playwright/snapshots/components/TreeView.test.ts-snapshots/TreeView-Empty-Directories-dark-high-contrast-linux.png index a7ddc08bf617e90cc8e2786174c5daf23c355ae7..bd1437b8b471ae124e966b044c1f27d7f9953460 100644 GIT binary patch delta 2265 zcmcJR`B&3d8pgj&N6}HCwhC61v_l0c1&YXCh^`MX!36hYI1cWRQAd}87bLJ12d+rbS+;h*p&w1bH^PH=+ z%C^311OD*yxgY%T&m=QxcLU{w?p4amg693>_i|62sJU{;`iUuO@Lxv@e=+&S5ayLP zzw6+QJ+Y|IxV>Lf^SwBiqAu3q&koA-&+Y&FO?(#qN$h>m+@0JnkN)vm8vNIpuw9RK z8i;q!?$P87qP%U5wCSdFuW z;X5!eKs==n0L#nHmeQDkltc@dz5VFKm{&>?Ygv!92LP_2Pb{}E+obI_QQbv0?-u3D zV`&RLSXzC=YgNJpgEr0dlH zTLV}~HF8UiW$!$(NoiKSl9WdL+y4N6&nD6v-{ozDB`1~-At@^wQK3cDS2yLMrfBmH=@9GC!XJRM>}e2 zYS>Us6)8=QLZKuaYMk#O+-x$t#635+#BsaP51z46m?mvwp3J%JFw2M@C>Dvl)9xS9 zUVh%`4(PJF8CO|V<#XiJa@$yySlV3k5Q{Dqkkn&YBVZH0qyJCgCX|eDoM5I3R)sZZYd{ebsza0W?AJ z#KeH{ao$b6h2VOK$7?Vylg$ZyD>|t92?T)Gg%22?TQTs$dd?IjS~|y7xcmCUU`pXo zRL70qpsgY(^Qy`h!`x=|nvJ1fM)wYv>Oztt)cqL3noP;ljJV*v0YG@=#G7rQ4gb~w zC~`APe_3@v>F%5Ng{x>Or9deI&jbXFb?8Dy%h|IRirO1`i?zb*Kv46E6(b^@O>$)$ zxh%fCz*Nqr#a-L_0{{m9={bpoULCaYlQETwUfM$&wmm(0cwt*HgOl>Hsq4aqU*Bp% z2@<)jF=x6jvcj>8(--oXWo2AQ*wkRXD4&Z7X-(?Y zd!n`8wLoH%r7i%REW&{In3q7JfwEiAZHGlKXBDqq<}!^iq-hLq+gTV)HPfpD1+=G( zl#d0uuIm@J!Z zJDFpIX;!dYOljo$9U^a>DxI29Z!#Zx4*e`%U(aUxdvxC}W75ZE29Z035ML;5}tUm!V zhaY~b^fTq1T6>?ZW%)x%E;Fp_JXh9ZeY~ODIBjc=S9c{gHWj~UQUJBV^^57rVg*qa z&KVr6zxuwUWsT&#FqhTD*b!ijx8J@fs0pJhaxCgZ!(eHDk*;x=NCf~Zw;xgj8T0Z9 zEj#4zE>EUa!6s%BLd*rzdIa@O3W2b#mN9vXk4!jzwf?Mbd?dloZ=|o#f?I&&qG*<6 z@O_CpO4riT(gIeyIa7S~PJR4NbK?ei`KnUw}GX%8VEQVr_o^G}S z1@TZca$|)Lp*A+gPdwIw^Htw%^d;Cme`3j5}wn2GOr2RN4zSS;4}kgoA0GlYf)h4Hy?c%m><2eof! z={|;_dM}fXlO5BAk=e(CEBviC6wuQS4p1jtxW`Tq0Mw&Ae^+16%72ooX`{`4-;kHm z)IIoBH_esH868dP3VOjhmXNBokZvxf~YswYAcI3lj1QG zwgyi{4#lm3Yg-gdyL|j50@JiD3@E+WvdIxM!3}0LI$e-A;-eN-n8f$%0CPT`0RhR` zTPK$xc5$o++{TQagr~E&c-30|I2?`wcm)MzE*_BNg*kpUN|vWpYHKb5uX9ji)6uS9S+rGRR~@J*EakN*3K)?g45AMyMKp+j5d^}M#UK!dVhE7o(%J_V z1f&QkL!x4s0t5}C5Q0(+5FnL#2!x>!NJs)m5{4xA-ToDCt@GnqXMewIfA&79<|?x% zND%3I^@>+Qk#q`tGNd4L*W}%%G5be$m9Eu{g+G4PRX6g&)zakUk0oDF3-tC}Jht~# zdA)0-arQxD%O5h4XSAmt9rHSLg?{g#<%r=g<<~E|;t#r0_O9tT{}3$6ynE_bG5P1Eizp|E!G?fZCnrj9eonld4QUk-i>3UyE~HFu=;7a=w64-pZO zk#deMyh7H^lqL>&z|?Xo9L;cKd5KB$3dgftFS|e*SsN}Hsm{pAFf}#hJ3`z5ns{np zV1VwH|LU~t-44|`{m4=0*#7a*J{q*{;3O#jCui2K<@>B7MJn1uj1gn7AC?|>+0%?2-@Gl6==(tN)oruIvs6Q&uMoce~G6d zskT`W2tP)YF6e7^0ee9V_3snJ?%;=Cjyi64RZXcI$R3Aaw;YH{zuLfAcjgYCe}XLN z$z}B0uqlO>Zh2->;?hYRfupGgQA;oQD~qUIz>AXHlQNgb#~l*7mMsjLKovFyd#JPP zo1^v?qV7v%-5QvrN!4Ey6Xbj|4bLh99=zI}_RzdJ0ldx(V4EGcT<=+%pQaEsGQ-0F zVC(f=O|#+o)!%kx#Yx=PcYBb0-4;cIs}5y*kVPX^h4QJqeCD&5jvE$+1;g9FOjz;q z%^ibpYWl3vP09iWHZk~$=DW~pA6Dt9!7qTz-0|I%KP$bn4A{1jM*!fbn{Tq7M~&6K z)TCoZ^CO^-WmX;c2+O!f?GDzNY`0Q;zMTsFFyswRV{xtw7y$-jW z(*c0f=0dG*b{hsXIil)FK}3W-6AlfHB^BDKp2H^N|7sSy>%R>dE}XRAT*yI_LZ=Fp z(d!>*S{V5B9*1La_-=I0QPe7CIfD_=GT9g{ygyhPFP~-`^(%T=aT2~gLy^$yd^GPG zJ<|r(^}5|T*VfPwRp_FeWU30I+oqKPl*#Is;D5BMvmJy5KbXZhk@n^3w1R?yeU8w5 zQGYQ37Y~E>FB2z$5Scj9~&!<82Z*SqSTMH@ri~VJ1?J7WLOv$QD)1tzt&%@ z_s<(_juX{0@^i1zy?I!DMc+5h9+A_niCr^Sm}aErttmWwdwLsuh!v1J{0SgBd@`o5 z(puuKKaeC~g=VE17Ocs(Kc?gd*ew5Pj_>8|0g{WoQkrNMI~7clBI0NUyYBdBQXK-@ z&N@NAb${_O%uCVMXgx@j;2N4 zM$Mv0pmC$N*!QE291wc;sicN8yErkeBOpMa!+ElAmVrb3R_-p~^7zw}vS``^URA1r zeYLjN&3p%q`f(zWOPPH}R*s8Y9NR+XKV~5Mk~X``LZU%(W7Jd|v2(LNV${s9DNI>Z zhL8}Kl%tUH4Hw#3GoDTq6-U&tYdp))*yAxIAFd9N4Eo>l&-4Fb`T-e_SDY!+r4Xmy zbrZDj&Jkt5O|zkpz5+|QEW_A4j^?ciL)n@}76q1MV3<*MvWa?$QiW{_^N?JLi~B4d zj+QoJ>a4c0RVD3v38bfciKuq9p!8^tE7 z5ZF6H(ab|%#JdN}Z{=+?--gIUROy#M^7?5fL6#mWY4yoqsC^8SF$z^3H?#jk;m~i0dvu|Yi`Es&+WL|Q4@6)r_-Etmj|owHfBxY));P?D?$$b zJqN3ms-|~11elTwOXVe*=W?&*gCeXoZepWlJkEAKco)!~dB#bA&`bD0R-xGn%(pxw zzhCcxxVxH$n`(-kuZ=U;yR=aRgXtfmO&rybK3HKE&jqMK@w~e|O0_KXPwM7U2%_Q~ zIaM{_mLBk2B@&6+v>)}EY-N%pD*)zspS9q@FaoTti5;$u>(}=9IQi%82HK6Ud3)n; zIHLtaLrqQ+;>OZ2HJE;@f=;I^b^}5~)zo~Jo$_^#j(p`Y{Nou{jF}HLkjrimt9q_J#owdt*O!7?&Km*1iYr_Y^IRxUA@-K~G~eq?gPO!* zWtHGrpL{sYsn;y69SUbFJ&5*RyWb5iFaU6MMqjP@ci^x81KTs}zW@LL diff --git a/.playwright/snapshots/components/TreeView.test.ts-snapshots/TreeView-Files-Changed-dark-high-contrast-linux.png b/.playwright/snapshots/components/TreeView.test.ts-snapshots/TreeView-Files-Changed-dark-high-contrast-linux.png index de83cf8f11b4e91d7e605223a73b7a7151bdd0b4..11fb1f3f63c9ea319ce46a386d5076e0c53b1ad6 100644 GIT binary patch literal 21541 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�JkD;Hd-(#gNiCa@o}cD4*9Z2C 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 bctZ19M65~u*6H4r+#w+<`zBxH!>9iT<`cVt literal 21515 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 Q(qD+Uh|Jr3=!dWWA5tdis{jB1 diff --git a/.playwright/snapshots/components/TreeView.test.ts-snapshots/TreeView-Files-dark-high-contrast-linux.png b/.playwright/snapshots/components/TreeView.test.ts-snapshots/TreeView-Files-dark-high-contrast-linux.png index 78d0c95b3c609185a67ce1724fb727dcdd476a27..24a37f28b2428a0221aaa87f811ee6b0f4319d00 100644 GIT binary patch literal 19316 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 literal 19318 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