Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TreeView: Add truncate prop #5122

Merged
merged 11 commits into from
Nov 6, 2024
5 changes: 5 additions & 0 deletions .changeset/slow-shoes-wait.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': minor
---

TreeView: Adds prop `truncate`, keeps default behavior of truncation but allows for text to wrap when turned off.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions packages/react/src/TreeView/TreeView.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@
"name": "onSelect",
"type": "(event: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>) => void"
},
{
"name": "truncate",
"type": "boolean",
"defaultValue": "true",
"description": "Truncate the item's text content with an ellipsis."
},
{
"name": "ref",
"type": "React.Ref<HTMLElement>"
Expand Down
22 changes: 9 additions & 13 deletions packages/react/src/TreeView/TreeView.features.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const meta: Meta = {

export const Files: StoryFn = () => (
<nav aria-label="Files">
<TreeView aria-label="Files">
<TreeView aria-label="Files" truncate={false}>
<TreeView.Item id="src" defaultExpanded>
<TreeView.LeadingVisual>
<TreeView.DirectoryIcon />
Expand Down Expand Up @@ -112,7 +112,7 @@ export const Files: StoryFn = () => (
export const FilesChanged: StoryFn = () => {
return (
<nav aria-label="Files">
<TreeView aria-label="Files">
<TreeView aria-label="Files" truncate={false}>
<TreeView.Item id="src" defaultExpanded>
<TreeView.LeadingVisual>
<TreeView.DirectoryIcon />
Expand Down Expand Up @@ -785,7 +785,7 @@ export const ContainIntrinsicSize: StoryFn = () => {
export const InitialFocus: StoryFn = () => (
<div>
<Button>Focusable element before TreeView</Button>
<TreeView aria-label="Test tree">
<TreeView aria-label="Test tree" truncate={false}>
<TreeView.Item id="src" defaultExpanded>
<TreeView.LeadingVisual>
<TreeView.DirectoryIcon />
Expand Down Expand Up @@ -890,11 +890,11 @@ export const InitialFocus: StoryFn = () => (
</TreeView.Item>
</TreeView.SubTree>
</TreeView.Item>
<TreeView.Item id="src/ReallyLongFileNameThatShouldBeTruncated.tsx">
<TreeView.Item id="src/ReallyLongFileNameThatShouldNotBeTruncated.tsx">
<TreeView.LeadingVisual>
<FileIcon />
</TreeView.LeadingVisual>
ReallyLongFileNameThatShouldBeTruncated.tsx
ReallyLongFileNameThatShouldNotBeTruncated.tsx
</TreeView.Item>
</TreeView.SubTree>
</TreeView.Item>
Expand Down Expand Up @@ -1046,15 +1046,13 @@ export const LeadingAction: StoryFn = () => {

export const MultilineItems: StoryFn = () => (
<nav aria-label="Files changed">
<TreeView aria-label="Files changed">
<TreeView aria-label="Files changed" truncate={false}>
<TreeView.Item id="src" defaultExpanded>
<TreeView.LeadingVisual>
<TreeView.DirectoryIcon />
</TreeView.LeadingVisual>
<div style={{whiteSpace: 'wrap'}}>
this is a very long directory name that we have intentionally allowed to wrap over multiple lines to
demonstrate alignment
</div>
this is a very long directory name that we have intentionally allowed to wrap over multiple lines to demonstrate
alignment
<TreeView.SubTree>
<TreeView.Item id="src/Avatar.tsx">
<TreeView.LeadingVisual>
Expand All @@ -1071,9 +1069,7 @@ export const MultilineItems: StoryFn = () => (
<TreeView.LeadingVisual>
<TreeView.DirectoryIcon />
</TreeView.LeadingVisual>
<div style={{whiteSpace: 'wrap'}}>
this is a medium directory name that we wrap over 2 lines to demonstrate alignment
</div>
this is a medium directory name that we wrap over 2 lines to demonstrate alignment
<TreeView.TrailingVisual label="Added">
<Octicon icon={DiffAddedIcon} color="success.fg" />
</TreeView.TrailingVisual>
Expand Down
11 changes: 10 additions & 1 deletion packages/react/src/TreeView/TreeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export type TreeViewProps = {
'aria-labelledby'?: React.AriaAttributes['aria-labelledby']
children: React.ReactNode
flat?: boolean
truncate?: boolean
className?: string
}

Expand Down Expand Up @@ -205,14 +206,20 @@ const UlBox = styled.ul<SxProp>`
}

.PRIVATE_TreeView-item-content-text {
/* Truncate text label */
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;
Expand Down Expand Up @@ -282,6 +289,7 @@ const Root: React.FC<TreeViewProps> = ({
'aria-labelledby': ariaLabelledby,
children,
flat,
truncate = true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TylerJDev do you think it might make more sense to make this false by default? Just wondering if this is kind of a breaking change. Have you run an integration test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this, I set it to true to keep the default behavior of the text truncating when not using the prop. When using it with false, it will wrap instead. The new behavior should only be opt-in, so that we can release this under a non breaking change.

Let me know if you think we should change the prop name (e.g. shouldNotTruncate, wrap). Not sure if truncate is confusing or not 😅

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OH sorry I totally read the CSS wrong. Awesome! LGTM

className,
}) => {
const containerRef = React.useRef<HTMLUListElement>(null)
Expand Down Expand Up @@ -338,6 +346,7 @@ const Root: React.FC<TreeViewProps> = ({
aria-label={ariaLabel}
aria-labelledby={ariaLabelledby}
data-omit-spacer={flat}
data-truncate-text={truncate || false}
onMouseDown={onMouseDown}
className={className}
>
Expand Down
Loading