1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-08-27 13:49:10 +02:00

chore: make project list table take less horizontal space (#10480)

https://linear.app/unleash/issue/2-3761/address-ux-feedback-make-table-take-less-horizontal-space-to-prevent

Addresses UX feedback by making the project list table take less
horizontal space. This should prevent us from having to scroll
horizontally in most cases.

<img width="1103" height="647" alt="image"
src="https://github.com/user-attachments/assets/e5cc22a2-5eda-4cb5-a226-c54993c019ce"
/>
This commit is contained in:
Nuno Góis 2025-08-08 08:03:02 +01:00 committed by GitHub
parent 60a2fa675b
commit 937cba4c1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 82 additions and 37 deletions

View File

@ -10,15 +10,21 @@ import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
type ProjectLastSeenProps = {
date?: Date | number | string | null;
hideLabel?: boolean;
};
const StyledContainer = styled(Box)(({ theme }) => ({
const StyledContainer = styled(Box, {
shouldForwardProp: (prop) => prop !== 'secondary',
})<{ secondary?: boolean }>(({ theme, secondary }) => ({
...flexRow,
justifyContent: 'flex-start',
textWrap: 'nowrap',
width: '50%',
gap: theme.spacing(1),
cursor: 'default',
color: secondary
? theme.palette.text.secondary
: theme.palette.text.primary,
}));
const StyledIcon = styled(StyledIconWrapper)<{ background: string }>(
@ -28,13 +34,18 @@ const StyledIcon = styled(StyledIconWrapper)<{ background: string }>(
}),
);
const Title = () => (
const Title = ({ date }: Pick<ProjectLastSeenProps, 'date'>) => (
<>
<Typography
component='span'
sx={(theme) => ({ fontSize: theme.fontSizes.smallBody })}
>
Last usage reported
Last usage reported:{' '}
{date ? (
<TimeAgo date={date} refresh={false} />
) : (
<span>No activity</span>
)}
</Typography>
<Typography
sx={(theme) => ({
@ -48,32 +59,29 @@ const Title = () => (
</>
);
export const ProjectLastSeen: FC<ProjectLastSeenProps> = ({ date }) => {
export const ProjectLastSeen: FC<ProjectLastSeenProps> = ({
date,
hideLabel,
}) => {
const getColor = useLastSeenColors();
const { text, background } = getColor(date);
if (!date) {
return (
<HtmlTooltip title={<Title />} arrow>
<StyledContainer
sx={(theme) => ({ color: theme.palette.text.secondary })}
>
<StyledIcon background={background}>
<UsageLine stroke={text} />
</StyledIcon>{' '}
<div>No activity</div>
</StyledContainer>
</HtmlTooltip>
);
}
return (
<HtmlTooltip title={<Title />} arrow>
<StyledContainer>
<HtmlTooltip title={<Title date={date} />} arrow>
<StyledContainer secondary={!date}>
<StyledIcon background={background}>
<UsageRate stroke={text} />
{date ? (
<UsageRate stroke={text} />
) : (
<UsageLine stroke={text} />
)}
</StyledIcon>{' '}
<TimeAgo date={date} refresh={false} />
{!hideLabel &&
(date ? (
<TimeAgo date={date} refresh={false} />
) : (
<div>No activity</div>
))}
</StyledContainer>
</HtmlTooltip>
);

View File

@ -0,0 +1,25 @@
import { styled } from '@mui/material';
import { ProjectLastSeen } from 'component/project/ProjectCard/ProjectLastSeen/ProjectLastSeen';
const StyledContainer = styled('div', {
shouldForwardProp: (prop) => prop !== 'hideLabel',
})<{ hideLabel?: boolean }>(({ theme, hideLabel }) => ({
display: 'flex',
alignItems: 'center',
justifyContent: hideLabel ? 'center' : 'start',
padding: theme.spacing(1, 2),
}));
type ProjectListTableLastSeenCellProps = {
value?: Date | number | string | null;
hideLabel?: boolean;
};
export const ProjectListTableLastSeenCell = ({
value,
hideLabel,
}: ProjectListTableLastSeenCellProps) => (
<StyledContainer hideLabel={hideLabel}>
<ProjectLastSeen date={value} hideLabel={hideLabel} />
</StyledContainer>
);

View File

@ -4,14 +4,16 @@ import { HighlightCell } from 'component/common/Table/cells/HighlightCell/Highli
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
import { TimeAgoCell } from 'component/common/Table/cells/TimeAgoCell/TimeAgoCell';
import { ProjectOwners } from 'component/project/ProjectCard/ProjectCardFooter/ProjectOwners/ProjectOwners';
import { ProjectLastSeen } from 'component/project/ProjectCard/ProjectLastSeen/ProjectLastSeen';
import { useFavoriteProjectsApi } from 'hooks/api/actions/useFavoriteProjectsApi/useFavoriteProjectsApi';
import useProjects from 'hooks/api/getters/useProjects/useProjects';
import type { ProjectSchema, ProjectSchemaOwners } from 'openapi';
import { useCallback, useMemo } from 'react';
import { useFlexLayout, useTable } from 'react-table';
import { formatDateYMDHMS } from 'utils/formatDate';
import { ProjectsListTableProjectName } from './ProjectsListTableProjectName.tsx';
import { ProjectsListTableNameCell } from './ProjectsListTableNameCell.tsx';
import { useMediaQuery } from '@mui/material';
import theme from 'themes/theme.ts';
import { ProjectListTableLastSeenCell } from './ProjectListTableLastSeenCell.tsx';
type ProjectsListTableProps = {
projects: ProjectSchema[];
@ -20,6 +22,7 @@ type ProjectsListTableProps = {
export const ProjectsListTable = ({ projects }: ProjectsListTableProps) => {
const { refetch } = useProjects();
const { favorite, unfavorite } = useFavoriteProjectsApi();
const isMediumScreen = useMediaQuery(theme.breakpoints.down('lg'));
const onFavorite = useCallback(
async (project: ProjectSchema) => {
@ -51,7 +54,7 @@ export const ProjectsListTable = ({ projects }: ProjectsListTableProps) => {
accessor: 'name',
minWidth: 200,
searchable: true,
Cell: ProjectsListTableProjectName,
Cell: ProjectsListTableNameCell,
},
{
Header: 'Last updated',
@ -64,15 +67,17 @@ export const ProjectsListTable = ({ projects }: ProjectsListTableProps) => {
dateFormat={formatDateYMDHMS}
/>
),
width: 150,
},
{
Header: 'Number of flags',
Header: 'Flags',
accessor: 'featureCount',
Cell: ({ value }: { value: number }) => (
<TextCell>
{value} flag{value === 1 ? '' : 's'}
</TextCell>
),
width: 90,
},
{
Header: 'Health',
@ -80,24 +85,30 @@ export const ProjectsListTable = ({ projects }: ProjectsListTableProps) => {
Cell: ({ value }: { value: number }) => (
<TextCell>{value}%</TextCell>
),
width: 100,
width: 70,
},
{
Header: 'Last seen',
accessor: 'lastReportedFlagUsage',
Cell: ({ value }: { value: Date }) => (
<ProjectLastSeen date={value} />
<ProjectListTableLastSeenCell
value={value}
hideLabel={isMediumScreen}
/>
),
width: isMediumScreen ? 100 : 140,
},
{
Header: 'Owner',
accessor: 'owners',
Cell: ({ value }: { value: ProjectSchemaOwners }) => (
<ProjectOwners
owners={value?.filter(
(owner) => owner.ownerType !== 'system',
)}
/>
<TextCell>
<ProjectOwners
owners={value?.filter(
(owner) => owner.ownerType !== 'system',
)}
/>
</TextCell>
),
},
{
@ -106,6 +117,7 @@ export const ProjectsListTable = ({ projects }: ProjectsListTableProps) => {
Cell: ({ value }: { value: number }) => (
<TextCell>{value} members</TextCell>
),
width: 120,
},
],
[onFavorite],

View File

@ -20,15 +20,15 @@ const StyledFeatureLink = styled(Link)({
},
});
type ProjectsListTableProjectNameProps = {
type ProjectsListTableNameCellProps = {
row: {
original: ProjectSchema;
};
};
export const ProjectsListTableProjectName = ({
export const ProjectsListTableNameCell = ({
row,
}: ProjectsListTableProjectNameProps) => {
}: ProjectsListTableNameCellProps) => {
const { searchQuery } = useSearchHighlightContext();
return (