Skip to content

Commit 91b36b0

Browse files
committed
internal(summary-control): add support for links in summary helper text via unsafe html rendering
1 parent 35de2c6 commit 91b36b0

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

src/elements/internal/InternalSummaryControl/InternalSummaryControl.test.ts

+31
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ describe('InternalSummaryControl', () => {
2020
expect(new Control()).to.be.instanceOf(customElements.get('foxy-internal-editable-control'));
2121
});
2222

23+
it('has a reactive property "unsafeHelperText" that defaults to false', () => {
24+
expect(new Control()).to.have.property('unsafeHelperText', false);
25+
expect(Control).to.have.deep.nested.property('properties.unsafeHelperText', {
26+
attribute: 'unsafe-helper-text',
27+
type: Boolean,
28+
});
29+
});
30+
2331
it('has a reactive property "layout" that defaults to null', () => {
2432
expect(Control).to.have.deep.nested.property('properties.layout', {});
2533
expect(new Control()).to.have.property('layout', null);
@@ -80,6 +88,15 @@ describe('InternalSummaryControl', () => {
8088
expect(control.renderRoot).to.include.text('Test helper text');
8189
});
8290

91+
it('renders unsafe helper text in default layout if "unsafeHelperText" is true', async () => {
92+
const control = await fixture<Control>(html`
93+
<foxy-internal-summary-control helper-text="Test <span>unsafe</span>" unsafe-helper-text>
94+
</foxy-internal-summary-control>
95+
`);
96+
97+
expect(control.renderRoot).to.include.html('Test <span>unsafe</span>');
98+
});
99+
83100
it('renders default slot in default layout', async () => {
84101
const control = await fixture<Control>(html`
85102
<foxy-internal-summary-control></foxy-internal-summary-control>
@@ -135,6 +152,20 @@ describe('InternalSummaryControl', () => {
135152
expect(summary).to.include.text('Test helper text');
136153
});
137154

155+
it('renders unsafe helper text inside of the details summary in details layout if "unsafeHelperText" is true', async () => {
156+
const control = await fixture<Control>(html`
157+
<foxy-internal-summary-control
158+
helper-text="Test <span>unsafe</span>"
159+
layout="details"
160+
unsafe-helper-text
161+
>
162+
</foxy-internal-summary-control>
163+
`);
164+
165+
const summary = control.renderRoot.querySelector('summary');
166+
expect(summary).to.include.html('Test <span>unsafe</span>');
167+
});
168+
138169
it('renders default slot inside of the details content in details layout', async () => {
139170
const control = await fixture<Control>(html`
140171
<foxy-internal-summary-control layout="details"></foxy-internal-summary-control>

src/elements/internal/InternalSummaryControl/InternalSummaryControl.ts

+25-2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ import type { CSSResultArray, PropertyDeclarations } from 'lit-element';
22
import { svg, TemplateResult } from 'lit-html';
33

44
import { InternalEditableControl } from '../InternalEditableControl/InternalEditableControl';
5+
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
56
import { html, css } from 'lit-element';
67

78
export class InternalSummaryControl extends InternalEditableControl {
89
static get properties(): PropertyDeclarations {
910
return {
1011
...super.properties,
12+
unsafeHelperText: { type: Boolean, attribute: 'unsafe-helper-text' },
1113
layout: {},
1214
count: { type: Number },
1315
open: { type: Boolean },
@@ -34,10 +36,27 @@ export class InternalSummaryControl extends InternalEditableControl {
3436
details[open] summary > div {
3537
border-radius: var(--lumo-border-radius) var(--lumo-border-radius) 0 0;
3638
}
39+
40+
.with-unsafe a {
41+
text-decoration: underline;
42+
transition: color 0.1s ease-in-out;
43+
}
44+
45+
.with-unsafe a:hover {
46+
color: var(--lumo-primary-text-color);
47+
}
48+
49+
.with-unsafe a:focus {
50+
outline: none;
51+
box-shadow: 0 0 0 2px var(--lumo-primary-color-50pct);
52+
border-radius: var(--lumo-border-radius-s);
53+
}
3754
`,
3855
];
3956
}
4057

58+
unsafeHelperText = false;
59+
4160
layout: null | 'section' | 'details' = null;
4261

4362
count: number | null = null;
@@ -80,7 +99,9 @@ export class InternalSummaryControl extends InternalEditableControl {
8099
${svg`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" style="width: 1.2em; height: 1.2em"><path fill-rule="evenodd" d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" /></svg>`}
81100
</span>
82101
</p>
83-
<p class="text-s text-secondary" ?hidden=${!this.helperText}>${this.helperText}</p>
102+
<p class="text-s text-secondary with-unsafe" ?hidden=${!this.helperText}>
103+
${this.unsafeHelperText ? unsafeHTML(this.helperText) : this.helperText}
104+
</p>
84105
</div>
85106
</summary>
86107
<div class="overflow-hidden grid" style="gap: 1px">
@@ -93,7 +114,9 @@ export class InternalSummaryControl extends InternalEditableControl {
93114
return html`
94115
<div class="leading-s mb-s" ?hidden=${!this.label && !this.helperText}>
95116
<p class="font-medium text-body text-l" ?hidden=${!this.label}>${this.label}</p>
96-
<p class="text-s text-secondary" ?hidden=${!this.helperText}>${this.helperText}</p>
117+
<p class="text-s text-secondary with-unsafe" ?hidden=${!this.helperText}>
118+
${this.unsafeHelperText ? unsafeHTML(this.helperText) : this.helperText}
119+
</p>
97120
</div>
98121
<div class="rounded overflow-hidden grid" style="gap: 1px">
99122
<slot></slot>

0 commit comments

Comments
 (0)