fix(ux): fixed off-by-some wrapping caused by fixed-width characters (#17816)

This commit is contained in:
Dev Randalpura
2026-01-28 13:52:37 -08:00
committed by GitHub
parent bee1267e2a
commit b2265cfde4
3 changed files with 59 additions and 4 deletions

View File

@@ -31,4 +31,34 @@ describe('TableRenderer', () => {
expect(output).toContain('Row 3, Col 3');
expect(output).toMatchSnapshot();
});
it('renders a table with long headers and 4 columns correctly', () => {
const headers = [
'Very Long Column Header One',
'Very Long Column Header Two',
'Very Long Column Header Three',
'Very Long Column Header Four',
];
const rows = [
['Data 1.1', 'Data 1.2', 'Data 1.3', 'Data 1.4'],
['Data 2.1', 'Data 2.2', 'Data 2.3', 'Data 2.4'],
['Data 3.1', 'Data 3.2', 'Data 3.3', 'Data 3.4'],
];
const terminalWidth = 80;
const { lastFrame } = renderWithProviders(
<TableRenderer
headers={headers}
rows={rows}
terminalWidth={terminalWidth}
/>,
);
const output = lastFrame();
// Since terminalWidth is 80 and headers are long, they might be truncated.
// We just check for some of the content.
expect(output).toContain('Data 1.1');
expect(output).toContain('Data 3.4');
expect(output).toMatchSnapshot();
});
});

View File

@@ -34,11 +34,24 @@ export const TableRenderer: React.FC<TableRendererProps> = ({
});
// Ensure table fits within terminal width
const totalWidth = columnWidths.reduce((sum, width) => sum + width + 1, 1);
// We calculate scale based on content width vs available width (terminal - borders)
// First, extract content widths by removing the 2-char padding.
const contentWidths = columnWidths.map((width) => Math.max(0, width - 2));
const totalContentWidth = contentWidths.reduce(
(sum, width) => sum + width,
0,
);
// Fixed overhead includes padding (2 per column) and separators (1 per column + 1 final).
const fixedOverhead = headers.length * 2 + (headers.length + 1);
// Subtract 1 from available width to avoid edge-case wrapping on some terminals
const availableWidth = Math.max(0, terminalWidth - fixedOverhead - 1);
const scaleFactor =
totalWidth > terminalWidth ? terminalWidth / totalWidth : 1;
const adjustedWidths = columnWidths.map((width) =>
Math.floor(width * scaleFactor),
totalContentWidth > availableWidth ? availableWidth / totalContentWidth : 1;
const adjustedWidths = contentWidths.map(
(width) => Math.floor(width * scaleFactor) + 2,
);
// Helper function to render a cell with proper width

View File

@@ -54,6 +54,18 @@ exports[`TableRenderer > renders a simple table correctly 1`] = `
"
`;
exports[`TableRenderer > renders a table with long headers and 4 columns correctly 1`] = `
"
┌──────────────────┬──────────────────┬───────────────────┬──────────────────┐
│ Very Long Col... │ Very Long Col... │ Very Long Colu... │ Very Long Col... │
├──────────────────┼──────────────────┼───────────────────┼──────────────────┤
│ Data 1.1 │ Data 1.2 │ Data 1.3 │ Data 1.4 │
│ Data 2.1 │ Data 2.2 │ Data 2.3 │ Data 2.4 │
│ Data 3.1 │ Data 3.2 │ Data 3.3 │ Data 3.4 │
└──────────────────┴──────────────────┴───────────────────┴──────────────────┘
"
`;
exports[`TableRenderer > truncates content when terminal width is small 1`] = `
"
┌────────┬─────────┬─────────┐