Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/52810-cap-truncated-text-list-tooltip
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Fixed the software details modal so that hovering the vulnerabilities list shows the first 10 CVEs and a count of the rest, instead of a tooltip that runs off the screen when software has many CVEs.
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,12 @@ export const AllFit: Story = {
args: { items: ["Mac", "Linux"] },
decorators: [withFrame(360)],
};

/** Hover "+N more" — the tooltip lists 10 items and counts the rest, rather
* than growing past the height of the window. */
export const ManyItems: Story = {
args: {
items: Array.from({ length: 57 }, (_, i) => `CVE-2026-${1000 + i}`),
},
decorators: [withFrame(360)],
};
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,19 @@ describe("TruncatedTextList — truncatedFirstContent edge cases", () => {
expect.objectContaining({ tipContent: longName })
);
});

it("caps the hidden items listed in the tooltip and counts the rest", () => {
const items = Array.from({ length: 57 }, (_, i) => `CVE-2026-${i}`);
render(<TruncatedTextList items={items} />);

// The first item is short enough to skip its own tooltip, so the only
// wrapper here is the "+N more" pill's.
const { tipContent } = mockedTooltipWrapper.mock.calls[0][0];
const { container } = render(<div>{tipContent}</div>);

// 56 items are hidden: 10 listed, the remaining 46 rolled into a count.
expect(container).toHaveTextContent("CVE-2026-10");
expect(container).not.toHaveTextContent("CVE-2026-11");
expect(container).toHaveTextContent("+46 more");
});
});
30 changes: 20 additions & 10 deletions frontend/components/TruncatedTextList/TruncatedTextList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,26 @@ interface ITruncatedTextListProps {
const truncateString = (s: string, max: number) =>
s.length > max ? `${s.slice(0, max).trimEnd()}...` : s;

const renderItemsList = (list: string[]) => (
<>
{list.map((name, i) => (
<React.Fragment key={name}>
{name}
{i < list.length - 1 && <br />}
</React.Fragment>
))}
</>
);
/** A hover tooltip can't scroll, so an uncapped list runs off the screen with
* no way to reach the rest of it. Same cap idea as `VulnerabilitiesCell`. */
const MAX_ITEMS_IN_TOOLTIP = 10;

const renderItemsList = (list: string[]) => {
const shown = list.slice(0, MAX_ITEMS_IN_TOOLTIP);
const remaining = list.length - shown.length;

return (
<>
{shown.map((name, i) => (
<React.Fragment key={name}>
{name}
{(i < shown.length - 1 || remaining > 0) && <br />}
</React.Fragment>
))}
{remaining > 0 && `+${remaining} more`}
</>
);
};

interface IRenderVisibleRowParams {
visibleCount: number;
Expand Down
Loading