mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-18 13:48:58 +02:00
feat: add truncation and tooltips (#10498)
This PR uses the existing Truncator component to add truncation and tooltips for long names.
This commit is contained in:
parent
05ea405bf6
commit
a99e5bc4b4
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@ npm-debug
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
/dist
|
/dist
|
||||||
.vscode
|
.vscode
|
||||||
|
.claude
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
|
@ -5,6 +5,7 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
|
|||||||
import { TooltipLink } from 'component/common/TooltipLink/TooltipLink';
|
import { TooltipLink } from 'component/common/TooltipLink/TooltipLink';
|
||||||
import { useSearchHighlightContext } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
import { useSearchHighlightContext } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||||
import { Highlighter } from 'component/common/Highlighter/Highlighter';
|
import { Highlighter } from 'component/common/Highlighter/Highlighter';
|
||||||
|
import { Truncator } from 'component/common/Truncator/Truncator';
|
||||||
|
|
||||||
const StyledBox = styled(Box)(({ theme }) => ({
|
const StyledBox = styled(Box)(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -13,10 +14,7 @@ const StyledBox = styled(Box)(({ theme }) => ({
|
|||||||
padding: theme.spacing(1, 0, 1, 2),
|
padding: theme.spacing(1, 0, 1, 2),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledLink = styled(Link)(({ theme }) => ({
|
const StyledLink = styled(Link)(() => ({
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
textDecoration: 'none',
|
textDecoration: 'none',
|
||||||
'&:hover, &:focus': {
|
'&:hover, &:focus': {
|
||||||
textDecoration: 'underline',
|
textDecoration: 'underline',
|
||||||
@ -53,12 +51,13 @@ export const FeaturesCell: VFC<FeaturesCellProps> = ({ value, project }) => {
|
|||||||
show={featureNames?.map((featureName: string) => (
|
show={featureNames?.map((featureName: string) => (
|
||||||
<StyledLink
|
<StyledLink
|
||||||
key={featureName}
|
key={featureName}
|
||||||
title={featureName}
|
|
||||||
to={`/projects/${project}/features/${featureName}`}
|
to={`/projects/${project}/features/${featureName}`}
|
||||||
>
|
>
|
||||||
<Highlighter search={searchQuery}>
|
<Truncator lines={1} title={featureName} arrow>
|
||||||
{featureName}
|
<Highlighter search={searchQuery}>
|
||||||
</Highlighter>
|
{featureName}
|
||||||
|
</Highlighter>
|
||||||
|
</Truncator>
|
||||||
</StyledLink>
|
</StyledLink>
|
||||||
))}
|
))}
|
||||||
elseShow={
|
elseShow={
|
||||||
@ -69,12 +68,17 @@ export const FeaturesCell: VFC<FeaturesCellProps> = ({ value, project }) => {
|
|||||||
{featureNames?.map((featureName: string) => (
|
{featureNames?.map((featureName: string) => (
|
||||||
<StyledTooltipLink
|
<StyledTooltipLink
|
||||||
key={featureName}
|
key={featureName}
|
||||||
title={featureName}
|
|
||||||
to={`/projects/${project}/features/${featureName}`}
|
to={`/projects/${project}/features/${featureName}`}
|
||||||
>
|
>
|
||||||
<Highlighter search={searchQuery}>
|
<Truncator
|
||||||
{featureName}
|
lines={1}
|
||||||
</Highlighter>
|
title={featureName}
|
||||||
|
arrow
|
||||||
|
>
|
||||||
|
<Highlighter search={searchQuery}>
|
||||||
|
{featureName}
|
||||||
|
</Highlighter>
|
||||||
|
</Truncator>
|
||||||
</StyledTooltipLink>
|
</StyledTooltipLink>
|
||||||
))}
|
))}
|
||||||
</StyledTooltipContainer>
|
</StyledTooltipContainer>
|
||||||
|
@ -5,7 +5,7 @@ import useFeatureTypes from 'hooks/api/getters/useFeatureTypes/useFeatureTypes';
|
|||||||
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
|
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
|
||||||
import { useSearchHighlightContext } from '../../SearchHighlightContext/SearchHighlightContext.tsx';
|
import { useSearchHighlightContext } from '../../SearchHighlightContext/SearchHighlightContext.tsx';
|
||||||
import { Highlighter } from '../../../Highlighter/Highlighter.tsx';
|
import { Highlighter } from '../../../Highlighter/Highlighter.tsx';
|
||||||
import { StyledDescription, StyledTitle } from '../LinkCell/LinkCell.styles';
|
import { StyledDescription } from '../LinkCell/LinkCell.styles';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Badge } from '../../../Badge/Badge.tsx';
|
import { Badge } from '../../../Badge/Badge.tsx';
|
||||||
import { HtmlTooltip } from '../../../HtmlTooltip/HtmlTooltip.tsx';
|
import { HtmlTooltip } from '../../../HtmlTooltip/HtmlTooltip.tsx';
|
||||||
@ -15,6 +15,7 @@ import { useLocationSettings } from 'hooks/useLocationSettings';
|
|||||||
import { getLocalizedDateString } from '../../../util.ts';
|
import { getLocalizedDateString } from '../../../util.ts';
|
||||||
import { Tag } from 'component/common/Tag/Tag';
|
import { Tag } from 'component/common/Tag/Tag';
|
||||||
import { formatTag } from 'utils/format-tag';
|
import { formatTag } from 'utils/format-tag';
|
||||||
|
import { Truncator } from 'component/common/Truncator/Truncator';
|
||||||
|
|
||||||
interface IFeatureNameCellProps {
|
interface IFeatureNameCellProps {
|
||||||
row: {
|
row: {
|
||||||
@ -135,15 +136,20 @@ const FeatureName: FC<{
|
|||||||
return (
|
return (
|
||||||
<Box sx={(theme) => ({ fontWeight: theme.typography.fontWeightBold })}>
|
<Box sx={(theme) => ({ fontWeight: theme.typography.fontWeightBold })}>
|
||||||
<StyledFeatureLink to={`/projects/${project}/features/${feature}`}>
|
<StyledFeatureLink to={`/projects/${project}/features/${feature}`}>
|
||||||
<StyledTitle
|
<Truncator
|
||||||
style={{
|
lines={1}
|
||||||
WebkitLineClamp: 1,
|
title={feature}
|
||||||
lineClamp: 1,
|
arrow
|
||||||
|
sx={{
|
||||||
overflowWrap: 'anywhere',
|
overflowWrap: 'anywhere',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Highlighter search={searchQuery}>{feature}</Highlighter>
|
<span>
|
||||||
</StyledTitle>
|
<Highlighter search={searchQuery}>
|
||||||
|
{feature}
|
||||||
|
</Highlighter>
|
||||||
|
</span>
|
||||||
|
</Truncator>
|
||||||
</StyledFeatureLink>
|
</StyledFeatureLink>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
@ -154,14 +160,18 @@ const ArchivedFeatureName: FC<{
|
|||||||
searchQuery: string;
|
searchQuery: string;
|
||||||
}> = ({ feature, searchQuery }) => {
|
}> = ({ feature, searchQuery }) => {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Truncator
|
||||||
|
lines={1}
|
||||||
|
title={feature}
|
||||||
|
arrow
|
||||||
sx={(theme) => ({
|
sx={(theme) => ({
|
||||||
fontWeight: theme.typography.fontWeightBold,
|
fontWeight: theme.typography.fontWeightBold,
|
||||||
color: theme.palette.neutral.main,
|
color: theme.palette.neutral.main,
|
||||||
|
overflowWrap: 'anywhere',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Highlighter search={searchQuery}>{feature}</Highlighter>
|
<Highlighter search={searchQuery}>{feature}</Highlighter>
|
||||||
</Box>
|
</Truncator>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import { useSearchHighlightContext } from 'component/common/Table/SearchHighligh
|
|||||||
import { Box, styled } from '@mui/material';
|
import { Box, styled } from '@mui/material';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
|
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
|
||||||
|
import { Truncator } from 'component/common/Truncator/Truncator';
|
||||||
|
|
||||||
interface IHighlightCellProps {
|
interface IHighlightCellProps {
|
||||||
value: string;
|
value: string;
|
||||||
@ -21,14 +22,7 @@ const StyledContainer = styled(Box)(({ theme }) => ({
|
|||||||
padding: theme.spacing(1, 2),
|
padding: theme.spacing(1, 2),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const StyledTitle = styled('span')(({ theme }) => ({
|
const StyledTitle = styled('span')(() => ({}));
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
display: '-webkit-box',
|
|
||||||
WebkitBoxOrient: 'vertical',
|
|
||||||
WebkitLineClamp: '1',
|
|
||||||
lineClamp: '1',
|
|
||||||
}));
|
|
||||||
|
|
||||||
const StyledSubtitle = styled('span')(({ theme }) => ({
|
const StyledSubtitle = styled('span')(({ theme }) => ({
|
||||||
color: theme.palette.text.secondary,
|
color: theme.palette.text.secondary,
|
||||||
@ -73,16 +67,17 @@ export const HighlightCell: FC<IHighlightCellProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<StyledTitle
|
<Truncator
|
||||||
style={{
|
lines={subtitle ? 1 : 2}
|
||||||
WebkitLineClamp: subtitle ? 1 : 2,
|
title={value}
|
||||||
lineClamp: subtitle ? 1 : 2,
|
arrow
|
||||||
}}
|
|
||||||
data-loading
|
data-loading
|
||||||
>
|
>
|
||||||
<Highlighter search={searchQuery}>{value}</Highlighter>
|
<StyledTitle>
|
||||||
{afterTitle}
|
<Highlighter search={searchQuery}>{value}</Highlighter>
|
||||||
</StyledTitle>
|
{afterTitle}
|
||||||
|
</StyledTitle>
|
||||||
|
</Truncator>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(subtitle)}
|
condition={Boolean(subtitle)}
|
||||||
show={renderSubtitle}
|
show={renderSubtitle}
|
||||||
|
@ -33,13 +33,6 @@ export const StyledContainer = styled('div')(({ theme }) => ({
|
|||||||
wordBreak: 'break-all',
|
wordBreak: 'break-all',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const StyledTitle = styled('span')(({ theme }) => ({
|
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
display: '-webkit-box',
|
|
||||||
WebkitBoxOrient: 'vertical',
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const StyledDescription = styled('span')(({ theme }) => ({
|
export const StyledDescription = styled('span')(({ theme }) => ({
|
||||||
color: theme.palette.text.secondary,
|
color: theme.palette.text.secondary,
|
||||||
textDecoration: 'none',
|
textDecoration: 'none',
|
||||||
|
@ -4,11 +4,11 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
|
|||||||
import { Highlighter } from 'component/common/Highlighter/Highlighter';
|
import { Highlighter } from 'component/common/Highlighter/Highlighter';
|
||||||
import { useSearchHighlightContext } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
import { useSearchHighlightContext } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||||
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
|
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
|
||||||
|
import { Truncator } from 'component/common/Truncator/Truncator';
|
||||||
import {
|
import {
|
||||||
StyledWrapper,
|
StyledWrapper,
|
||||||
StyledLink,
|
StyledLink,
|
||||||
StyledContainer,
|
StyledContainer,
|
||||||
StyledTitle,
|
|
||||||
StyledDescription,
|
StyledDescription,
|
||||||
} from './LinkCell.styles';
|
} from './LinkCell.styles';
|
||||||
|
|
||||||
@ -51,16 +51,17 @@ export const LinkCell: React.FC<ILinkCellProps> = ({
|
|||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<StyledTitle
|
<Truncator
|
||||||
|
lines={subtitle ? 1 : 2}
|
||||||
|
title={title}
|
||||||
|
arrow
|
||||||
data-loading
|
data-loading
|
||||||
style={{
|
|
||||||
WebkitLineClamp: subtitle ? 1 : 2,
|
|
||||||
lineClamp: subtitle ? 1 : 2,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Highlighter search={searchQuery}>{title}</Highlighter>
|
<span>
|
||||||
{children}
|
<Highlighter search={searchQuery}>{title}</Highlighter>
|
||||||
</StyledTitle>
|
{children}
|
||||||
|
</span>
|
||||||
|
</Truncator>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(subtitle)}
|
condition={Boolean(subtitle)}
|
||||||
show={renderSubtitle}
|
show={renderSubtitle}
|
||||||
|
@ -275,16 +275,21 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
className="css-u8cmsa"
|
className="css-u8cmsa"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="css-697v50"
|
aria-label=""
|
||||||
|
aria-labelledby={null}
|
||||||
|
className=" MuiBox-root css-gzore8"
|
||||||
data-loading={true}
|
data-loading={true}
|
||||||
style={
|
data-mui-internal-clone-element={true}
|
||||||
{
|
onBlur={[Function]}
|
||||||
"WebkitLineClamp": 1,
|
onFocus={[Function]}
|
||||||
"lineClamp": 1,
|
onMouseLeave={[Function]}
|
||||||
}
|
onMouseOver={[Function]}
|
||||||
}
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
>
|
>
|
||||||
Tag type name
|
<span>
|
||||||
|
Tag type name
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="css-1121jr7"
|
className="css-1121jr7"
|
||||||
@ -449,16 +454,21 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
className="css-u8cmsa"
|
className="css-u8cmsa"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="css-697v50"
|
aria-label=""
|
||||||
|
aria-labelledby={null}
|
||||||
|
className=" MuiBox-root css-gzore8"
|
||||||
data-loading={true}
|
data-loading={true}
|
||||||
style={
|
data-mui-internal-clone-element={true}
|
||||||
{
|
onBlur={[Function]}
|
||||||
"WebkitLineClamp": 1,
|
onFocus={[Function]}
|
||||||
"lineClamp": 1,
|
onMouseLeave={[Function]}
|
||||||
}
|
onMouseOver={[Function]}
|
||||||
}
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
>
|
>
|
||||||
Tag type name
|
<span>
|
||||||
|
Tag type name
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="css-1121jr7"
|
className="css-1121jr7"
|
||||||
@ -623,16 +633,21 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
className="css-u8cmsa"
|
className="css-u8cmsa"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="css-697v50"
|
aria-label=""
|
||||||
|
aria-labelledby={null}
|
||||||
|
className=" MuiBox-root css-gzore8"
|
||||||
data-loading={true}
|
data-loading={true}
|
||||||
style={
|
data-mui-internal-clone-element={true}
|
||||||
{
|
onBlur={[Function]}
|
||||||
"WebkitLineClamp": 1,
|
onFocus={[Function]}
|
||||||
"lineClamp": 1,
|
onMouseLeave={[Function]}
|
||||||
}
|
onMouseOver={[Function]}
|
||||||
}
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
>
|
>
|
||||||
Tag type name
|
<span>
|
||||||
|
Tag type name
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="css-1121jr7"
|
className="css-1121jr7"
|
||||||
@ -797,16 +812,21 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
className="css-u8cmsa"
|
className="css-u8cmsa"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="css-697v50"
|
aria-label=""
|
||||||
|
aria-labelledby={null}
|
||||||
|
className=" MuiBox-root css-gzore8"
|
||||||
data-loading={true}
|
data-loading={true}
|
||||||
style={
|
data-mui-internal-clone-element={true}
|
||||||
{
|
onBlur={[Function]}
|
||||||
"WebkitLineClamp": 1,
|
onFocus={[Function]}
|
||||||
"lineClamp": 1,
|
onMouseLeave={[Function]}
|
||||||
}
|
onMouseOver={[Function]}
|
||||||
}
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
>
|
>
|
||||||
Tag type name
|
<span>
|
||||||
|
Tag type name
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="css-1121jr7"
|
className="css-1121jr7"
|
||||||
@ -971,16 +991,21 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
className="css-u8cmsa"
|
className="css-u8cmsa"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="css-697v50"
|
aria-label=""
|
||||||
|
aria-labelledby={null}
|
||||||
|
className=" MuiBox-root css-gzore8"
|
||||||
data-loading={true}
|
data-loading={true}
|
||||||
style={
|
data-mui-internal-clone-element={true}
|
||||||
{
|
onBlur={[Function]}
|
||||||
"WebkitLineClamp": 1,
|
onFocus={[Function]}
|
||||||
"lineClamp": 1,
|
onMouseLeave={[Function]}
|
||||||
}
|
onMouseOver={[Function]}
|
||||||
}
|
onTouchEnd={[Function]}
|
||||||
|
onTouchStart={[Function]}
|
||||||
>
|
>
|
||||||
Tag type name
|
<span>
|
||||||
|
Tag type name
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="css-1121jr7"
|
className="css-1121jr7"
|
||||||
|
Loading…
Reference in New Issue
Block a user