From ce5918fc2b7e1fa19f6af77c78084eb8c1fe3239 Mon Sep 17 00:00:00 2001 From: hinzzx Date: Wed, 12 Jul 2023 15:47:41 +0300 Subject: [PATCH 01/11] feat(ui5-switch): add required property --- packages/main/src/Switch.hbs | 1 + packages/main/src/Switch.ts | 17 +++++++++++++++++ packages/main/src/i18n/messagebundle.properties | 3 +++ packages/main/test/pages/Switch.html | 5 +++++ packages/main/test/specs/Switch.spec.js | 13 +++++++++++++ 5 files changed, 39 insertions(+) diff --git a/packages/main/src/Switch.hbs b/packages/main/src/Switch.hbs index 67792aee1a44..42fda02e5117 100644 --- a/packages/main/src/Switch.hbs +++ b/packages/main/src/Switch.hbs @@ -4,6 +4,7 @@ aria-label="{{ariaLabelText}}" aria-checked="{{checked}}" aria-disabled="{{effectiveAriaDisabled}}" + aria-description="{{_ariaDescription}}" @click="{{_onclick}}" @keyup="{{_onkeyup}}" @keydown="{{_onkeydown}}" diff --git a/packages/main/src/Switch.ts b/packages/main/src/Switch.ts index 5bf52da7960b..77e19cb1536a 100644 --- a/packages/main/src/Switch.ts +++ b/packages/main/src/Switch.ts @@ -10,6 +10,7 @@ import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; import type { ClassMap } from "@ui5/webcomponents-base/dist/types.js"; import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js"; +import { SWITCH_ARIA_DESCRIPTION } from "./generated/i18n/i18n-defaults.js"; import "@ui5/webcomponents-icons/dist/accept.js"; import "@ui5/webcomponents-icons/dist/decline.js"; import "@ui5/webcomponents-icons/dist/less.js"; @@ -188,6 +189,18 @@ class Switch extends UI5Element { @property() tooltip!: string; + /** + * Defines whether the component is required. + * + * @type {boolean} + * @name sap.ui.webc.main.Switch.prototype.required + * @defaultvalue false + * @public + * @since 1.16.0 + */ + @property({ type: Boolean }) + required!: boolean; + static i18nBundle: I18nBundle; get sapNextIcon() { @@ -247,6 +260,10 @@ class Switch extends UI5Element { return this.disabled ? undefined : "0"; } + get _ariaDescription() { + return this.required ? Switch.i18nBundle.getText(SWITCH_ARIA_DESCRIPTION) : undefined; + } + get classes(): ClassMap { const hasLabel = this.graphical || this.textOn || this.textOff; diff --git a/packages/main/src/i18n/messagebundle.properties b/packages/main/src/i18n/messagebundle.properties index c101ba86c168..8e7b9e81b514 100644 --- a/packages/main/src/i18n/messagebundle.properties +++ b/packages/main/src/i18n/messagebundle.properties @@ -253,6 +253,9 @@ SEGMENTEDBUTTONITEM_ARIA_DESCRIPTION=Segmented button #XACT: ARIA description for slider handle SLIDER_ARIA_DESCRIPTION=Slider handle +#XACT: ARIA description for required switch +SWITCH_ARIA_DESCRIPTION=Required + #XTXT Table and List "load more" row's text. LOAD_MORE_TEXT=More diff --git a/packages/main/test/pages/Switch.html b/packages/main/test/pages/Switch.html index 59155605f6c2..5af041896ab6 100644 --- a/packages/main/test/pages/Switch.html +++ b/packages/main/test/pages/Switch.html @@ -42,6 +42,11 @@

Default Switch

+

Switch with required attribute

+
+ +
+

Change prevented Switch

