Skip to content

Commit 560b9c6

Browse files
APIC-830 collapsable example panel (#26)
* APIC-830 Add behavior collapsable to panel example Co-authored-by: Carolina Wright <carolina.wright@mulesoft.com>
1 parent 3517135 commit 560b9c6

File tree

8 files changed

+171
-38
lines changed

8 files changed

+171
-38
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@api-components/api-resource-example-document",
33
"description": "A viewer for examples in a resource based on AMF model",
4-
"version": "4.3.4",
4+
"version": "4.3.5",
55
"license": "Apache-2.0",
66
"main": "index.js",
77
"module": "index.js",

src/ApiExampleRender.js

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -410,15 +410,17 @@ export class ApiExampleRender extends LitElement {
410410
const isJson = this._computeIsJson(this.isJson, example.value);
411411
return html`
412412
<div class="example-actions">
413-
<anypoint-button
414-
part="content-action-button, code-content-action-button"
415-
class="action-button"
416-
data-action="copy"
417-
@click="${this._copyToClipboard}"
418-
?compatibility="${compatibility}"
419-
title="Copy example to clipboard"
420-
>Copy</anypoint-button>
421-
${isJson ? html`
413+
<arc-icon class="info-icon" icon="code"></arc-icon>
414+
<div>
415+
<anypoint-button
416+
part="content-action-button, code-content-action-button"
417+
class="action-button"
418+
data-action="copy"
419+
@click="${this._copyToClipboard}"
420+
?compatibility="${compatibility}"
421+
title="Copy example to clipboard"
422+
>Copy</anypoint-button>
423+
${isJson ? html`
422424
<anypoint-button
423425
part="content-action-button, code-content-action-button"
424426
class="action-button"
@@ -429,17 +431,18 @@ export class ApiExampleRender extends LitElement {
429431
?compatibility="${compatibility}"
430432
title="Toggle between table and JSON view"
431433
>Table view</anypoint-button>` : ''}
432-
${hasRaw ? html`
433-
<anypoint-button
434-
part="content-action-button, code-content-action-button"
435-
class="action-button"
436-
data-action="code"
437-
toggles
438-
.active="${this.sourceOpened}"
439-
@active-changed="${this._toggleSourceOpened}"
440-
?compatibility="${compatibility}"
441-
title="Toggle between JSON and example source view"
442-
>Source view</anypoint-button>` : ''}
434+
${hasRaw ? html`
435+
<anypoint-button
436+
part="content-action-button, code-content-action-button"
437+
class="action-button"
438+
data-action="code"
439+
toggles
440+
.active="${this.sourceOpened}"
441+
@active-changed="${this._toggleSourceOpened}"
442+
?compatibility="${compatibility}"
443+
title="Toggle between JSON and example source view"
444+
>Source view</anypoint-button>` : ''}
445+
</div>
443446
</div>`;
444447
}
445448

src/ApiResourceExampleDocument.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,4 +216,6 @@ export class ApiResourceExampleDocument extends AmfHelperMixin(LitElement) {
216216
_computeExampleDescription(example: Example): string;
217217

218218
_exampleTitleIsMediaType(example: Example): boolean;
219+
220+
_handleCollapsePanel(): void;
219221
}

src/ApiResourceExampleDocument.js

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ export class ApiResourceExampleDocument extends AmfHelperMixin(LitElement) {
117117
* read-only properties to the example
118118
*/
119119
renderReadOnly: { type: Boolean },
120+
/**
121+
* If enabled, the example panel would be closed
122+
*/
123+
_collapseExamplePanel: { type: Boolean, reflect: true },
120124
};
121125
}
122126

@@ -313,6 +317,19 @@ export class ApiResourceExampleDocument extends AmfHelperMixin(LitElement) {
313317
}));
314318
}
315319

320+
get _collapseExamplePanel() {
321+
return this.__collapseExamplePanel
322+
}
323+
324+
set _collapseExamplePanel(value) {
325+
const old = this.__collapseExamplePanel;
326+
if (old === value) {
327+
return;
328+
}
329+
this.__collapseExamplePanel = value;
330+
this.requestUpdate('_collapseExamplePanel', old);
331+
}
332+
316333
constructor() {
317334
super();
318335
this._onStorageChanged = this._onStorageChanged.bind(this);
@@ -324,6 +341,7 @@ export class ApiResourceExampleDocument extends AmfHelperMixin(LitElement) {
324341
this.hasExamples = false;
325342
this.compatibility = false;
326343
this.renderReadOnly = false;
344+
this._collapseExamplePanel = false;
327345
this._ensureJsonTable();
328346
}
329347

@@ -549,16 +567,44 @@ export class ApiResourceExampleDocument extends AmfHelperMixin(LitElement) {
549567
this.table = e.detail.value;
550568
}
551569

570+
/**
571+
* Collapse the current example panel
572+
*/
573+
_handleCollapsePanel() {
574+
const examplePanel = this.shadowRoot.querySelector('.renderer')
575+
const icon = this.shadowRoot.querySelector('.expand-icon')
576+
icon.classList.toggle('expand-icon-collapse')
577+
examplePanel.classList.toggle('collapse')
578+
579+
this._collapseExamplePanel = !this._collapseExamplePanel
580+
}
581+
552582
/**
553583
* @param {Example} example
554584
* @returns {TemplateResult|string}
555585
*/
556586
_titleTemplate(example) {
587+
const { compatibility } = this;
588+
557589
if (example.isScalar) {
558590
return '';
559591
}
560592
const label = this._computeExampleTitle(example);
561-
return html`<div class="example-title">${label}</div>`;
593+
return html`<div
594+
class="example-title"
595+
@click="${this._handleCollapsePanel}"
596+
@keyup="${this._handleCollapsePanel}"
597+
?compatibility="${compatibility}"
598+
>
599+
<span>${label}</span>
600+
<anypoint-icon-button
601+
class="expand-icon-wrapper"
602+
data-action="collapse"
603+
title="Collapse panel"
604+
>
605+
<arc-icon class="expand-icon" icon="expandLess"></arc-icon>
606+
</anypoint-icon-button>
607+
</div>`;
562608
}
563609

564610
/**
@@ -622,7 +668,6 @@ export class ApiResourceExampleDocument extends AmfHelperMixin(LitElement) {
622668
${this._titleTemplate(item)}
623669
${this._descriptionTemplate(item)}
624670
<div class="renderer">
625-
<arc-icon class="info-icon" icon="code"></arc-icon>
626671
<api-example-render
627672
exportParts="${parts}"
628673
class="example"

src/styles/Document.js

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,67 @@ export default css`
2121
line-height: var(--arc-font-body1-line-height);
2222
font-size: 1rem;
2323
display: var(--api-example-title-display, block);
24-
padding: 8px 12px;
24+
min-height: 36px;
25+
padding: 0 10px 0px 10px;
2526
background-color: var(--api-example-title-background-color, #ff9800);
2627
color: var(--api-example-title-color, #000);
27-
border-top-right-radius: 2px;
28-
border-top-left-radius: 2px;
28+
border-radius: 0px 2px 0px 0px;
29+
display: flex;
30+
justify-content: space-between;
31+
align-items: center;
32+
cursor: pointer;
33+
}
34+
35+
.expand-icon {
36+
height: 25px;
37+
width: 25px;
38+
-moz-transform:none;
39+
-webkit-transform:none;
40+
-o-transform:none;
41+
-ms-transform:none;
42+
transform:none;
43+
-webkit-transition: transform 0.2s 0.2s ease;
44+
-moz-transition: transform 0.2s 0.2s ease;
45+
-o-transition: transform 0.2s 0.2s ease;
46+
transition: transform 0.2s 0.2s ease;
47+
}
48+
49+
.expand-icon-wrapper {
50+
height: 30px;
51+
width: 30px;
2952
}
3053
3154
.renderer {
3255
padding: 8px 0;
3356
display: flex;
57+
max-height: 500px;
58+
-webkit-transition: all 0.4s 0.1s ease-in-out;
59+
-moz-transition: all 0.4s 0.1s ease-in-out;
60+
-o-transition: all 0.4s 0.1s ease-in-out;
61+
transition: all 0.4s 0.1s ease-in-out;
62+
}
63+
64+
.collapse {
65+
max-height: 0;
66+
margin: 0;
67+
overflow: hidden;
68+
padding: 0;
69+
-webkit-transition: all 0.4s 0.1s ease-in-out;
70+
-moz-transition: all 0.4s 0.1s ease-in-out;
71+
-o-transition: all 0.4s 0.1s ease-in-out;
72+
transition: all 0.4s 0.1s ease-in-out;
3473
}
3574
36-
.info-icon {
37-
margin: 0 12px;
38-
fill: var(--api-example-accent-color, #FF9800);
39-
width: 24px;
40-
height: 24px;
75+
.expand-icon-collapse {
76+
-moz-transform: rotate(180deg);
77+
-webkit-transform: rotate(180deg);
78+
-o-transform: rotate(180deg);
79+
-ms-transform: rotate(180deg);
80+
transform: rotate(180deg);
81+
-webkit-transition: transform 0.2s 0.2s ease;
82+
-moz-transition: transform 0.2s 0.2s ease;
83+
-o-transition: transform 0.2s 0.2s ease;
84+
transition: transform 0.2s 0.2s ease;
4185
}
4286
4387
api-example-render {

src/styles/Render.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export default css`
88
99
.code-wrapper {
1010
padding: 0px;
11+
margin-left: 42px;
1112
}
1213
1314
[hidden] {
@@ -54,26 +55,31 @@ export default css`
5455
display: flex;
5556
align-items: center;
5657
flex-direction: row;
57-
justify-content: flex-end;
58+
justify-content: space-between;
59+
margin: 0;
60+
margin-right: 10px;
5861
flex-wrap: wrap;
5962
flex: 1;
6063
}
6164
65+
.info-icon {
66+
margin: 0 12px;
67+
fill: var(--api-example-accent-color, #FF9800);
68+
width: 24px;
69+
height: 24px;
70+
}
71+
6272
anypoint-button {
63-
margin-bottom: 8px;
6473
height: 28px;
6574
color: var(--api-resource-example-document-button-color);
6675
font-size: var(--api-resource-example-document-button-font-size);
6776
font-weight: var(--api-resource-example-document-button-font-weight);
6877
}
6978
70-
api-example-render {
71-
background-color: inherit;
72-
}
73-
7479
json-table,
7580
api-example-render {
7681
overflow: auto;
7782
max-width: 100%;
83+
margin-left: 50px;
7884
}
7985
`;

test/api-resource-example-document.test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,39 @@ describe('ApiResourceExampleDocument', () => {
541541
assert.equal(titles[2].innerText.trim(), 'User 3');
542542
assert.equal(titles[3].innerText.trim(), 'User 4');
543543
});
544+
545+
it('should expand example panel when _handleCollapsePanel is called', async () => {
546+
const payloads = getPayload(element, amf, '/IncludedInline', 'post');
547+
element.examples = payloads;
548+
await aTimeout(100);
549+
550+
const examplePanelNoCollapsed = /** @type HTMLElement */ (element.shadowRoot.querySelector('.collapse'));
551+
assert.isNull(examplePanelNoCollapsed);
552+
const expandIconNoCollapsed = /** @type HTMLElement */ (element.shadowRoot.querySelector('.expand-icon-collapse'));
553+
assert.isNull(expandIconNoCollapsed);
554+
555+
setTimeout(() => element._handleCollapsePanel());
556+
557+
const examplePanelCollapsed = /** @type HTMLElement */ (element.shadowRoot.querySelector('.collapse'));
558+
assert.isDefined(examplePanelCollapsed);
559+
const expandIconCollapsed = /** @type HTMLElement */ (element.shadowRoot.querySelector('.expand-icon-collapse'));
560+
assert.isDefined(expandIconCollapsed);
561+
});
562+
563+
it('should expand example panel on click ', async () => {
564+
const payloads = getPayload(element, amf, '/IncludedInline', 'post');
565+
element.examples = payloads;
566+
await aTimeout(100);
567+
568+
const examplePanel = /** @type HTMLElement */ (element.shadowRoot.querySelector('.renderer'));
569+
examplePanel.click()
570+
await aTimeout(100);
571+
572+
const examplePanelCollapsed = /** @type HTMLElement */ (element.shadowRoot.querySelector('.collapse'));
573+
const expandIconCollapsed = /** @type HTMLElement */ (element.shadowRoot.querySelector('.expand-icon-collapse'));
574+
assert.isDefined(examplePanelCollapsed);
575+
assert.isDefined(expandIconCollapsed);
576+
});
544577
});
545578
});
546579
});

0 commit comments

Comments
 (0)