Skip to content

Commit 90c3480

Browse files
committed
fix(FR-2807): replace antd EllipsisMeasure in BAILink with BAIText CSS ellipsis
1 parent c68eddb commit 90c3480

2 files changed

Lines changed: 56 additions & 21 deletions

File tree

packages/backend.ai-ui/src/components/BAILink.stories.tsx

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import BAIFlex from './BAIFlex';
22
import BAILink from './BAILink';
3+
import BAIText from './BAIText';
34
import type { Meta, StoryObj } from '@storybook/react-vite';
45
import { MemoryRouter, Route, Routes } from 'react-router-dom';
56

@@ -18,7 +19,15 @@ const meta: Meta<typeof BAILink> = {
1819
- Uses React Router \`Link\` when \`to\` prop is provided
1920
- Falls back to Ant Design \`Typography.Link\` when \`to\` is not provided
2021
- Custom hover and disabled states
21-
- Ellipsis with tooltip support
22+
- Ellipsis with tooltip support via \`BAIText\` (CSS-based, no layout-loop risk)
23+
24+
## Ellipsis Behavior
25+
When \`ellipsis\` is provided, the content is wrapped by \`BAIText\` internally:
26+
- \`ellipsis={true}\` — CSS truncation + tooltip showing full text on overflow
27+
- \`ellipsis={{ tooltip: 'custom' }}\` — CSS truncation + custom tooltip text
28+
29+
This avoids antd's JS-based \`EllipsisMeasure\` component, which can cause infinite
30+
render loops when nested inside flex containers with \`ResizeObserver\`.
2231
2332
## BAI-Specific Props
2433
| Prop | Type | Default | Description |
@@ -50,7 +59,8 @@ For other props, refer to [React Router Link](https://reactrouter.com/en/main/co
5059
},
5160
ellipsis: {
5261
control: false,
53-
description: 'Enable text ellipsis with optional tooltip',
62+
description:
63+
'Enable text ellipsis with optional tooltip. Internally uses BAIText for CSS-based truncation.',
5464
table: {
5565
type: { summary: 'boolean | { tooltip?: string }' },
5666
},
@@ -118,30 +128,58 @@ export const WithEllipsis: Story = {
118128
parameters: {
119129
docs: {
120130
description: {
121-
story:
122-
'Long text can be truncated with ellipsis. Add `tooltip` property to show full text on hover.',
131+
story: `Long text is truncated via CSS ellipsis (no layout-loop risk).
132+
\`ellipsis={true}\` shows the full text as a tooltip on overflow.
133+
Hover over the truncated links below to see the tooltip.`,
123134
},
124135
},
125136
},
126137
render: () => (
127138
<BAIFlex direction="column" gap="md">
128-
<BAIFlex direction="column" gap="xs" style={{ width: '200px' }}>
129-
<strong>Ellipsis without tooltip</strong>
139+
<BAIFlex direction="column" gap="xs" style={{ width: 200 }}>
140+
<strong>ellipsis (boolean) — tooltip on overflow</strong>
130141
<BAILink ellipsis>
131142
This is a very long link text that will be truncated with ellipsis
132143
</BAILink>
133144
</BAIFlex>
134-
<BAIFlex direction="column" gap="xs" style={{ width: '200px' }}>
135-
<strong>Ellipsis with tooltip</strong>
136-
<BAILink
137-
ellipsis={{
138-
tooltip:
139-
'This is a very long link text that will be truncated with ellipsis',
140-
}}
141-
>
145+
<BAIFlex direction="column" gap="xs" style={{ width: 200 }}>
146+
<strong>ellipsis with custom tooltip</strong>
147+
<BAILink ellipsis={{ tooltip: 'Full text shown here as tooltip' }}>
142148
This is a very long link text that will be truncated with ellipsis
143149
</BAILink>
144150
</BAIFlex>
145151
</BAIFlex>
146152
),
147153
};
154+
155+
export const EllipsisInsideContainer: Story = {
156+
parameters: {
157+
docs: {
158+
description: {
159+
story: `A common pattern: \`BAILink ellipsis\` nested inside a \`BAIText ellipsis\` container
160+
(as used in \`BAINameActionCell\`). Both truncation layers are CSS-based and do not
161+
conflict — the outer \`BAIText\` clips the row, the inner \`BAILink\` tooltip shows on hover.`,
162+
},
163+
},
164+
},
165+
render: () => (
166+
<BAIFlex direction="column" gap="md">
167+
<BAIFlex direction="column" gap="xs" style={{ width: 240 }}>
168+
<strong>BAILink inside BAIText (table cell pattern)</strong>
169+
<BAIText ellipsis={{ tooltip: true }}>
170+
<BAILink type="hover" ellipsis>
171+
very-long-revision-name-abc123def456ghi789
172+
</BAILink>
173+
</BAIText>
174+
</BAIFlex>
175+
<BAIFlex direction="column" gap="xs" style={{ width: 240 }}>
176+
<strong>Short text (no truncation)</strong>
177+
<BAIText ellipsis={{ tooltip: true }}>
178+
<BAILink type="hover" ellipsis>
179+
rev-001
180+
</BAILink>
181+
</BAIText>
182+
</BAIFlex>
183+
</BAIFlex>
184+
),
185+
};

packages/backend.ai-ui/src/components/BAILink.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import BAIText from './BAIText';
12
import { theme, Typography } from 'antd';
23
import { createStyles } from 'antd-style';
34
import React from 'react';
@@ -52,17 +53,13 @@ const BAILink: React.FC<BAILinkProps> = ({
5253
className={type ? styles?.[type] : undefined}
5354
onClick={linkProps.onClick}
5455
disabled={type === 'disabled'}
55-
ellipsis={!!ellipsis}
5656
{...linkProps}
5757
>
58-
{typeof ellipsis === 'object' && ellipsis.tooltip ? (
59-
<Typography.Text
60-
className={type ? styles?.[type] : undefined}
61-
ellipsis={ellipsis}
62-
>
58+
{ellipsis ? (
59+
<BAIText ellipsis={ellipsis === true ? { tooltip: true } : ellipsis}>
6360
{children}
6461
{icon}
65-
</Typography.Text>
62+
</BAIText>
6663
) : (
6764
<>
6865
{children}

0 commit comments

Comments
 (0)