fix(collab): a long link title wraps instead of being cut off

The link chip held its title on one line with an ellipsis, and nothing in
the UI showed the rest: the tooltip names the action, not the link, and a
phone or the PWA has no hover at all. The title now wraps and the chip grows
in height, the host drops to its own line under a wrapped title, and the
chip keeps rounded corners instead of pill ends once it is taller.

Closes #2550
This commit is contained in:
Maurice
2026-09-29 20:49:56 +02:00
parent 64087512df
commit ec06035855
2 changed files with 41 additions and 11 deletions
@@ -1,4 +1,4 @@
// FE-COMP-LINKS-001 to FE-COMP-LINKS-015
// FE-COMP-LINKS-001 to FE-COMP-LINKS-016
vi.mock('../../api/websocket', () => ({
connect: vi.fn(),
@@ -223,6 +223,32 @@ describe('CollabLinks', () => {
expect(action).toMatch(/margin:\s*-4px 0/);
});
it('FE-COMP-LINKS-016: a long title wraps and grows the chip instead of ending in an ellipsis (#2550)', async () => {
const title = 'Very long ferry timetable for the northern isles in the summer season';
server.use(http.get('/api/trips/1/collab/links', () => HttpResponse.json({ links: [buildLink({ title })] })));
render(<CollabLinks tripId={1} />);
// The whole name is in the chip, not a shortened copy of it.
expect(await screen.findByText(title)).toHaveClass('collab-link-chip__title');
// jsdom lays nothing out, so the rules are the assertion: the title may not be
// cut, and it has to be allowed to break, even inside one long word.
const css = readFileSync(resolve(process.cwd(), 'src/index.css'), 'utf8');
const rule = (selector: string) => {
const at = css.indexOf(`\n${selector} {`);
return at === -1 ? '' : css.slice(at, css.indexOf('}', at));
};
const titleRule = rule('.collab-link-chip__title');
expect(titleRule, '.collab-link-chip__title rule missing from index.css').not.toBe('');
expect(titleRule).not.toMatch(/white-space:\s*nowrap/);
expect(titleRule).not.toMatch(/text-overflow:\s*ellipsis/);
expect(titleRule).not.toMatch(/overflow:\s*hidden/);
expect(titleRule).toMatch(/overflow-wrap:\s*anywhere/);
// The host drops below a wrapping title instead of squeezing it.
expect(rule('.collab-link-chip__text')).toMatch(/flex-wrap:\s*wrap/);
// A grown chip keeps rounded corners rather than a pill's stadium ends.
expect(rule('.collab-link-chip')).not.toMatch(/border-radius:\s*999px/);
});
it('FE-COMP-LINKS-008: a viewer without edit rights gets no add button', async () => {
// collab_edit reserved for the owner, on somebody else's trip.
seedStore(usePermissionsStore, { permissions: { collab_edit: 'trip_owner' } });
+14 -10
View File
@@ -1401,7 +1401,9 @@ img[alt="TREK"] {
gap: 6px;
min-width: 0;
padding: 5px 8px 5px 5px;
border-radius: 999px;
/* Half the one-line height, so a one-line chip is still a pill and one whose
title wraps (#2550) keeps its rounded corners instead of a stadium end. */
border-radius: 18px;
background: var(--bg-secondary);
border: 1px solid var(--border-faint);
box-shadow: var(--shadow-sm);
@@ -1453,12 +1455,13 @@ img[alt="TREK"] {
.collab-link-chip__main:hover .collab-link-chip__go, .collab-link-chip__main:focus-visible .collab-link-chip__go { opacity: 1; }
.collab-link-chip__main:hover .collab-link-chip__icon > :not(.collab-link-chip__go),
.collab-link-chip__main:focus-visible .collab-link-chip__icon > :not(.collab-link-chip__go) { opacity: 0; }
/* Title first, host with what is left: a max-content track takes its full width
before the fr track sees any, and shrinks only once the title alone no longer
fits. Two flex items shrank together and both ended in an ellipsis. */
/* The title is never cut (#2550): it wraps and the chip grows in height, so the
full name is on screen on every device, not behind a tooltip a phone has no
way to show. The host sits beside a title short enough to leave room and drops
to its own line below one that wraps; only the host is allowed an ellipsis. */
.collab-link-chip__text {
display: grid;
grid-template-columns: minmax(0, max-content) minmax(0, 1fr);
display: flex;
flex-wrap: wrap;
align-items: baseline;
column-gap: 6px;
min-width: 0;
@@ -1467,11 +1470,11 @@ img[alt="TREK"] {
.collab-link-chip__title {
font-size: calc(12.5px * var(--fs-scale-body, 1));
font-weight: 600;
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.25;
white-space: normal;
overflow-wrap: anywhere;
min-width: 0;
max-width: 100%;
}
.collab-link-chip__host {
font-size: calc(10.5px * var(--fs-scale-caption, 1));
@@ -1480,6 +1483,7 @@ img[alt="TREK"] {
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
max-width: 100%;
}
.collab-link-chip__actions {
display: flex;