From 6830b57831b7be4f63c86d6b67bbba610c2b780d Mon Sep 17 00:00:00 2001 From: ChrisLabattD2L Date: Tue, 12 Nov 2024 09:25:35 -0500 Subject: [PATCH 1/5] Improve the Status Indication A11y Docn --- components/status-indicator/README.md | 3 +++ components/status-indicator/status-indicator.js | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/components/status-indicator/README.md b/components/status-indicator/README.md index cab851c6cd4..04c95d26b33 100644 --- a/components/status-indicator/README.md +++ b/components/status-indicator/README.md @@ -220,3 +220,6 @@ The text label should be kept short; one or two words at most. If more informati ``` + +## Accessibility +Although `aria-description` can be used to provide additional context on the state, it is recommended to provide that context for both sighted and non-sighted users by following the recommendations mentioned in the [Content](#content) section diff --git a/components/status-indicator/status-indicator.js b/components/status-indicator/status-indicator.js index 42c1887ad73..17e53ff7a6b 100644 --- a/components/status-indicator/status-indicator.js +++ b/components/status-indicator/status-indicator.js @@ -17,7 +17,7 @@ class StatusIndicator extends LitElement { reflect: true }, /** - * REQUIRED: The text that is displayed within the status indicator + * ACCESSIBILITY: REQUIRED: The text that is displayed within the status indicator * @type {string} */ text: { From fb66204276bfedd4ae8a5f3d4ab3c6bfb394f460 Mon Sep 17 00:00:00 2001 From: ChrisLabattD2L Date: Fri, 15 Nov 2024 13:46:36 -0500 Subject: [PATCH 2/5] Adding demo controls for Inspiration --- components/alert/alert.js | 11 ++++ components/alert/demo/alert.html | 6 +- components/demo/demo-snippet.js | 105 ++++++++++++++++++++++++++++++- 3 files changed, 117 insertions(+), 5 deletions(-) diff --git a/components/alert/alert.js b/components/alert/alert.js index 01577fb1cfc..2868a7cfae6 100644 --- a/components/alert/alert.js +++ b/components/alert/alert.js @@ -171,6 +171,17 @@ class Alert extends LocalizeCoreElement(RtlMixin(LitElement)) { this.type = 'default'; } + static get demoProperties() { + return { + type: { type: 'select', options: ['default','critical','success','warning'], label: 'Alert Type' }, + subtext: { type: 'text', label: 'Subtext' }, + buttonText: { type: 'text', attribute: 'button-text', label: 'Button Text' }, + hasCloseButton: { type: 'switch', attribute: 'has-close-button', label: 'Has Close Button' }, + noPadding: { type: 'switch', attribute: 'no-padding', label: 'No Padding' } + } + } + + render() { const hasActions = this.buttonText && this.buttonText.length > 0 || this.hasCloseButton; const alertTextClasses = { diff --git a/components/alert/demo/alert.html b/components/alert/demo/alert.html index bdcf280bb19..56db26ac666 100644 --- a/components/alert/demo/alert.html +++ b/components/alert/demo/alert.html @@ -22,7 +22,9 @@

Default

-

Success

+ + + diff --git a/components/demo/demo-snippet.js b/components/demo/demo-snippet.js index 5c86d480bda..6d43234f09d 100644 --- a/components/demo/demo-snippet.js +++ b/components/demo/demo-snippet.js @@ -3,7 +3,11 @@ import '../button/button-subtle.js'; import '../switch/switch.js'; import '../dropdown/dropdown.js'; import '../dropdown/dropdown-content.js'; +import '../inputs/input-date.js'; +import '../inputs/input-text.js'; import { css, html, LitElement } from 'lit'; +import { labelStyles } from '../typography/styles.js'; +import { selectStyles } from '../inputs/input-select-styles.js'; class DemoSnippet extends LitElement { @@ -14,6 +18,7 @@ class DemoSnippet extends LitElement { noPadding: { type: Boolean, reflect: true, attribute: 'no-padding' }, overflowHidden: { type: Boolean, reflect: true, attribute: 'overflow-hidden' }, _code: { type: String }, + _controlProperties: { type: Array }, _fullscreen: { state: true }, _hasSkeleton: { type: Boolean, attribute: false }, _settingsPeek: { state: true }, @@ -22,7 +27,7 @@ class DemoSnippet extends LitElement { } static get styles() { - return css` + return [ labelStyles, selectStyles, css` :host { background-color: white; border: 1px solid var(--d2l-color-tungsten); @@ -106,7 +111,14 @@ class DemoSnippet extends LitElement { :host([code-view-hidden]) d2l-code-view { display: none; } -`; + .d2l-demo-control { + display: block; + padding-top: 0.5rem; + } + .d2l-demo-control-dropdown { + width: 100%; + } + `]; } constructor() { @@ -121,7 +133,9 @@ class DemoSnippet extends LitElement { const skeleton = this._hasSkeleton ? html`` : null; const switches = html`
- ${skeleton}`; + ${skeleton} + ${this._renderControls()} + `; const settings = this.fullWidth && this._fullscreen ? html` @@ -215,6 +229,41 @@ class DemoSnippet extends LitElement { .replace(/=""/g, ''); // replace empty strings for boolean attributes (="") } + _getProperties() { + // Possible improvements: + // - Add more control types + // - Allow grouping things together to split things up more easily on the side bar (using styles) + // - Improve default value support (settings a value in the demo directly doesn't reflect in the control) + + if (!this.shadowRoot) return; + const query = this._isTemplate ? 'slot[name="_demo"]' : 'slot:not([name="_demo"])'; + const nodes = this.shadowRoot.querySelector(query).assignedNodes(); + + this._controlProperties = []; + + const doApply = (nodes) => { + for (let i = 0; i < nodes.length; i++) { + if (nodes[i].nodeType === Node.ELEMENT_NODE) { + if (nodes[i].constructor.properties) { + Object.entries(nodes[i].constructor.demoProperties).forEach(([key, value]) => { + this._controlProperties.push({ + label: value.label || key, + attributeName: value.attribute || key, + type: value.type, + options: value.options, + node: nodes[i] + }); + }); + } + + doApply(nodes[i].children); + } + } + }; + doApply(nodes); + } + + async _handleFullscreenChange(e) { this._fullscreen = e.target.on; this._settingsPeek = this._fullscreen; @@ -234,6 +283,14 @@ class DemoSnippet extends LitElement { this._updateCode(e.target); } + _onControlValueChange(e) { + this._updateDemoAttribute(e.target.controlObject, e.target.value); + } + + _onSwitchControlChange(e) { + this._updateDemoAttribute(e.target.controlObject, e.target.on); + } + _removeImportedDemo() { if (!this.shadowRoot) return; const nodes = this.shadowRoot.querySelector('slot[name="_demo"]').assignedNodes(); @@ -242,6 +299,38 @@ class DemoSnippet extends LitElement { } } + _renderControls() { + if (!this._controlProperties?.length) return; + + return this._controlProperties.map((control) => { + switch (control.type) { + case 'switch': + return html``; + case 'select': + return html` +
+ + +
+ `; + case 'text': + return html` +
+ +
+ `; + case 'date': + return html` +
+ +
+ `; + } + }); + } + _repeat(value, times) { if (!value || !times) return ''; if (!''.repeat) return Array(times).join(value); // for IE11 @@ -273,6 +362,16 @@ class DemoSnippet extends LitElement { this._code = textNode.textContent; this._updateHasSkeleton(); + this._getProperties(); + } + + _updateDemoAttribute(control, value) { + if (value) { + control.node.setAttribute(control.attributeName, value); + } else { + control.node.removeAttribute(control.attributeName); + } + this._code = control.node.outerHTML; } _updateHasSkeleton() { From 9aeddb73566b56466914703c7f806a6aaf8b4203 Mon Sep 17 00:00:00 2001 From: ChrisLabattD2L Date: Fri, 15 Nov 2024 13:48:55 -0500 Subject: [PATCH 3/5] Small fix to prevent error when demoProperties doesn't exist --- components/demo/demo-snippet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/demo/demo-snippet.js b/components/demo/demo-snippet.js index 6d43234f09d..9c4a2a9fe55 100644 --- a/components/demo/demo-snippet.js +++ b/components/demo/demo-snippet.js @@ -244,7 +244,7 @@ class DemoSnippet extends LitElement { const doApply = (nodes) => { for (let i = 0; i < nodes.length; i++) { if (nodes[i].nodeType === Node.ELEMENT_NODE) { - if (nodes[i].constructor.properties) { + if (nodes[i].constructor.demoProperties) { Object.entries(nodes[i].constructor.demoProperties).forEach(([key, value]) => { this._controlProperties.push({ label: value.label || key, From 016438384d46caacd6a9594214d139ec04a640fb Mon Sep 17 00:00:00 2001 From: ChrisLabattD2L Date: Fri, 15 Nov 2024 13:53:09 -0500 Subject: [PATCH 4/5] Lint Fixes --- components/demo/demo-snippet.js | 1 - 1 file changed, 1 deletion(-) diff --git a/components/demo/demo-snippet.js b/components/demo/demo-snippet.js index 9c4a2a9fe55..0860fa37a66 100644 --- a/components/demo/demo-snippet.js +++ b/components/demo/demo-snippet.js @@ -263,7 +263,6 @@ class DemoSnippet extends LitElement { doApply(nodes); } - async _handleFullscreenChange(e) { this._fullscreen = e.target.on; this._settingsPeek = this._fullscreen; From a7806a8b02b995beeb066545940c100af51f1c40 Mon Sep 17 00:00:00 2001 From: ChrisLabattD2L Date: Fri, 15 Nov 2024 14:05:50 -0500 Subject: [PATCH 5/5] forgot to push other lint fix --- components/alert/alert.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/alert/alert.js b/components/alert/alert.js index 2868a7cfae6..2132b743ccf 100644 --- a/components/alert/alert.js +++ b/components/alert/alert.js @@ -173,15 +173,14 @@ class Alert extends LocalizeCoreElement(RtlMixin(LitElement)) { static get demoProperties() { return { - type: { type: 'select', options: ['default','critical','success','warning'], label: 'Alert Type' }, + type: { type: 'select', options: ['default', 'critical', 'success', 'warning'], label: 'Alert Type' }, subtext: { type: 'text', label: 'Subtext' }, buttonText: { type: 'text', attribute: 'button-text', label: 'Button Text' }, hasCloseButton: { type: 'switch', attribute: 'has-close-button', label: 'Has Close Button' }, noPadding: { type: 'switch', attribute: 'no-padding', label: 'No Padding' } - } + }; } - render() { const hasActions = this.buttonText && this.buttonText.length > 0 || this.hasCloseButton; const alertTextClasses = {