diff --git a/packages/main/test/specs/Switch.spec.js b/packages/main/test/specs/Switch.spec.js index 9400c199053d..07cf9e9d006f 100644 --- a/packages/main/test/specs/Switch.spec.js +++ b/packages/main/test/specs/Switch.spec.js @@ -62,4 +62,17 @@ describe("Switch general interaction", async () => { assert.strictEqual(await switchPrevented.getProperty("checked"), currentChecked, "The switch is not checked"); }); + it("required property adds aria-description attribute", async () => { + const switchRoot = await browser.$("#requiredSwitch").shadow$(".ui5-switch-root"); + + let resourceBundleText = null; + + resourceBundleText = await browser.executeAsync(done => { + const switchComponent = document.getElementById("requiredSwitch"); + done(switchComponent.constructor.i18nBundle.getText(window["sap-ui-webcomponents-bundle"].defaultTexts.SWITCH_ARIA_DESCRIPTION)); + }) + + assert.strictEqual(await switchRoot.getAttribute("aria-description"), resourceBundleText, "The aria-description attribute is set"); + }) + }); From 9766896f974899cb1123bd3b09fc7656e8be71b4 Mon Sep 17 00:00:00 2001 From: hinzzx Date: Fri, 14 Jul 2023 17:26:18 +0300 Subject: [PATCH 02/11] feat(ui5-switch): enable form support --- packages/main/src/Switch.hbs | 3 +- packages/main/src/Switch.ts | 60 +++++++++++++++++-- .../main/src/i18n/messagebundle.properties | 3 - packages/main/test/pages/Switch.html | 9 +++ packages/main/test/specs/Switch.spec.js | 14 +---- .../_stories/main/Switch/Switch.stories.ts | 27 ++++++++- 6 files changed, 94 insertions(+), 22 deletions(-) diff --git a/packages/main/src/Switch.hbs b/packages/main/src/Switch.hbs index 42fda02e5117..d227fec52019 100644 --- a/packages/main/src/Switch.hbs +++ b/packages/main/src/Switch.hbs @@ -4,7 +4,7 @@ aria-label="{{ariaLabelText}}" aria-checked="{{checked}}" aria-disabled="{{effectiveAriaDisabled}}" - aria-description="{{_ariaDescription}}" + aria-required="{{required}}" @click="{{_onclick}}" @keyup="{{_onkeyup}}" @keydown="{{_onkeydown}}" @@ -48,4 +48,5 @@
+ diff --git a/packages/main/src/Switch.ts b/packages/main/src/Switch.ts index 77e19cb1536a..07046282f121 100644 --- a/packages/main/src/Switch.ts +++ b/packages/main/src/Switch.ts @@ -2,6 +2,7 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js"; import property from "@ui5/webcomponents-base/dist/decorators/property.js"; import event from "@ui5/webcomponents-base/dist/decorators/event.js"; +import slot from "@ui5/webcomponents-base/dist/decorators/slot.js"; import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js"; @@ -10,10 +11,12 @@ import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; import type { ClassMap } from "@ui5/webcomponents-base/dist/types.js"; import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js"; -import { SWITCH_ARIA_DESCRIPTION } from "./generated/i18n/i18n-defaults.js"; import "@ui5/webcomponents-icons/dist/accept.js"; import "@ui5/webcomponents-icons/dist/decline.js"; import "@ui5/webcomponents-icons/dist/less.js"; +import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js"; +import type FormSupport from "./features/InputElementsFormSupport.js"; +import type { IFormElement } from "./features/InputElementsFormSupport.js"; import Icon from "./Icon.js"; import SwitchDesign from "./types/SwitchDesign.js"; @@ -78,7 +81,7 @@ import switchCss from "./generated/themes/Switch.css.js"; * @event sap.ui.webc.main.Switch#change */ @event("change") -class Switch extends UI5Element { +class Switch extends UI5Element implements IFormElement { /** * Defines the component design. *

