From 527d94d0fc2b18c30ee1730aa6e7f83a54098144 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Thu, 23 Oct 2025 10:42:08 +0200 Subject: [PATCH] chore: never wrap other text fields in global change requests table (#10841) Prevents text wraps in the wrapping columns of the table: - Title - environment - status Also prevents the change request badge cells (change request badges in tables, such as the project CR table) from wrapping. Before: image
In extreme cases image
After: image and when it's wide enough to not horizontally scroll: image ## Note: bug introduced (but fix is coming) This does introduce a rendering bug in Chrome, however, where the columns will take up all the width that they can without being truncated: image This does not happen in Firefox. However, it can be fixed by specifying a max width for the columns. I'll fix this in the next PR. --- .../ChangeRequestStatusBadge.tsx | 7 ++- .../ChangeRequests/ChangeRequests.tsx | 17 +++--- .../GlobalChangeRequestTitleCell.tsx | 59 +++++++++++-------- .../ChangeRequestStatusCell.tsx | 11 ++-- .../cells/HighlightCell/HighlightCell.tsx | 4 +- 5 files changed, 58 insertions(+), 40 deletions(-) diff --git a/frontend/src/component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge.tsx b/frontend/src/component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge.tsx index bd8afb879d..bed92f2f66 100644 --- a/frontend/src/component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge.tsx +++ b/frontend/src/component/changeRequest/ChangeRequestStatusBadge/ChangeRequestStatusBadge.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import { Badge } from 'component/common/Badge/Badge'; +import { Badge as MuiBadge } from 'component/common/Badge/Badge'; import AccessTime from '@mui/icons-material/AccessTime'; import Check from '@mui/icons-material/Check'; import CircleOutlined from '@mui/icons-material/CircleOutlined'; @@ -12,6 +12,11 @@ import type { ScheduledChangeRequest, UnscheduledChangeRequest, } from '../changeRequest.types'; +import { styled } from '@mui/material'; + +const Badge = styled(MuiBadge)({ + whiteSpace: 'nowrap', +}); export interface IChangeRequestStatusBadgeProps { changeRequest: diff --git a/frontend/src/component/changeRequest/ChangeRequests/ChangeRequests.tsx b/frontend/src/component/changeRequest/ChangeRequests/ChangeRequests.tsx index 62f2a1a414..6c5a884227 100644 --- a/frontend/src/component/changeRequest/ChangeRequests/ChangeRequests.tsx +++ b/frontend/src/component/changeRequest/ChangeRequests/ChangeRequests.tsx @@ -39,6 +39,10 @@ const columnHelper = createColumnHelper(); const StyledPaginatedTable = styled( PaginatedTable, )(() => ({ + th: { + whiteSpace: 'nowrap', + }, + td: { verticalAlign: 'top', }, @@ -98,16 +102,11 @@ const ChangeRequestsInner = () => { const columns = useMemo( () => [ - columnHelper.accessor('title', { + columnHelper.accessor('id', { id: 'Title', header: 'Title', meta: { width: '300px' }, - cell: ({ getValue, row }) => ( - - ), + cell: GlobalChangeRequestTitleCell, }), columnHelper.accessor('features', { id: 'Updated feature flags', @@ -149,7 +148,9 @@ const ChangeRequestsInner = () => { id: 'Environment', header: 'Environment', meta: { width: '100px' }, - cell: ({ getValue }) => , + cell: ({ getValue }) => ( + + ), }), columnHelper.accessor('state', { id: 'Status', diff --git a/frontend/src/component/changeRequest/ChangeRequests/GlobalChangeRequestTitleCell.tsx b/frontend/src/component/changeRequest/ChangeRequests/GlobalChangeRequestTitleCell.tsx index 17f0b1275a..af356ded93 100644 --- a/frontend/src/component/changeRequest/ChangeRequests/GlobalChangeRequestTitleCell.tsx +++ b/frontend/src/component/changeRequest/ChangeRequests/GlobalChangeRequestTitleCell.tsx @@ -2,27 +2,28 @@ import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; import { Link, styled, Typography } from '@mui/material'; import { Link as RouterLink, type LinkProps } from 'react-router-dom'; import { useProjectOverviewNameOrId } from 'hooks/api/getters/useProjectOverview/useProjectOverview'; - -type IGlobalChangeRequestTitleCellProps = { - value?: any; - row: { original: any }; -}; +import { Truncator } from 'component/common/Truncator/Truncator'; +import type { ChangeRequestSearchItemSchema } from 'openapi'; +import type { Row } from '@tanstack/react-table'; const LinkContainer = styled('div')(({ theme }) => ({ color: theme.palette.text.secondary, + display: 'flex', + columnGap: theme.spacing(0.5), })); const BaseLink = styled(({ children, ...props }: LinkProps) => ( {children} -))(({ theme }) => ({ +))({ + whiteSpace: 'nowrap', textDecoration: 'none', color: 'inherit', ':hover': { textDecoration: 'underline', }, -})); +}); const ChangeRequestLink = styled(BaseLink)(({ theme }) => ({ color: theme.palette.primary.main, @@ -34,33 +35,43 @@ const UpdateText = styled(Typography)(({ theme }) => ({ fontSize: theme.typography.body2.fontSize, })); +type GlobalChangeRequestTitleCellProps = { + row: Row; +}; + export const GlobalChangeRequestTitleCell = ({ - value, - row: { original }, -}: IGlobalChangeRequestTitleCellProps) => { - const { - id, - title, - project, - features: featureChanges, - segments: segmentChanges, - } = original; + row: { + original: { + id, + title, + project, + features: featureChanges, + segments: segmentChanges, + }, + }, +}: GlobalChangeRequestTitleCellProps) => { const projectName = useProjectOverviewNameOrId(project); const totalChanges = featureChanges?.length ?? 0 + segmentChanges?.length ?? 0; const projectPath = `/projects/${project}`; const crPath = `${projectPath}/change-requests/${id}`; - if (!value) { - return ; - } - return ( - {projectName} - - {title} + + {projectName} + + + {title ? ( + + + {title} + + + ) : ( + #{id} + )} {`${totalChanges}`} {totalChanges === 1 ? `update` : 'updates'} diff --git a/frontend/src/component/changeRequest/ProjectChangeRequests/ChangeRequestsTabs/ChangeRequestStatusCell.tsx b/frontend/src/component/changeRequest/ProjectChangeRequests/ChangeRequestsTabs/ChangeRequestStatusCell.tsx index 84f7bc2618..b65695bc77 100644 --- a/frontend/src/component/changeRequest/ProjectChangeRequests/ChangeRequestsTabs/ChangeRequestStatusCell.tsx +++ b/frontend/src/component/changeRequest/ProjectChangeRequests/ChangeRequestsTabs/ChangeRequestStatusCell.tsx @@ -16,14 +16,13 @@ export const ChangeRequestStatusCell: FC = ({ value, row: { original }, }) => { - const renderState = () => { - if (!value) return null; - return ; - }; - if (!value) { return ; } - return {renderState()}; + return ( + + + + ); }; diff --git a/frontend/src/component/common/Table/cells/HighlightCell/HighlightCell.tsx b/frontend/src/component/common/Table/cells/HighlightCell/HighlightCell.tsx index 195f64bc0f..f50d517902 100644 --- a/frontend/src/component/common/Table/cells/HighlightCell/HighlightCell.tsx +++ b/frontend/src/component/common/Table/cells/HighlightCell/HighlightCell.tsx @@ -12,6 +12,7 @@ interface IHighlightCellProps { subtitle?: string; afterTitle?: React.ReactNode; subtitleTooltip?: boolean; + maxTitleLines?: number; } const StyledContainer = styled(Box)(({ theme }) => ({ @@ -40,6 +41,7 @@ export const HighlightCell: FC = ({ subtitle, afterTitle, subtitleTooltip, + maxTitleLines, }) => { const { searchQuery } = useSearchHighlightContext(); @@ -68,7 +70,7 @@ export const HighlightCell: FC = ({ return (