diff --git a/src/components/api-request.js b/src/components/api-request.js index c08cc984..52eca23b 100644 --- a/src/components/api-request.js +++ b/src/components/api-request.js @@ -6,7 +6,7 @@ import formatXml from 'xml-but-prettier'; import { getI18nText } from '../languages/index.js'; import { schemaInObjectNotation, getTypeInfo, generateExample, isPatternProperty } from '../utils/schema-utils.js'; -import { toMarkdown } from '../utils/common-utils.js'; +import { toMarkdown, handleTabs } from '../utils/common-utils.js'; import './schema-tree.js'; import getRequestFormTable from './request-form-table.js'; import './tag-input.js'; @@ -302,7 +302,7 @@ export default class ApiRequest extends LitElement { } return html` -
${title}${paramLocation === 'path' ? html`*` : ''}
+
${title}${paramLocation === 'path' ? html`*` : ''}
${tableRows} @@ -575,7 +575,7 @@ export default class ApiRequest extends LitElement { return html`
-
+
${getI18nText('operations.request-body')} ${this.request_body.required ? html`*` : ''} ${this.selectedRequestBodyType} @@ -586,12 +586,12 @@ export default class ApiRequest extends LitElement { ${reqBodySchemaHtml || reqBodyDefaultHtml ? html`
-
- - +
+ +
- ${html`
${reqBodySchemaHtml}
`} - ${html`
${reqBodyDefaultHtml}
`} + ${html`
${reqBodySchemaHtml}
`} + ${html`
${reqBodyDefaultHtml}
`}
` : html`${reqBodyFileInputHtml}` } @@ -627,22 +627,26 @@ export default class ApiRequest extends LitElement { ${!hasResponse ? '' : html``}
-
-
-
- - ${!hasResponse ? '' : html` - - ` - } -
+ ${hasResponse + ? html` +
+ + + +
` + : html` +
+ /* nonfunctional button should not be a button element*/ +
${getI18nText('operations.request')}
+
` + }
${this.responseIsBlob ? html` -
+
${this.responseBlobType === 'image' ? html`` : '' @@ -658,14 +662,14 @@ export default class ApiRequest extends LitElement {
` : html` -
+
` } -
+
-
+
`; diff --git a/src/components/api-response.js b/src/components/api-response.js index f5e3ecf9..80b0c16e 100644 --- a/src/components/api-response.js +++ b/src/components/api-response.js @@ -1,7 +1,7 @@ import { LitElement, html, css } from 'lit'; import { unsafeHTML } from 'lit/directives/unsafe-html.js'; import { schemaInObjectNotation, generateExample, getTypeInfo } from '../utils/schema-utils.js'; -import { toMarkdown } from '../utils/common-utils.js'; +import { toMarkdown, handleTabs } from '../utils/common-utils.js'; import { getI18nText } from '../languages/index.js'; import FontStyles from '../styles/font-styles.js'; import FlexStyles from '../styles/flex-styles.js'; @@ -103,7 +103,7 @@ export default class ApiResponse extends LitElement { render() { return html`
-
+
${this.callback === 'true' ? getI18nText('operations.callback-response') : getI18nText('operations.response')}
@@ -159,7 +159,7 @@ export default class ApiResponse extends LitElement { this.headersForEachRespStatus[statusCode] = tempHeaders; this.mimeResponsesForEachStatus[statusCode] = allMimeResp; } - return html`
+ return html`
${Object.keys(this.responses).map((respStatus) => html` ${respStatus === '$$ref' // Swagger-Client parser creates '$$ref' object if JSON references are used to create responses - this should be ignored ? '' @@ -173,7 +173,11 @@ export default class ApiResponse extends LitElement { this.selectedMimeType = undefined; } }}" - aria-current="${this.selectedStatus === respStatus}" + role="tab" + aria-selected="${this.selectedStatus === respStatus}" + aria-controls="status${respStatus}" + tabindex="${this.selectedStatus === respStatus ? '0' : '-1'}" + id="button${respStatus}" class='m-btn small ${this.selectedStatus === respStatus ? 'primary' : ''}' part="btn--resp ${this.selectedStatus === respStatus ? 'btn-fill--resp' : 'btn-outline--resp'} btn-response-status" style='margin: 8px 4px 0 0; text-transform: capitalize'> @@ -184,7 +188,7 @@ export default class ApiResponse extends LitElement {
${Object.keys(this.responses).map((status) => html` -
+
${unsafeHTML(toMarkdown(this.responses[status] && this.responses[status].description || ''))} ${(this.headersForEachRespStatus[status] && this.headersForEachRespStatus[status].length > 0) @@ -196,23 +200,21 @@ export default class ApiResponse extends LitElement { ? '' : html`
-
- - +
+ +
${Object.keys(this.mimeResponsesForEachStatus[status]).length === 1 ? html` ${Object.keys(this.mimeResponsesForEachStatus[status])[0]} ` : html`${this.mimeTypeDropdownTemplate(Object.keys(this.mimeResponsesForEachStatus[status]))}` }
- ${this.activeSchemaTab === 'body' - ? html`
- ${this.mimeExampleTemplate(this.mimeResponsesForEachStatus[status][this.selectedMimeType])} -
` - : html`
- ${this.mimeSchemaTemplate(this.mimeResponsesForEachStatus[status][this.selectedMimeType])} -
` - } + ${html`
+ ${this.mimeExampleTemplate(this.mimeResponsesForEachStatus[status][this.selectedMimeType])} +
`} + ${html`
+ ${this.mimeSchemaTemplate(this.mimeResponsesForEachStatus[status][this.selectedMimeType])} +
`}
` }`) diff --git a/src/styles/tab-styles.js b/src/styles/tab-styles.js index 2efe1c04..a67d1d42 100644 --- a/src/styles/tab-styles.js +++ b/src/styles/tab-styles.js @@ -42,7 +42,8 @@ export default css` color:var(--primary-color); } -.tab-btn:focus-visible { +.tab-btn:focus-visible, +.tab-btn.active:focus-visible { color:var(--secondary-color); } diff --git a/src/templates/code-samples-template.js b/src/templates/code-samples-template.js index 02d353d8..5689e95a 100644 --- a/src/templates/code-samples-template.js +++ b/src/templates/code-samples-template.js @@ -1,5 +1,6 @@ import { html } from 'lit'; import { getI18nText } from '../languages/index.js'; +import { handleTabs } from '../utils/common-utils.js'; /* eslint-disable indent */ export default function codeSamplesTemplate(xCodeSamples) { @@ -17,8 +18,8 @@ export default function codeSamplesTemplate(xCodeSamples) { tabContents.forEach((tabBodyEl) => { tabBodyEl.style.display = (tabBodyEl.dataset.tab === clickedTab ? 'block' : 'none'); }); } }"> -
- ${xCodeSamples.map((v, i) => html``)} +
+ ${xCodeSamples.map((v, i) => html``)}
${xCodeSamples.map((v, i) => { // We skip the first line because it could be there is no padding there, but padding on the next lines which needs to be removed @@ -26,7 +27,7 @@ export default function codeSamplesTemplate(xCodeSamples) { const sanitizedSource = v.source.split('\n').map(s => s.substring(0, paddingToRemove).match(/^\s+$/) ? s.substring(paddingToRemove) : s); const fullSource = sanitizedSource.join('\n'); return html` -
+
`; }) diff --git a/src/utils/common-utils.js b/src/utils/common-utils.js index a55e96c5..7adbb13b 100644 --- a/src/utils/common-utils.js +++ b/src/utils/common-utils.js @@ -188,3 +188,29 @@ export function getSanitizedEmail(emailRaw) { return ''; } + +export function handleTabs(e) { + const b = e.target; + if (b.tagName.toLowerCase() !== 'button') { return; } + const buttons = Array.from(b.parentElement.children); + const i = buttons.indexOf(b); + let newIndex = 0; + switch (e.key) { + case 'ArrowRight': + newIndex = (i + 1) % buttons.length; + break; + case 'ArrowLeft': + newIndex = (i - 1 + buttons.length) % buttons.length; + break; + case 'Home': + newIndex = 0; + break; + case 'End': + newIndex = buttons.length - 1; + break; + default: + return; + } + b.parentElement.children[newIndex].focus(); +} +