@@ -201,8 +204,57 @@ class Switch extends UI5Element { @property({ type: Boolean }) required!: boolean; + /** + * Determines the name with which the component will be submitted in an HTML form. + * + *

+ * Important: For the name property to have effect, you must add the following import to your project: + * import "@ui5/webcomponents/dist/features/InputElementsFormSupport.js"; + * + *

+ * Note: When set, a native input HTML element + * will be created inside the component so that it can be submitted as + * part of an HTML form. Do not use this property unless you need to submit a form. + * + * @type {string} + * @name sap.ui.webc.main.Switch.prototype.name + * @defaultvalue "" + * @public + * @since 1.16.0 + */ + @property() + name!: string; + + /** + * The slot is used to render native input HTML element within Light DOM to enable form submit, when Switch is a part of HTML form. + * + * @type {HTMLElement[]} + * @slot + * @private + * @since 1.16.0 + */ + @slot() + formSupport!: Array; + static i18nBundle: I18nBundle; + onBeforeRendering() { + this._enableFormSupport(); + } + + _enableFormSupport() { + const formSupport = getFeature("FormSupport"); + if (formSupport) { + formSupport.syncNativeHiddenInput(this, (element: IFormElement, nativeInput: HTMLInputElement) => { + const switchComponent = (element as Switch); + nativeInput.checked = !!switchComponent.checked; + nativeInput.disabled = !!switchComponent.disabled || switchComponent.checked; + }); + } else if (this.name) { + console.warn(`In order for the "name" property to have effect, you should also: import "@ui5/webcomponents/dist/features/InputElementsFormSupport.js";`); // eslint-disable-line + } + } + get sapNextIcon() { return this.checked ? "accept" : "less"; } @@ -260,10 +312,6 @@ class Switch extends UI5Element { return this.disabled ? undefined : "0"; } - get _ariaDescription() { - return this.required ? Switch.i18nBundle.getText(SWITCH_ARIA_DESCRIPTION) : undefined; - } - get classes(): ClassMap { const hasLabel = this.graphical || this.textOn || this.textOff; diff --git a/packages/main/src/i18n/messagebundle.properties b/packages/main/src/i18n/messagebundle.properties index 8e7b9e81b514..c101ba86c168 100644 --- a/packages/main/src/i18n/messagebundle.properties +++ b/packages/main/src/i18n/messagebundle.properties @@ -253,9 +253,6 @@ SEGMENTEDBUTTONITEM_ARIA_DESCRIPTION=Segmented button #XACT: ARIA description for slider handle SLIDER_ARIA_DESCRIPTION=Slider handle -#XACT: ARIA description for required switch -SWITCH_ARIA_DESCRIPTION=Required - #XTXT Table and List "load more" row's text. LOAD_MORE_TEXT=More diff --git a/packages/main/test/pages/Switch.html b/packages/main/test/pages/Switch.html index 5af041896ab6..8ba6c44c2dc9 100644 --- a/packages/main/test/pages/Switch.html +++ b/packages/main/test/pages/Switch.html @@ -60,6 +60,15 @@

Graphical Switch

+

Switch in form, required

+
+
+ +
+ Submit Form +
+
+

Custom Switch

diff --git a/packages/main/test/specs/Switch.spec.js b/packages/main/test/specs/Switch.spec.js index 07cf9e9d006f..2152a97f0659 100644 --- a/packages/main/test/specs/Switch.spec.js +++ b/packages/main/test/specs/Switch.spec.js @@ -62,17 +62,9 @@ describe("Switch general interaction", async () => { assert.strictEqual(await switchPrevented.getProperty("checked"), currentChecked, "The switch is not checked"); }); - it("required property adds aria-description attribute", async () => { - const switchRoot = await browser.$("#requiredSwitch").shadow$(".ui5-switch-root"); - - let resourceBundleText = null; - - resourceBundleText = await browser.executeAsync(done => { - const switchComponent = document.getElementById("requiredSwitch"); - done(switchComponent.constructor.i18nBundle.getText(window["sap-ui-webcomponents-bundle"].defaultTexts.SWITCH_ARIA_DESCRIPTION)); - }) - - assert.strictEqual(await switchRoot.getAttribute("aria-description"), resourceBundleText, "The aria-description attribute is set"); + it("The 'required' attribute is propagated properly", async () => { + assert.strictEqual(await browser.$("#requiredSwitch").shadow$(".ui5-switch-root").getAttribute("aria-required"), "true", "The required attribute is set correctly"); + assert.strictEqual(await browser.$("#switchprevented").shadow$(".ui5-switch-root").getAttribute("aria-required"), "false", "The required attribute is set correctly"); }) }); diff --git a/packages/playground/_stories/main/Switch/Switch.stories.ts b/packages/playground/_stories/main/Switch/Switch.stories.ts index 42d52272682f..d44cd143898b 100644 --- a/packages/playground/_stories/main/Switch/Switch.stories.ts +++ b/packages/playground/_stories/main/Switch/Switch.stories.ts @@ -28,6 +28,8 @@ const Template: UI5StoryArgs = (args) => html` { + return html` +
+
+
+ The switch is required, and should be checked in order the form to be submit + ${story()} +
+ Submit +
+
` + } +]; + From bff7f378832b2b23c58b68532e62e456299acd8c Mon Sep 17 00:00:00 2001 From: hinzzx Date: Mon, 17 Jul 2023 23:23:32 +0300 Subject: [PATCH 03/11] feat(ui5-switch): code review changes --- packages/main/test/pages/Switch.html | 27 ++++++++++++++-------- packages/main/test/pages/styles/Switch.css | 6 +++++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/packages/main/test/pages/Switch.html b/packages/main/test/pages/Switch.html index 8ba6c44c2dc9..975dd1594044 100644 --- a/packages/main/test/pages/Switch.html +++ b/packages/main/test/pages/Switch.html @@ -42,11 +42,6 @@

Default Switch

-

Switch with required attribute

-
- -
-

Change prevented Switch

@@ -60,12 +55,17 @@

Graphical Switch

-

Switch in form, required

-
- + +

Switch in Registration form example

+
+ + +
+

Please accept the terms and conditions, in order to proceed.

+
- Submit Form + Submit Form
@@ -97,6 +97,15 @@

sap_horizon