Skip to content

Commit

Permalink
feat(ui5-checkbox): add displayOnly mode (#8111)
Browse files Browse the repository at this point in the history
* feat(ui5-checkbox): add displayOnly mode

* chore: import icons

* fix: icon color in dark themes and add more examples
  • Loading branch information
dobrinyonkov committed Jan 16, 2024
1 parent aa5b09b commit c99d0ec
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 23 deletions.
43 changes: 25 additions & 18 deletions packages/main/src/CheckBox.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,37 @@
@click="{{_onclick}}"
@focusout="{{_onfocusout}}"
>

{{#if isDisplayOnly}}
<div class="ui5-checkbox-display-only-icon-inner">
<ui5-icon aria-hidden="true" name={{displayOnlyIcon}} class="ui5-checkbox-display-only-icon"></ui5-icon>
</div>
{{else}}
<div id="{{_id}}-CbBg" class="ui5-checkbox-inner">
{{#if isCompletelyChecked}}
<ui5-icon aria-hidden="true" name="accept" class="ui5-checkbox-icon"></ui5-icon>
{{/if}}

<input
id="{{_id}}-CB"
type='checkbox'
?checked="{{checked}}"
?readonly="{{readonly}}"
?disabled="{{disabled}}"
tabindex="-1"
aria-hidden="true"
data-sap-no-tab-ref
/>
</div>
{{/if}}

<input
id="{{_id}}-CB"
type='checkbox'
?checked="{{checked}}"
?readonly="{{readonly}}"
?disabled="{{disabled}}"
tabindex="-1"
aria-hidden="true"
data-sap-no-tab-ref
/>

{{#if text}}
<ui5-label part="label" id="{{_id}}-label" class="ui5-checkbox-label" wrapping-type="{{wrappingType}}">{{text}}</ui5-label>
{{/if}}
{{#if text}}
<ui5-label part="label" id="{{_id}}-label" class="ui5-checkbox-label" wrapping-type="{{wrappingType}}">{{text}}</ui5-label>
{{/if}}

{{#if hasValueState}}
<span id="{{_id}}-descr" class="ui5-hidden-text">{{valueStateText}}</span>
{{/if}}
{{#if hasValueState}}
<span id="{{_id}}-descr" class="ui5-hidden-text">{{valueStateText}}</span>
{{/if}}

<slot name="formSupport"></slot>
<slot name="formSupport"></slot>
</div>
36 changes: 33 additions & 3 deletions packages/main/src/CheckBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js";
import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js";
import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js";
import "@ui5/webcomponents-icons/dist/accept.js";
import "@ui5/webcomponents-icons/dist/complete.js";
import "@ui5/webcomponents-icons/dist/border.js";
import "@ui5/webcomponents-icons/dist/tri-state.js";
import Icon from "./Icon.js";
import Label from "./Label.js";
import WrappingType from "./types/WrappingType.js";
Expand Down Expand Up @@ -139,6 +142,19 @@ class CheckBox extends UI5Element implements IFormElement {
@property({ type: Boolean })
readonly!: boolean;

/**
* Determines whether the <code>ui5-checkbox</code> is in display only state.
*
* When set to <code>true</code>, the <code>ui5-checkbox</code> is not interactive, not editable, not focusable
* and not in the tab chain. This setting is used for forms in review mode.
*
* <Note:> When the property <code>disabled</code> is set to <code>true</code> this property has no effect.
* @since 1.22.0
* @default false
*/
@property({ type: Boolean })
displayOnly!: boolean;

/**
* Defines whether the component is required.
*
Expand Down Expand Up @@ -346,7 +362,7 @@ class CheckBox extends UI5Element implements IFormElement {
}

canToggle() {
return !(this.disabled || this.readonly);
return !(this.disabled || this.readonly || this.displayOnly);
}

valueStateTextMappings() {
Expand All @@ -370,7 +386,7 @@ class CheckBox extends UI5Element implements IFormElement {
}

get ariaReadonly() {
return this.readonly ? "true" : undefined;
return this.readonly || this.displayOnly ? "true" : undefined;
}

get effectiveAriaDisabled() {
Expand Down Expand Up @@ -405,13 +421,27 @@ class CheckBox extends UI5Element implements IFormElement {

get effectiveTabIndex() {
const tabindex = this.getAttribute("tabindex");
return this.disabled ? undefined : tabindex || "0";
return this.disabled || this.displayOnly ? undefined : tabindex || "0";
}

get isCompletelyChecked() {
return this.checked && !this.indeterminate;
}

get isDisplayOnly() {
return this.displayOnly && !this.disabled;
}

get displayOnlyIcon() {
if (this.isCompletelyChecked) {
return "complete";
}
if (this.checked && this.indeterminate) {
return "tri-state";
}
return "border";
}

static async onDefine() {
CheckBox.i18nBundle = await getI18nBundle("@ui5/webcomponents");
}
Expand Down
19 changes: 18 additions & 1 deletion packages/main/src/themes/CheckBox.css
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@
height: var(--_ui5_checkbox_partially_icon_size);
}

.ui5-checkbox-inner input {
:host input {
-webkit-appearance: none;
visibility: hidden;
width: 0;
Expand Down Expand Up @@ -253,4 +253,21 @@
transform: translate(-50%, -50%);
}

/* Display only mode */
:host([display-only]) {
cursor: default;
}

:host([display-only]) .ui5-checkbox-display-only-icon-inner [ui5-icon] {
color: var(--sapTextColor);
}

:host([display-only]) .ui5-checkbox-display-only-icon-inner {
min-width: var(--_ui5_checkbox_inner_width_height);
max-width: var(--_ui5_checkbox_inner_width_height);
height: var(--_ui5_checkbox_inner_width_height);
max-height: var(--_ui5_checkbox_inner_width_height);
display: flex;
align-items: center;
justify-content: center;
}
7 changes: 6 additions & 1 deletion packages/main/test/pages/CheckBox.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
<ui5-checkbox checked text="Option B"></ui5-checkbox>
<ui5-checkbox text="Option C"></ui5-checkbox>
<ui5-checkbox text="Option D"></ui5-checkbox>
<ui5-checkbox display-only text="Display only"></ui5-checkbox>
<ui5-checkbox display-only checked text="Display only checked"></ui5-checkbox>
<ui5-checkbox display-only checked indeterminate text="Display only partially checked"></ui5-checkbox>
</div>

<br><br>
Expand All @@ -40,6 +43,7 @@
<ui5-title>Change Event Test</ui5-title>
<ui5-checkbox id="cb1" text="Long long long text"></ui5-checkbox>
<ui5-checkbox id="cb2" disabled></ui5-checkbox>
<ui5-checkbox id="displayOnlyCb" display-only></ui5-checkbox>
<ui5-input id="field"></ui5-input>

<br>
Expand Down Expand Up @@ -79,10 +83,11 @@
var input = document.querySelector("#field");
var checkBox1 = document.querySelector("#cb1");
var checkBox2 = document.querySelector("#cb2");
var displayOnlyCb = document.querySelector("#displayOnlyCb");
var cbFormSubmitted = document.querySelector("#cbFormSubmitted");
var counter = 0;

[checkBox1, checkBox2].forEach(function(el) {
[checkBox1, checkBox2, displayOnlyCb].forEach(function(el) {
el.addEventListener("ui5-change", function(event) {
counter += 1;
input.value = counter;
Expand Down
46 changes: 46 additions & 0 deletions packages/main/test/specs/CheckBox.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ describe("CheckBox general interaction", () => {
assert.strictEqual(await field.getProperty("value"), "3", "Change event should not be called any more");
});

it("tests change events not fired when displayOnly", async () => {
const checkBox = await browser.$("#displayOnlyCb");
const field = await browser.$("#field");

await checkBox.click();
await checkBox.keys("Space");
await checkBox.keys("Enter");

assert.strictEqual(await field.getProperty("value"), "3", "Change event should not be called any more");
});

it("tests truncating and wrapping", async () => {
const CHECKBOX_DEFAULT_HEIGHT = 44;
const truncatingCb = await browser.$("#truncatingCb").shadow$(".ui5-checkbox-root");
Expand Down Expand Up @@ -105,4 +116,39 @@ describe("CheckBox general interaction", () => {

assert.strictEqual(await browser.$("#cbFormSubmitted").getValue(), "true", "Form is submitted");
});

it("tests displayOnly mode - checkbox cannot be toggled", async () => {
const checkBox = await browser.$("#displayOnlyCb");
const initialCheck = await checkBox.getProperty("checked");

await checkBox.click();

assert.strictEqual(await checkBox.getProperty("checked"), initialCheck, "Checkbox state should not be changed");
});

it("tests displayOnly mode - checkbox is not focusable", async () => {
const checkBox = await browser.$("#displayOnlyCb");

await checkBox.click();

assert.strictEqual(await checkBox.isFocused(), false, "Checkbox should not be focusable");
});

it("tests displayOnly mode - checkbox is not in the tab chain", async () => {
const checkbox = await browser.$("#displayOnlyCb").shadow$(".ui5-checkbox-root");
assert.strictEqual(await checkbox.getAttribute("tabindex"), null, "Checkbox should not be in the tab chain");
});

it("tests displayOnly mode - displays the correct icon", async () => {
const checkBox = await browser.$("#displayOnlyCb");
const icon = await checkBox.shadow$("ui5-icon");

assert.strictEqual(await icon.getAttribute("name"), "border", "Displays the correct icon for not checked");

await checkBox.setAttribute("checked", "true");
assert.strictEqual(await icon.getAttribute("name"), "complete", "Displays the correct icon for checked");

await checkBox.setAttribute("indeterminate", "true");
assert.strictEqual(await icon.getAttribute("name"), "tri-state", "Displays the correct icon for indeterminate checked");
});
});

0 comments on commit c99d0ec

Please sign in to comment.