Skip to content

Commit

Permalink
fix(checkbox): disabled state on nested controls
Browse files Browse the repository at this point in the history
  • Loading branch information
bennypowers committed Oct 18, 2023
1 parent 0328c9f commit c2cd390
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 36 deletions.
9 changes: 2 additions & 7 deletions elements/pf-checkbox/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
# Checkbox
Add a description of the component here.

## Usage
Describe how best to use this web component along with best practices.
A **checkbox** is used to select a single item or multiple items, typically to choose elements to perform an action or to reflect a binary setting.

```html
<pf-checkbox>

</pf-checkbox>
<pf-checkbox label="Checkbox"></pf-checkbox>
```
13 changes: 13 additions & 0 deletions elements/pf-checkbox/demo/controlled.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<pf-checkbox label="Parent">
<pf-checkbox label="Child 1"></pf-checkbox>
<pf-checkbox label="Child 2"></pf-checkbox>
<pf-text-input label="Text"></pf-text-input>
</pf-checkbox>
<pf-checkbox label="Sibling"></pf-checkbox>

<script type="module">
import '@patternfly/elements/pf-checkbox/pf-checkbox.js';
import '@patternfly/elements/pf-text-input/pf-text-input.js';
</script>


12 changes: 1 addition & 11 deletions elements/pf-checkbox/pf-checkbox.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

[hidden] { display: none !important; }

::slotted(pf-checkbox) {
#nested::slotted(*) {
margin-inline-start: var(--pf-global--spacer--md, 1rem);
grid-column: -1/1;
}
Expand Down Expand Up @@ -52,13 +52,3 @@ label {
color: var(--pf-c-check__label--Color);
}

.visually-hidden {
position: fixed;
top: 0;
left: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}

70 changes: 52 additions & 18 deletions elements/pf-checkbox/pf-checkbox.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LitElement, html } from 'lit';
import { LitElement, html, type PropertyValues } from 'lit';
import { customElement } from 'lit/decorators/custom-element.js';

import styles from './pf-checkbox.css';
Expand All @@ -13,10 +13,26 @@ export class RestoreEvent extends Event {
}

/**
* Checkbox
* @slot - Place nested (i.e. 'controlled') pf-checkbox elements here
* A **checkbox** is used to select a single item or multiple items, typically to choose elements to perform an action or to reflect a binary setting.
*
* @slot - Place nested (i.e. 'controlled') patternfly form-control elements here
* @slot description - Description text
* @slot body - Body text
* @fires {RestoreEvent} restore - when the form state is restored.
* @cssprop --pf-c-check--GridGap {@default var(--pf-global--spacer--xs, 0.25rem) var(--pf-global--spacer--sm, 0.5rem)}
* @cssprop --pf-c-check__label--disabled--Color {@default var(--pf-global--disabled-color--100, #6a6e73)}
* @cssprop --pf-c-check__label--Color {@default var(--pf-global--Color--100, #151515)}
* @cssprop --pf-c-check__label--FontWeight {@default var(--pf-global--FontWeight--normal, 400)}
* @cssprop --pf-c-check__label--FontSize {@default var(--pf-global--FontSize--md, 1rem)}
* @cssprop --pf-c-check__label--LineHeight {@default var(--pf-global--LineHeight--sm, 1.3)}
* @cssprop --pf-c-check__input--Height {@default var(--pf-c-check__label--FontSize)}
* @cssprop --pf-c-check__input--MarginTop {@default calc(((var(--pf-c-check__label--FontSize) * var(--pf-c-check__label--LineHeight)) - var(--pf-c-check__input--Height)) / 2)}
* @cssprop --pf-c-check__description--FontSize {@default var(--pf-global--FontSize--sm, 0.875rem)}
* @cssprop --pf-c-check__description--Color {@default var(--pf-global--Color--200, #6a6e73)}
* @cssprop --pf-c-check__body--MarginTop {@default var(--pf-global--spacer--sm, 0.5rem)}
* @cssprop --pf-c-check__label-required--MarginLeft {@default var(--pf-global--spacer--xs, 0.25rem)}
* @cssprop --pf-c-check__label-required--FontSize {@default var(--pf-global--FontSize--sm, 0.875rem)}
* @cssprop --pf-c-check__label-required--Color {@default var(--pf-global--danger-color--100)}
*/
@customElement('pf-checkbox')
export class PfCheckbox extends LitElement {
Expand Down Expand Up @@ -51,6 +67,7 @@ export class PfCheckbox extends LitElement {

override willUpdate() {
this.#internals.setFormValue(this.checked ? this.value : null);
this.#setDisabledStateOnNestedControls();
}

override render() {
Expand All @@ -66,7 +83,7 @@ export class PfCheckbox extends LitElement {
.indeterminate="${this.indeterminate}">
<label for="checkbox">${this.label ?? this.#internals.ariaLabel}</label>
<slot id="nested"
@input="${this.#onSlottedCheckboxChange}"
@input="${this.#onSlottedChange}"
?hidden="${emptyNested}"></slot>
<slot id="description" name="description" ?hidden="${emptyDescription}"></slot>
<slot id="body" name="body" ?hidden="${emptyBody}"></slot>
Expand All @@ -88,18 +105,6 @@ export class PfCheckbox extends LitElement {
}
}

setCustomValidity(message: string) {
this.#internals.setValidity({}, message);
}

checkValidity() {
return this.#internals.checkValidity();
}

reportValidity() {
return this.#internals.reportValidity();
}

#onChange(event: Event) {
this.checked = (event.target as HTMLInputElement).checked;
this.#toggleAll(this.checked);
Expand All @@ -108,11 +113,12 @@ export class PfCheckbox extends LitElement {
async #onRestore(event: Event) {
if (event instanceof RestoreEvent && event.element !== this) {
await this.updateComplete;
this.#onSlottedCheckboxChange();
this.#onSlottedChange();
this.#setDisabledStateOnNestedControls();
}
}

#onSlottedCheckboxChange() {
async #onSlottedChange() {
if (this.#batching) {
return;
}
Expand All @@ -128,6 +134,22 @@ export class PfCheckbox extends LitElement {
this.indeterminate = checked && unchecked;
}

async #setDisabledStateOnNestedControls() {
const controls = this.nestedElements?.filter(x => !(x instanceof PfCheckbox)) ?? [];
if (controls.length) {
await Promise.race([
new Promise(r => setTimeout(r, 1000)),
Promise.all(controls.map(x =>
customElements.whenDefined(x.localName)))
]);
for (const control of controls) {
if ('disabled' in control) {
control.disabled = !this.checked;
}
}
}
}

#toggleAll(force: boolean) {
this.#batching = true;
for (const el of this.nestedElements ?? []) {
Expand All @@ -137,6 +159,18 @@ export class PfCheckbox extends LitElement {
}
this.#batching = false;
}

setCustomValidity(message: string) {
this.#internals.setValidity({}, message);
}

checkValidity() {
return this.#internals.checkValidity();
}

reportValidity() {
return this.#internals.reportValidity();
}
}

declare global {
Expand Down

0 comments on commit c2cd390

Please sign in to comment.