Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 3 additions & 13 deletions components/collapsible-panel/collapsible-panel-summary-item.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import '../colors/colors.js';
import { css, html, LitElement } from 'lit';
import { css, html, LitElement, nothing } from 'lit';
import { bodySmallStyles } from '../typography/styles.js';
import { classMap } from 'lit/directives/class-map.js';
import { getOverflowDeclarations } from '../../helpers/overflow.js';
import { SkeletonMixin } from '../skeleton/skeleton-mixin.js';
import { styleMap } from 'lit/directives/style-map.js';

/**
* A component for a "summary item" child component that describes the content in a collapsible panel.
Expand Down Expand Up @@ -35,9 +33,6 @@ class CollapsiblePanelSummaryItem extends SkeletonMixin(LitElement) {
.d2l-body-small {
line-height: 1.2rem;
}
p.truncate {
${getOverflowDeclarations({ lines: 1 })}
}
`];

constructor() {
Expand All @@ -47,13 +42,8 @@ class CollapsiblePanelSummaryItem extends SkeletonMixin(LitElement) {
}

render() {
const classes = {
'd2l-body-small': true,
'd2l-skeletize': true,
'truncate': this.lines > 0
};
const styles = (this.lines > 0) ? { '-webkit-line-clamp': this.lines } : {};
return html`<p class="${classMap(classes)}" style="${styleMap(styles)}">${this.text}</p>`;
const styles = this.lines ? getOverflowDeclarations({ lines: this.lines }) : null;
return html`<p class="d2l-body-small d2l-skeletize" style="${styles ?? nothing}">${this.text}</p>`;
}
}

Expand Down
20 changes: 4 additions & 16 deletions components/link/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ import '../colors/colors.js';
import '../icons/icon.js';
import '../tooltip/tooltip.js';
import { css, html, LitElement, nothing } from 'lit';
import { getOverflowDeclarations, overflowEllipsisDeclarations } from '../../helpers/overflow.js';
import { _generateLinkStyles } from './link-styles.js';
import { classMap } from 'lit/directives/class-map.js';
import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
import { getOverflowDeclarations } from '../../helpers/overflow.js';
import { getUniqueId } from '../../helpers/uniqueId.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
import { offscreenStyles } from '../offscreen/offscreen.js';
import { styleMap } from 'lit/directives/style-map.js';

export const linkStyles = _generateLinkStyles('.d2l-link', true);

Expand Down Expand Up @@ -90,12 +89,6 @@ class Link extends LocalizeCoreElement(FocusMixin(LitElement)) {
align-items: baseline;
display: flex;
}
a span.truncate {
${getOverflowDeclarations({ lines: 1 })}
}
a span.truncate-one {
${overflowEllipsisDeclarations}
}
#new-window {
line-height: 0;
white-space: nowrap;
Expand Down Expand Up @@ -157,12 +150,7 @@ class Link extends LocalizeCoreElement(FocusMixin(LitElement)) {
'd2l-link-main': this.main,
'd2l-link-small': this.small
};
const spanClasses = {
'd2l-link-content': true,
'truncate': this.lines > 1,
'truncate-one': this.lines === 1
};
const styles = { webkitLineClamp: this.lines || null };
const styles = this.lines ? getOverflowDeclarations({ lines: this.lines }) : null;
Comment on lines -160 to +153

@bearfriend bearfriend Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of handling 1 and >1 lines cases with separate classes, we can use the same it seemed simpler to just apply the styles inline. Even though the same call gets us the correct style now, the stylesheet doesn't update with property changes so it needs to either happen on render, or go back to separate classes

const newWindowElements = (this.target === '_blank')
? html`<span id="new-window"><span style="font-size: 0;">&nbsp;</span><d2l-icon icon="tier1:new-window"></d2l-icon></span><span class="d2l-offscreen">${this.localize('components.link.open-in-new-window')}</span>`
: nothing;
Expand All @@ -186,8 +174,8 @@ class Link extends LocalizeCoreElement(FocusMixin(LitElement)) {
tabindex="${ifDefined(this.disabled && this.disabledTooltip ? 0 : undefined)}"
target="${ifDefined(this.target)}"
><span
class="${classMap(spanClasses)}"
style="${styleMap(styles)}"><slot></slot></span>${newWindowElements}</a>${disabledTooltip}`;
class="d2l-link-content"
style="${styles ?? nothing}"><slot></slot></span>${newWindowElements}</a>${disabledTooltip}`;
}

#linkId = getUniqueId();
Expand Down
10 changes: 5 additions & 5 deletions helpers/overflow.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { set } from './template-tags.js';
import { unsafeCSS } from 'lit';

export const overflowHiddenDeclarations = getOverflowDeclarations({});
export const overflowEllipsisDeclarations = getOverflowDeclarations({ textOverflow: 'ellipsis' });
export const overflowHiddenDeclarations = getOverflowDeclarations({ lines: 0 });
export const overflowEllipsisDeclarations = getOverflowDeclarations({ textOverflow: 'ellipsis', lines: 0 });

export function getOverflowDeclarations({ textOverflow = '', lines = 0, lit = true } = {}) {
export function getOverflowDeclarations({ textOverflow = '', lines = 1, lit = true } = {}) {
if (!arguments.length) return overflowHiddenDeclarations;
if (arguments[0].lines === 1) return overflowEllipsisDeclarations;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this not ignore the textOverflow option?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also does just lines === 1 break? Or why do we need to use the args object?

@bearfriend bearfriend Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arguments because we want to check what was passed in, not what was defaulted. It will ignore textOverflow because if you're passing lines that means you inherently are expecting the standard ellipses overflow. It would do that now already since that's the only way line-clamp renders. It sets it but doesn't do anything now.


const declarations = set`
min-width: 0; /* clamps width of flex items */
overflow-x: clip;
${lines
${lines > 1 || lines.constructor === String
? set`
display: -webkit-box;
overflow-clip-margin: 0.2em;
overflow-wrap: anywhere;
overflow-y: clip;
text-overflow: ${textOverflow || 'ellipsis'};
-webkit-box-orient: vertical;
-webkit-line-clamp: ${lines};`
: set`
Expand Down
15 changes: 13 additions & 2 deletions helpers/test/overflow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('overflow', () => {
expect(declarations).to.equal(overflowHiddenDeclarations.cssText);
});

it('should return line clamping declarations when lines > 0', () => {
it('should return line clamping declarations when lines > 1', () => {
const declarations = getOverflowDeclarations({ lines: 3 });
expect(declarations.cssText).to.equal(set`
min-width: 0; /* clamps width of flex items */
Expand All @@ -30,7 +30,6 @@ describe('overflow', () => {
overflow-clip-margin: 0.2em;
overflow-wrap: anywhere;
overflow-y: clip;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
`);
Expand All @@ -48,6 +47,18 @@ describe('overflow', () => {
white-space: nowrap;
`);
});

it('should produce overflow ellipsis declarations when lines is 1', () => {
const declarations = getOverflowDeclarations({ lines: 1 });
expect(declarations.cssText).to.equal(set`
min-width: 0; /* clamps width of flex items */
overflow-x: clip;
overflow-clip-margin: 1em;
overflow-y: visible;
text-overflow: ellipsis;
white-space: nowrap;
`);
});
});

describe('overflowEllipsisDeclarations', () => {
Expand Down