From 17b13615b1c85998ca55f2b3853aeea9c80d9f29 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Sun, 23 Feb 2025 23:31:06 +0530 Subject: [PATCH 01/85] chore: pf-search-input component created --- elements/package.json | 1 + elements/pf-search-input/README.md | 11 ++ .../pf-search-input/demo/pf-search-input.html | 12 ++ .../pf-search-input/docs/pf-search-input.md | 17 ++ elements/pf-search-input/pf-search-input.css | 3 + elements/pf-search-input/pf-search-input.ts | 157 ++++++++++++++++++ .../test/pf-search-input.e2e.ts | 25 +++ .../test/pf-search-input.spec.ts | 21 +++ 8 files changed, 247 insertions(+) create mode 100644 elements/pf-search-input/README.md create mode 100644 elements/pf-search-input/demo/pf-search-input.html create mode 100644 elements/pf-search-input/docs/pf-search-input.md create mode 100644 elements/pf-search-input/pf-search-input.css create mode 100644 elements/pf-search-input/pf-search-input.ts create mode 100644 elements/pf-search-input/test/pf-search-input.e2e.ts create mode 100644 elements/pf-search-input/test/pf-search-input.spec.ts diff --git a/elements/package.json b/elements/package.json index 4b159d1d9c..3538d376d0 100644 --- a/elements/package.json +++ b/elements/package.json @@ -45,6 +45,7 @@ "./pf-progress-stepper/pf-progress-step.js": "./pf-progress-stepper/pf-progress-step.js", "./pf-progress-stepper/pf-progress-stepper.js": "./pf-progress-stepper/pf-progress-stepper.js", "./pf-progress/pf-progress.js": "./pf-progress/pf-progress.js", + "./pf-search-input/pf-search-input.js": "./pf-search-input/pf-search-input.js", "./pf-spinner/pf-spinner.js": "./pf-spinner/pf-spinner.js", "./pf-switch/pf-switch.js": "./pf-switch/pf-switch.js", "./pf-table/pf-table.js": "./pf-table/pf-table.js", diff --git a/elements/pf-search-input/README.md b/elements/pf-search-input/README.md new file mode 100644 index 0000000000..f7e06c1c24 --- /dev/null +++ b/elements/pf-search-input/README.md @@ -0,0 +1,11 @@ +# Search Input +Add a description of the component here. + +## Usage +Describe how best to use this web component along with best practices. + +```html + + + +``` diff --git a/elements/pf-search-input/demo/pf-search-input.html b/elements/pf-search-input/demo/pf-search-input.html new file mode 100644 index 0000000000..68136eb3cb --- /dev/null +++ b/elements/pf-search-input/demo/pf-search-input.html @@ -0,0 +1,12 @@ + + + + + + diff --git a/elements/pf-search-input/docs/pf-search-input.md b/elements/pf-search-input/docs/pf-search-input.md new file mode 100644 index 0000000000..1945440caa --- /dev/null +++ b/elements/pf-search-input/docs/pf-search-input.md @@ -0,0 +1,17 @@ +{% renderOverview %} + +{% endrenderOverview %} + +{% band header="Usage" %}{% endband %} + +{% renderSlots %}{% endrenderSlots %} + +{% renderAttributes %}{% endrenderAttributes %} + +{% renderMethods %}{% endrenderMethods %} + +{% renderEvents %}{% endrenderEvents %} + +{% renderCssCustomProperties %}{% endrenderCssCustomProperties %} + +{% renderCssParts %}{% endrenderCssParts %} diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css new file mode 100644 index 0000000000..5d4e87f30f --- /dev/null +++ b/elements/pf-search-input/pf-search-input.css @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts new file mode 100644 index 0000000000..794217b6f1 --- /dev/null +++ b/elements/pf-search-input/pf-search-input.ts @@ -0,0 +1,157 @@ +import { LitElement, html, type TemplateResult } from 'lit'; +import { customElement } from 'lit/decorators/custom-element.js'; +import { ComboboxController } from '@patternfly/pfe-core/controllers/combobox-controller.js'; +import { query } from 'lit/decorators/query.js'; +import { property } from 'lit/decorators/property.js'; +import { observes } from '@patternfly/pfe-core/decorators/observes.js'; +import { + FloatingDOMController, + type Placement, +} from '@patternfly/pfe-core/controllers/floating-dom-controller.js'; +import '@patternfly/elements/pf-text-input/pf-text-input.js'; + +import styles from './pf-search-input.css'; + +/** + * Search Input + * @slot - Place element content here + */ +@customElement('pf-search-input') +export class PfSearchInput extends LitElement { + static readonly styles: CSSStyleSheet[] = [styles]; + + @property({ type: Boolean, reflect: true }) expanded = false; + @property({ reflect: true }) position: Placement = 'bottom'; + @property({ attribute: 'enable-flip', type: Boolean }) enableFlip = false; + + @query('#listbox') listbox!: HTMLElement; + @query('#button') button!: HTMLButtonElement; + @query('#combobox') combobox!: HTMLInputElement; + @query('#placeholder') placeholder!: HTMLOptionElement; + @query('#listbox-container') private _listboxContainer?: HTMLElement; + + + #float = new FloatingDOMController(this, { content: () => this._listboxContainer }); + + + static template: TemplateResult<1> = html` + `; + + controller: ComboboxController = ComboboxController.of(this, { + multi: false, + getItems: () => this.options, + isItem: item => item instanceof HTMLOptionElement, + getFallbackLabel: () => 'options', + getListboxElement: () => this.listbox ?? null, + getToggleButton: () => this.button ?? null, + getComboboxInput: () => this.combobox ?? null, + isExpanded: () => this.expanded, + requestShowListbox: () => void (this.expanded ||= true), + requestHideListbox: () => void (this.expanded &&= false), + setItemActive: (item, active) => item.classList.toggle('active', active), + setItemSelected: (item, selected) => item.selected = selected, + }); + + + /** List of options */ + get options(): HTMLOptionElement[] { + return [ + ...new Set([ + this.placeholder, + ...this.querySelectorAll('option'), + ...this.renderRoot.querySelectorAll('option'), + ]), + ].filter(x => !!x); + } + + get selected(): HTMLOptionElement[] { + return this.options.filter(x => x.selected); + } + + get activeOption(): HTMLOptionElement | undefined { + return this.options.find(x => x.classList.contains('active')); + } + + + render(): TemplateResult<1> { + return html` + + +
+ + + + + + + + + + + +
+ `; + } + + @observes('expanded') + private async expandedChanged(old: boolean, expanded: boolean) { + if (this.dispatchEvent(new Event(this.expanded ? 'close' : 'open'))) { + if (expanded) { + this.#doExpand(); + } else { + this.#doCollapse(); + } + } + } + + async #doExpand() { + try { + await this.#float.show({ placement: this.position || 'bottom', flip: !!this.enableFlip }); + return true; + } catch { + return false; + } + } + + async #doCollapse() { + try { + await this.#float.hide(); + return true; + } catch { + return false; + } + } + + /** + * Opens the dropdown + */ + async show(): Promise { + this.expanded = true; + await this.updateComplete; + } + + /** + * Closes listbox + */ + async hide(): Promise { + this.expanded = false; + await this.updateComplete; + } + + /** + * toggles popup based on current state + */ + async toggle(): Promise { + if (this.expanded) { + await this.hide(); + } else { + await this.show(); + } + } +} + +declare global { + interface HTMLElementTagNameMap { + 'pf-search-input': PfSearchInput; + } +} diff --git a/elements/pf-search-input/test/pf-search-input.e2e.ts b/elements/pf-search-input/test/pf-search-input.e2e.ts new file mode 100644 index 0000000000..b1d9dbb21a --- /dev/null +++ b/elements/pf-search-input/test/pf-search-input.e2e.ts @@ -0,0 +1,25 @@ +import { test } from '@playwright/test'; +import { PfeDemoPage } from '@patternfly/pfe-tools/test/playwright/PfeDemoPage.js'; +import { SSRPage } from '@patternfly/pfe-tools/test/playwright/SSRPage.js'; + +const tagName = 'pf-search-input'; + +test.describe(tagName, () => { + test('snapshot', async ({ page }) => { + const componentPage = new PfeDemoPage(page, tagName); + await componentPage.navigate(); + await componentPage.snapshot(); + }); + + test('ssr', async ({ browser }) => { + const fixture = new SSRPage({ + tagName, + browser, + demoDir: new URL('../demo/', import.meta.url), + importSpecifiers: [ + `@patternfly/elements/${tagName}/${tagName}.js`, + ], + }); + await fixture.snapshots(); + }); +}); diff --git a/elements/pf-search-input/test/pf-search-input.spec.ts b/elements/pf-search-input/test/pf-search-input.spec.ts new file mode 100644 index 0000000000..02aa8097cc --- /dev/null +++ b/elements/pf-search-input/test/pf-search-input.spec.ts @@ -0,0 +1,21 @@ +import { expect, html } from '@open-wc/testing'; +import { createFixture } from '@patternfly/pfe-tools/test/create-fixture.js'; +import { PfSearchInput } from '@patternfly/elements/pf-search-input/pf-search-input.js'; + +describe('', function() { + describe('simply instantiating', function() { + let element: PfSearchInput; + it('imperatively instantiates', function() { + expect(document.createElement('pf-search-input')).to.be.an.instanceof(PfSearchInput); + }); + + it('should upgrade', async function() { + element = await createFixture(html``); + const klass = customElements.get('pf-search-input'); + expect(element) + .to.be.an.instanceOf(klass) + .and + .to.be.an.instanceOf(PfSearchInput); + }); + }); +}); From 03d0269fc5dec4ed598990e32c44dcd446c2bd09 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Mon, 24 Feb 2025 00:42:37 +0530 Subject: [PATCH 02/85] chore: search input updated --- .../demo/pf-search-input-autocomplete.html | 12 +++ elements/pf-search-input/pf-search-input.ts | 76 ++++++++++++++----- 2 files changed, 68 insertions(+), 20 deletions(-) create mode 100644 elements/pf-search-input/demo/pf-search-input-autocomplete.html diff --git a/elements/pf-search-input/demo/pf-search-input-autocomplete.html b/elements/pf-search-input/demo/pf-search-input-autocomplete.html new file mode 100644 index 0000000000..68136eb3cb --- /dev/null +++ b/elements/pf-search-input/demo/pf-search-input-autocomplete.html @@ -0,0 +1,12 @@ + + + + + + diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 794217b6f1..a337de0c6f 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -9,7 +9,8 @@ import { type Placement, } from '@patternfly/pfe-core/controllers/floating-dom-controller.js'; import '@patternfly/elements/pf-text-input/pf-text-input.js'; - +import { arraysAreEquivalent } from '@patternfly/pfe-core/functions/arraysAreEquivalent.js'; +import '@patternfly/elements/pf-icon/pf-icon.js'; import styles from './pf-search-input.css'; /** @@ -34,16 +35,16 @@ export class PfSearchInput extends LitElement { #float = new FloatingDOMController(this, { content: () => this._listboxContainer }); - static template: TemplateResult<1> = html` - `; + // static template: TemplateResult<1> = html` + // `; - controller: ComboboxController = ComboboxController.of(this, { + #combobox: ComboboxController = ComboboxController.of(this, { multi: false, getItems: () => this.options, isItem: item => item instanceof HTMLOptionElement, getFallbackLabel: () => 'options', getListboxElement: () => this.listbox ?? null, - getToggleButton: () => this.button ?? null, + getToggleButton: () => this.combobox ?? null, getComboboxInput: () => this.combobox ?? null, isExpanded: () => this.expanded, requestShowListbox: () => void (this.expanded ||= true), @@ -52,6 +53,15 @@ export class PfSearchInput extends LitElement { setItemSelected: (item, selected) => item.selected = selected, }); + /** + * Single select option value for single select menus, + * or array of select option values for multi select. + */ + @property({ hasChanged: (a, b) => !arraysAreEquivalent(a, b) }) + set selected(selected: any) { + const list = Array.isArray(selected) ? selected : [selected]; + this.#combobox.selected = list; + } /** List of options */ get options(): HTMLOptionElement[] { @@ -72,23 +82,49 @@ export class PfSearchInput extends LitElement { return this.options.find(x => x.classList.contains('active')); } - + // render(): TemplateResult<1> { return html` - - -
- - - - - - - - - - - + + + + + + + + + + + + + +
+
+ + + + + + + + + +
`; } From d567bf5fce6f01f1bf31f86f0bcc9929177824ef Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Wed, 19 Mar 2025 19:21:42 +0530 Subject: [PATCH 03/85] chore: search input option added --- elements/package.json | 1 + .../pf-search-input/demo/pf-search-input.html | 7 +- .../pf-search-input-option.css | 3 + .../pf-search-input/pf-search-input-option.ts | 115 ++++++++++++++++++ elements/pf-search-input/pf-search-input.ts | 109 ++++++++++++----- 5 files changed, 205 insertions(+), 30 deletions(-) create mode 100644 elements/pf-search-input/pf-search-input-option.css create mode 100644 elements/pf-search-input/pf-search-input-option.ts diff --git a/elements/package.json b/elements/package.json index 3538d376d0..62a7846663 100644 --- a/elements/package.json +++ b/elements/package.json @@ -46,6 +46,7 @@ "./pf-progress-stepper/pf-progress-stepper.js": "./pf-progress-stepper/pf-progress-stepper.js", "./pf-progress/pf-progress.js": "./pf-progress/pf-progress.js", "./pf-search-input/pf-search-input.js": "./pf-search-input/pf-search-input.js", + "./pf-search-input/pf-search-input-option.js":"./pf-search-input/pf-search-input-option.js", "./pf-spinner/pf-spinner.js": "./pf-spinner/pf-spinner.js", "./pf-switch/pf-switch.js": "./pf-switch/pf-switch.js", "./pf-table/pf-table.js": "./pf-table/pf-table.js", diff --git a/elements/pf-search-input/demo/pf-search-input.html b/elements/pf-search-input/demo/pf-search-input.html index 68136eb3cb..d88a8eed2e 100644 --- a/elements/pf-search-input/demo/pf-search-input.html +++ b/elements/pf-search-input/demo/pf-search-input.html @@ -1,4 +1,9 @@ - + + New Jersey + New York + New Mexico + North Carolina + diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index 3f542d9ec3..869b4e40ce 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -258,14 +258,15 @@ text-align: left; border-radius: 0; flex: 1 0 auto; - min-height: 44px; - min-width: 44px; } #toggle-input { justify-content: space-between; padding: var(--pf-global--spacer--xs, 0.25rem) var(--pf-global--spacer--sm, 0.5rem); padding-left: 40px; + width: 90%; + box-sizing: border-box; + max-height: 36px; } .disabled #toggle-input { @@ -277,8 +278,17 @@ background-color: transparent; justify-content: flex-end; padding: var(--pf-global--spacer--sm, 0.5rem); + max-height: 36px; + max-width: 36px; + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: center; + position: relative; + top: 3px; } + #toggle-button:focus:before { border-bottom-color: var(--pf-c-select__toggle--focus--before--BorderBottomColor); border-bottom-width: var(--pf-c-select__toggle--focus--before--BorderBottomWidth); @@ -305,13 +315,6 @@ pf-badge { padding: 0; } -#toggle svg { - width: 1em; - height: 1em; - flex: 0 0 auto; - margin-inline-start: 1em; -} - #description { display: block; } @@ -381,9 +384,9 @@ pf-badge { div.search-icon{ position: absolute; - top: 50%; - left: 0; - transform: translateY(-50%); - display: flex; - align-items: center; + top: 50%; + left: 1rem; + transform: translateY(-50%); + display: flex; + align-items: center; } \ No newline at end of file From a332552157721afb7dbd38df6a79e38f15ee5b93 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Thu, 27 Mar 2025 01:51:23 +0530 Subject: [PATCH 07/85] chore: close button functionality implemented --- elements/pf-search-input/pf-search-input.css | 13 ++--- elements/pf-search-input/pf-search-input.ts | 53 +++++++++++++------- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index 869b4e40ce..6880c10275 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -224,7 +224,7 @@ } #toggle, -#toggle-button, +/* #toggle-button, */ #toggle-input { display: flex; align-items: center; @@ -251,8 +251,9 @@ border-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; } -#toggle-input, -#toggle-button { + +/* #toggle-button, */ +#toggle-input { background: transparent; border: none; text-align: left; @@ -273,7 +274,7 @@ pointer-events: none; } -#toggle-button { +#close-button { color: currentColor; background-color: transparent; justify-content: flex-end; @@ -294,9 +295,9 @@ border-bottom-width: var(--pf-c-select__toggle--focus--before--BorderBottomWidth); } -#outer.typeahead #toggle-button { +/* #outer.typeahead #toggle-button { flex: 0 0 auto; -} +} */ #toggle-badge { flex: 1 0 auto; diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 02812d472e..cadf0aefb3 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -148,9 +148,11 @@ export class PfSearchInput extends LitElement { const hideLightDomItems = !ComboboxController.supportsCrossRootActiveDescendant; return html` -
+
@@ -167,11 +169,19 @@ export class PfSearchInput extends LitElement {
- - - + + + - - + +
-
+
- ${this.#combobox.renderItemsToShadowRoot()}
@@ -288,6 +299,14 @@ export class PfSearchInput extends LitElement { await this.show(); } } + + async #OnClose(){ + if (this.expanded) { + await this.hide(); + } + this.value = ""; + this._toggleInput!.value = this.value; + } } declare global { From e8f5bfba08d77c503a59ee4914087180d4cc3b99 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Thu, 27 Mar 2025 02:15:40 +0530 Subject: [PATCH 08/85] chore: CSS variables updated --- elements/pf-search-input/pf-search-input.css | 322 +++++++++---------- 1 file changed, 151 insertions(+), 171 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index 6880c10275..0808249b6c 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -5,162 +5,152 @@ color: var(--pf-global--Color--100, #151515); --_pf-option-checkboxes-display: none; --_pf-option-svg-display: block; - --pf-c-select__toggle--PaddingTop: var(--pf-global--spacer--form-element, 0.375rem); - --pf-c-select__toggle--PaddingRight: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__toggle--PaddingBottom: var(--pf-global--spacer--form-element, 0.375rem); - --pf-c-select__toggle--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__toggle--MinWidth: var(--pf-global--target-size--MinWidth, 44px); - --pf-c-select__toggle--FontSize: var(--pf-global--FontSize--md, 1rem); - --pf-c-select__toggle--FontWeight: var(--pf-global--FontWeight--normal, 400); - --pf-c-select__toggle--LineHeight: var(--pf-global--LineHeight--md, 1.5); - --pf-c-select__toggle--BackgroundColor: var(--pf-global--BackgroundColor--100, #fff); - --pf-c-select__toggle--before--BorderTopWidth: var(--pf-global--BorderWidth--sm, 1px); - --pf-c-select__toggle--before--BorderRightWidth: var(--pf-global--BorderWidth--sm, 1px); - --pf-c-select__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--sm, 1px); - --pf-c-select__toggle--before--BorderLeftWidth: var(--pf-global--BorderWidth--sm, 1px); - --pf-c-select__toggle--before--BorderWidth: initial; - --pf-c-select__toggle--before--BorderTopColor: var(--pf-global--BorderColor--300, #f0f0f0); - --pf-c-select__toggle--before--BorderRightColor: var(--pf-global--BorderColor--300, #f0f0f0); - --pf-c-select__toggle--before--BorderBottomColor: var(--pf-global--BorderColor--200, #8a8d90); - --pf-c-select__toggle--before--BorderLeftColor: var(--pf-global--BorderColor--300, #f0f0f0); - --pf-c-select__toggle--Color: var(--pf-global--Color--100, #151515); - --pf-c-select__toggle--hover--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); - --pf-c-select__toggle--focus--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); - --pf-c-select__toggle--focus--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); - --pf-c-select__toggle--active--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); - --pf-c-select__toggle--active--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); - --pf-c-select__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); - --pf-c-select__toggle--m-expanded--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); - --pf-c-select__toggle--disabled--BackgroundColor: var(--pf-global--disabled-color--300, #f0f0f0); - --pf-c-select__toggle--m-plain--before--BorderColor: transparent; - --pf-c-select__toggle--m-placeholder--Color: transparent; - --pf-c-select--m-invalid__toggle--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); - --pf-c-select--m-invalid__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); - --pf-c-select--m-invalid__toggle--hover--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); - --pf-c-select--m-invalid__toggle--focus--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); - --pf-c-select--m-invalid__toggle--active--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); - --pf-c-select--m-invalid__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); - --pf-c-select--m-invalid__toggle-status-icon--Color: var(--pf-global--danger-color--100, #c9190b); - --pf-c-select--m-success__toggle--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); - --pf-c-select--m-success__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); - --pf-c-select--m-success__toggle--hover--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); - --pf-c-select--m-success__toggle--focus--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); - --pf-c-select--m-success__toggle--active--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); - --pf-c-select--m-success__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); - --pf-c-select--m-success__toggle-status-icon--Color: var(--pf-global--success-color--100, #3e8635); - --pf-c-select--m-warning__toggle--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); - --pf-c-select--m-warning__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); - --pf-c-select--m-warning__toggle--hover--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); - --pf-c-select--m-warning__toggle--focus--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); - --pf-c-select--m-warning__toggle--active--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); - --pf-c-select--m-warning__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); - --pf-c-select--m-warning__toggle-status-icon--Color: var(--pf-global--warning-color--100, #f0ab00); - --pf-c-select__toggle-wrapper--not-last-child--MarginRight: var(--pf-global--spacer--xs, 0.25rem); - --pf-c-select__toggle-wrapper--MaxWidth: calc(100% - var(--pf-global--spacer--lg, 1.5rem)); - --pf-c-select__toggle-wrapper--c-chip-group--MarginTop: 0.3125rem; - --pf-c-select__toggle-wrapper--c-chip-group--MarginBottom: 0.3125rem; - --pf-c-select__toggle-typeahead--FlexBasis: 10em; - --pf-c-select__toggle-typeahead--BackgroundColor: transparent; - --pf-c-select__toggle-typeahead--BorderTop: var(--pf-global--BorderWidth--sm, 1px) solid transparent; - --pf-c-select__toggle-typeahead--BorderRight: none; - --pf-c-select__toggle-typeahead--BorderLeft: none; - --pf-c-select__toggle-typeahead--MinWidth: 7.5rem; - --pf-c-select__toggle-typeahead--focus--PaddingBottom: calc(var(--pf-global--spacer--form-element, 0.375rem) - var(--pf-global--BorderWidth--md)); - --pf-c-select__toggle--m-placeholder__toggle-text--Color: var(--pf-global--Color--dark-200, #6a6e73); - --pf-c-select__toggle-icon--toggle-text--MarginLeft: var(--pf-global--spacer--xs, 0.25rem); - --pf-c-select__toggle-badge--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__toggle-status-icon--MarginLeft: var(--pf-global--spacer--xs, 0.25rem); - --pf-c-select__toggle-status-icon--Color: var(--pf-global--Color--100, #151515); - --pf-c-select__toggle-arrow--MarginLeft: var(--pf-global--spacer--md, 1rem); - --pf-c-select__toggle-arrow--MarginRight: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__toggle-arrow--with-clear--MarginLeft: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__toggle-arrow--m-top--m-expanded__toggle-arrow--Rotate: 180deg; - --pf-c-select--m-plain__toggle-arrow--Color: var(--pf-global--Color--200, #6a6e73); - --pf-c-select--m-plain--hover__toggle-arrow--Color: var(--pf-global--Color--100, #151515); - --pf-c-select__toggle-clear--PaddingRight: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__toggle-clear--PaddingLeft: var(--pf-global--spacer--md, 1rem); - --pf-c-select__toggle-clear--toggle-button--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__toggle-button--Color: var(--pf-global--Color--100, #151515); - --pf-c-select__menu--BackgroundColor: var(--pf-global--BackgroundColor--light-100, #fff); - --pf-c-select__menu--BoxShadow: var(--pf-global--BoxShadow--md, 0 0.25rem 0.5rem 0rem rgba(3, 3, 3, 0.12), 0 0 0.25rem 0 rgba(3, 3, 3, 0.06)); - --pf-c-select__menu--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__menu--PaddingBottom: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__menu--Top: calc(100% + var(--pf-global--spacer--xs, 0.25rem)); - --pf-c-select__menu--ZIndex: var(--pf-global--ZIndex--sm, 200); - --pf-c-select__menu--Width: auto; - --pf-c-select__menu--MinWidth: 100%; - --pf-c-select__menu--m-top--TranslateY: calc(-100% - var(--pf-global--spacer--xs, 0.25rem)); - --pf-c-select__list-item--m-loading--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__menu-item--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__menu-item--PaddingRight: var(--pf-global--spacer--md, 1rem); - --pf-c-select__menu-item--m-selected--PaddingRight: var(--pf-global--spacer--2xl, 3rem); - --pf-c-select__menu-item--PaddingBottom: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__menu-item--PaddingLeft: var(--pf-global--spacer--md, 1rem); - --pf-c-select__menu-item--FontSize: var(--pf-global--FontSize--md, 1rem); - --pf-c-select__menu-item--FontWeight: var(--pf-global--FontWeight--normal, 400); - --pf-c-select__menu-item--LineHeight: var(--pf-global--LineHeight--md, 1.5); - --pf-c-select__menu-item--Color: var(--pf-global--Color--dark-100, #151515); - --pf-c-select__menu-item--disabled--Color: var(--pf-global--Color--dark-200, #6a6e73); - --pf-c-select__menu-item--Width: 100%; - --pf-c-select__menu-item--hover--BackgroundColor: var(--pf-global--BackgroundColor--light-300, #f0f0f0); - --pf-c-select__menu-item--focus--BackgroundColor: var(--pf-global--BackgroundColor--light-300, #f0f0f0); - --pf-c-select__menu-item--disabled--BackgroundColor: transparent; - --pf-c-select__menu-item--m-link--Width: auto; - --pf-c-select__menu-item--m-link--hover--BackgroundColor: transparent; - --pf-c-select__menu-item--m-link--focus--BackgroundColor: transparent; - --pf-c-select__menu-item--m-action--Color: var(--pf-global--Color--200, #6a6e73); - --pf-c-select__menu-item--m-action--hover--Color: var(--pf-global--Color--100, #151515); - --pf-c-select__menu-item--m-action--focus--Color: var(--pf-global--Color--100, #151515); - --pf-c-select__menu-item--m-action--disabled--Color: var(--pf-global--disabled-color--200, #d2d2d2); - --pf-c-select__menu-item--m-action--Width: auto; - --pf-c-select__menu-item--m-action--FontSize: var(--pf-global--icon--FontSize--sm, 0.625rem); - --pf-c-select__menu-item--m-action--hover--BackgroundColor: transparent; - --pf-c-select__menu-item--m-action--focus--BackgroundColor: transparent; - --pf-c-select__menu-item--hover__menu-item--m-action--Color: var(--pf-global--Color--200, #6a6e73); - --pf-c-select__menu-item--m-favorite-action--Color: var(--pf-global--Color--200, #6a6e73); - --pf-c-select__menu-item--m-favorite-action--hover--Color: var(--pf-global--Color--100, #151515); - --pf-c-select__menu-item--m-favorite-action--focus--Color: var(--pf-global--Color--100, #151515); - --pf-c-select__menu-wrapper--m-favorite__menu-item--m-favorite-action--Color: var(--pf-global--palette--gold-400, #f0ab00); - --pf-c-select__menu-wrapper--m-favorite__menu-item--m-favorite-action--hover--Color: var(--pf-global--palette--gold-500, #c58c00); - --pf-c-select__menu-wrapper--m-favorite__menu-item--m-favorite-action--focus--Color: var(--pf-global--palette--gold-500, #c58c00); - --pf-c-select__menu-item--m-load--Color: var(--pf-global--link--Color, #06c); - --pf-c-select__menu-item-icon--Color: var(--pf-global--active-color--100, #06c); - --pf-c-select__menu-item-icon--FontSize: var(--pf-global--icon--FontSize--sm, 0.625rem); - --pf-c-select__menu-item-icon--Right: var(--pf-global--spacer--md, 1rem); - --pf-c-select__menu-item-icon--Top: 50%; - --pf-c-select__menu-item-icon--TranslateY: -50%; - --pf-c-select__menu-item-action-icon--MinHeight: calc(var(--pf-c-select__menu-item--FontSize) * var(--pf-c-select__menu-item--LineHeight)); - --pf-c-select__menu-item--match--FontWeight: var(--pf-global--FontWeight--bold, 700); - --pf-c-select__menu-search--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__menu-search--PaddingRight: var(--pf-c-select__menu-item--PaddingRight); - --pf-c-select__menu-search--PaddingBottom: var(--pf-global--spacer--md, 1rem); - --pf-c-select__menu-search--PaddingLeft: var(--pf-c-select__menu-item--PaddingLeft); - --pf-c-select__menu-group--menu-group--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__menu-group-title--PaddingTop: var(--pf-c-select__menu-item--PaddingTop); - --pf-c-select__menu-group-title--PaddingRight: var(--pf-c-select__menu-item--PaddingRight); - --pf-c-select__menu-group-title--PaddingBottom: var(--pf-c-select__menu-item--PaddingBottom); - --pf-c-select__menu-group-title--PaddingLeft: var(--pf-c-select__menu-item--PaddingLeft); - --pf-c-select__menu-group-title--FontSize: var(--pf-global--FontSize--xs, 0.75rem); - --pf-c-select__menu-group-title--FontWeight: var(--pf-global--FontWeight--normal, 400); - --pf-c-select__menu-group-title--Color: var(--pf-global--Color--dark-200, #6a6e73); - --pf-c-select__menu-item-count--MarginLeft: var(--pf-global--spacer--md, 1rem); - --pf-c-select__menu-item-count--FontSize: var(--pf-global--FontSize--sm, 0.875rem); - --pf-c-select__menu-item-count--Color: var(--pf-global--Color--200, #6a6e73); - --pf-c-select__menu-item--disabled__menu-item-count--Color: var(--pf-global--Color--dark-200, #6a6e73); - --pf-c-select__menu-item-description--FontSize: var(--pf-global--FontSize--xs, 0.75rem); - --pf-c-select__menu-item-description--Color: var(--pf-global--Color--200, #6a6e73); - --pf-c-select__menu-item-description--PaddingRight: var(--pf-c-select__menu-item--PaddingRight); - --pf-c-select__menu-item-main--PaddingRight: var(--pf-c-select__menu-item--PaddingRight); - --pf-c-select__menu-item--m-selected__menu-item-main--PaddingRight: var(--pf-c-select__menu-item--m-selected--PaddingRight); - --pf-c-select__menu-footer--BoxShadow: var(--pf-global--BoxShadow--sm-top, 0 -0.125rem 0.25rem -0.0625rem rgba(3, 3, 3, 0.16)); - --pf-c-select__menu-footer--PaddingTop: var(--pf-global--spacer--md, 1rem); - --pf-c-select__menu-footer--PaddingRight: var(--pf-global--spacer--md, 1rem); - --pf-c-select__menu-footer--PaddingBottom: var(--pf-global--spacer--md, 1rem); - --pf-c-select__menu-footer--PaddingLeft: var(--pf-global--spacer--md, 1rem); - --pf-c-select__menu-footer--MarginTop: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select__menu-footer--MarginBottom: calc(var(--pf-global--spacer--sm, 0.5rem) * -1); - --pf-c-select-menu--c-divider--MarginTop: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-select-menu--c-divider--MarginBottom: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__toggle--PaddingTop: var(--pf-global--spacer--form-element, 0.375rem); + --pf-c-search-input__toggle--PaddingRight: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__toggle--PaddingBottom: var(--pf-global--spacer--form-element, 0.375rem); + --pf-c-search-input__toggle--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__toggle--MinWidth: var(--pf-global--target-size--MinWidth, 44px); + --pf-c-search-input__toggle--FontSize: var(--pf-global--FontSize--md, 1rem); + --pf-c-search-input__toggle--FontWeight: var(--pf-global--FontWeight--normal, 400); + --pf-c-search-input__toggle--LineHeight: var(--pf-global--LineHeight--md, 1.5); + --pf-c-search-input__toggle--BackgroundColor: var(--pf-global--BackgroundColor--100, #fff); + --pf-c-search-input__toggle--before--BorderTopWidth: var(--pf-global--BorderWidth--sm, 1px); + --pf-c-search-input__toggle--before--BorderRightWidth: var(--pf-global--BorderWidth--sm, 1px); + --pf-c-search-input__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--sm, 1px); + --pf-c-search-input__toggle--before--BorderLeftWidth: var(--pf-global--BorderWidth--sm, 1px); + --pf-c-search-input__toggle--before--BorderWidth: initial; + --pf-c-search-input__toggle--before--BorderTopColor: var(--pf-global--BorderColor--300, #f0f0f0); + --pf-c-search-input__toggle--before--BorderRightColor: var(--pf-global--BorderColor--300, #f0f0f0); + --pf-c-search-input__toggle--before--BorderBottomColor: var(--pf-global--BorderColor--200, #8a8d90); + --pf-c-search-input__toggle--before--BorderLeftColor: var(--pf-global--BorderColor--300, #f0f0f0); + --pf-c-search-input__toggle--Color: var(--pf-global--Color--100, #151515); + --pf-c-search-input__toggle--hover--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); + --pf-c-search-input__toggle--focus--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); + --pf-c-search-input__toggle--focus--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); + --pf-c-search-input__toggle--active--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); + --pf-c-search-input__toggle--active--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); + --pf-c-search-input__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); + --pf-c-search-input__toggle--m-expanded--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); + --pf-c-search-input__toggle--disabled--BackgroundColor: var(--pf-global--disabled-color--300, #f0f0f0); + --pf-c-search-input__toggle--m-plain--before--BorderColor: transparent; + --pf-c-search-input__toggle--m-placeholder--Color: transparent; + --pf-c-search-input--m-invalid__toggle--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); + --pf-c-search-input--m-invalid__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); + --pf-c-search-input--m-invalid__toggle--hover--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); + --pf-c-search-input--m-invalid__toggle--focus--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); + --pf-c-search-input--m-invalid__toggle--active--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); + --pf-c-search-input--m-invalid__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); + --pf-c-search-input--m-invalid__toggle-status-icon--Color: var(--pf-global--danger-color--100, #c9190b); + --pf-c-search-input--m-success__toggle--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); + --pf-c-search-input--m-success__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); + --pf-c-search-input--m-success__toggle--hover--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); + --pf-c-search-input--m-success__toggle--focus--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); + --pf-c-search-input--m-success__toggle--active--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); + --pf-c-search-input--m-success__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); + --pf-c-search-input--m-success__toggle-status-icon--Color: var(--pf-global--success-color--100, #3e8635); + --pf-c-search-input--m-warning__toggle--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); + --pf-c-search-input--m-warning__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); + --pf-c-search-input--m-warning__toggle--hover--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); + --pf-c-search-input--m-warning__toggle--focus--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); + --pf-c-search-input--m-warning__toggle--active--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); + --pf-c-search-input--m-warning__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); + --pf-c-search-input--m-warning__toggle-status-icon--Color: var(--pf-global--warning-color--100, #f0ab00); + --pf-c-search-input__toggle-wrapper--not-last-child--MarginRight: var(--pf-global--spacer--xs, 0.25rem); + --pf-c-search-input__toggle-wrapper--MaxWidth: calc(100% - var(--pf-global--spacer--lg, 1.5rem)); + --pf-c-search-input__toggle--m-placeholder__toggle-text--Color: var(--pf-global--Color--dark-200, #6a6e73); + --pf-c-search-input__toggle-icon--toggle-text--MarginLeft: var(--pf-global--spacer--xs, 0.25rem); + --pf-c-search-input__toggle-status-icon--MarginLeft: var(--pf-global--spacer--xs, 0.25rem); + --pf-c-search-input__toggle-status-icon--Color: var(--pf-global--Color--100, #151515); + --pf-c-search-input__toggle-arrow--MarginLeft: var(--pf-global--spacer--md, 1rem); + --pf-c-search-input__toggle-arrow--MarginRight: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__toggle-arrow--with-clear--MarginLeft: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__toggle-arrow--m-top--m-expanded__toggle-arrow--Rotate: 180deg; + --pf-c-search-input--m-plain__toggle-arrow--Color: var(--pf-global--Color--200, #6a6e73); + --pf-c-search-input--m-plain--hover__toggle-arrow--Color: var(--pf-global--Color--100, #151515); + --pf-c-search-input__toggle-clear--PaddingRight: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__toggle-clear--PaddingLeft: var(--pf-global--spacer--md, 1rem); + --pf-c-search-input__toggle-clear--toggle-button--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__toggle-button--Color: var(--pf-global--Color--100, #151515); + --pf-c-search-input__menu--BackgroundColor: var(--pf-global--BackgroundColor--light-100, #fff); + --pf-c-search-input__menu--BoxShadow: var(--pf-global--BoxShadow--md, 0 0.25rem 0.5rem 0rem rgba(3, 3, 3, 0.12), 0 0 0.25rem 0 rgba(3, 3, 3, 0.06)); + --pf-c-search-input__menu--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__menu--PaddingBottom: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__menu--Top: calc(100% + var(--pf-global--spacer--xs, 0.25rem)); + --pf-c-search-input__menu--ZIndex: var(--pf-global--ZIndex--sm, 200); + --pf-c-search-input__menu--Width: auto; + --pf-c-search-input__menu--MinWidth: 100%; + --pf-c-search-input__menu--m-top--TranslateY: calc(-100% - var(--pf-global--spacer--xs, 0.25rem)); + --pf-c-search-input__list-item--m-loading--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__menu-item--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__menu-item--PaddingRight: var(--pf-global--spacer--md, 1rem); + --pf-c-search-input__menu-item--m-selected--PaddingRight: var(--pf-global--spacer--2xl, 3rem); + --pf-c-search-input__menu-item--PaddingBottom: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__menu-item--PaddingLeft: var(--pf-global--spacer--md, 1rem); + --pf-c-search-input__menu-item--FontSize: var(--pf-global--FontSize--md, 1rem); + --pf-c-search-input__menu-item--FontWeight: var(--pf-global--FontWeight--normal, 400); + --pf-c-search-input__menu-item--LineHeight: var(--pf-global--LineHeight--md, 1.5); + --pf-c-search-input__menu-item--Color: var(--pf-global--Color--dark-100, #151515); + --pf-c-search-input__menu-item--disabled--Color: var(--pf-global--Color--dark-200, #6a6e73); + --pf-c-search-input__menu-item--Width: 100%; + --pf-c-search-input__menu-item--hover--BackgroundColor: var(--pf-global--BackgroundColor--light-300, #f0f0f0); + --pf-c-search-input__menu-item--focus--BackgroundColor: var(--pf-global--BackgroundColor--light-300, #f0f0f0); + --pf-c-search-input__menu-item--disabled--BackgroundColor: transparent; + --pf-c-search-input__menu-item--m-link--Width: auto; + --pf-c-search-input__menu-item--m-link--hover--BackgroundColor: transparent; + --pf-c-search-input__menu-item--m-link--focus--BackgroundColor: transparent; + --pf-c-search-input__menu-item--m-action--Color: var(--pf-global--Color--200, #6a6e73); + --pf-c-search-input__menu-item--m-action--hover--Color: var(--pf-global--Color--100, #151515); + --pf-c-search-input__menu-item--m-action--focus--Color: var(--pf-global--Color--100, #151515); + --pf-c-search-input__menu-item--m-action--disabled--Color: var(--pf-global--disabled-color--200, #d2d2d2); + --pf-c-search-input__menu-item--m-action--Width: auto; + --pf-c-search-input__menu-item--m-action--FontSize: var(--pf-global--icon--FontSize--sm, 0.625rem); + --pf-c-search-input__menu-item--m-action--hover--BackgroundColor: transparent; + --pf-c-search-input__menu-item--m-action--focus--BackgroundColor: transparent; + --pf-c-search-input__menu-item--hover__menu-item--m-action--Color: var(--pf-global--Color--200, #6a6e73); + --pf-c-search-input__menu-item--m-favorite-action--Color: var(--pf-global--Color--200, #6a6e73); + --pf-c-search-input__menu-item--m-favorite-action--hover--Color: var(--pf-global--Color--100, #151515); + --pf-c-search-input__menu-item--m-favorite-action--focus--Color: var(--pf-global--Color--100, #151515); + --pf-c-search-input__menu-wrapper--m-favorite__menu-item--m-favorite-action--Color: var(--pf-global--palette--gold-400, #f0ab00); + --pf-c-search-input__menu-wrapper--m-favorite__menu-item--m-favorite-action--hover--Color: var(--pf-global--palette--gold-500, #c58c00); + --pf-c-search-input__menu-wrapper--m-favorite__menu-item--m-favorite-action--focus--Color: var(--pf-global--palette--gold-500, #c58c00); + --pf-c-search-input__menu-item--m-load--Color: var(--pf-global--link--Color, #06c); + --pf-c-search-input__menu-item-icon--Color: var(--pf-global--active-color--100, #06c); + --pf-c-search-input__menu-item-icon--FontSize: var(--pf-global--icon--FontSize--sm, 0.625rem); + --pf-c-search-input__menu-item-icon--Right: var(--pf-global--spacer--md, 1rem); + --pf-c-search-input__menu-item-icon--Top: 50%; + --pf-c-search-input__menu-item-icon--TranslateY: -50%; + --pf-c-search-input__menu-item-action-icon--MinHeight: calc(var(--pf-c-search-input__menu-item--FontSize) * var(--pf-c-search-input__menu-item--LineHeight)); + --pf-c-search-input__menu-item--match--FontWeight: var(--pf-global--FontWeight--bold, 700); + --pf-c-search-input__menu-search--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__menu-search--PaddingRight: var(--pf-c-search-input__menu-item--PaddingRight); + --pf-c-search-input__menu-search--PaddingBottom: var(--pf-global--spacer--md, 1rem); + --pf-c-search-input__menu-search--PaddingLeft: var(--pf-c-search-input__menu-item--PaddingLeft); + --pf-c-search-input__menu-group--menu-group--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__menu-group-title--PaddingTop: var(--pf-c-search-input__menu-item--PaddingTop); + --pf-c-search-input__menu-group-title--PaddingRight: var(--pf-c-search-input__menu-item--PaddingRight); + --pf-c-search-input__menu-group-title--PaddingBottom: var(--pf-c-search-input__menu-item--PaddingBottom); + --pf-c-search-input__menu-group-title--PaddingLeft: var(--pf-c-search-input__menu-item--PaddingLeft); + --pf-c-search-input__menu-group-title--FontSize: var(--pf-global--FontSize--xs, 0.75rem); + --pf-c-search-input__menu-group-title--FontWeight: var(--pf-global--FontWeight--normal, 400); + --pf-c-search-input__menu-group-title--Color: var(--pf-global--Color--dark-200, #6a6e73); + --pf-c-search-input__menu-item-count--MarginLeft: var(--pf-global--spacer--md, 1rem); + --pf-c-search-input__menu-item-count--FontSize: var(--pf-global--FontSize--sm, 0.875rem); + --pf-c-search-input__menu-item-count--Color: var(--pf-global--Color--200, #6a6e73); + --pf-c-search-input__menu-item--disabled__menu-item-count--Color: var(--pf-global--Color--dark-200, #6a6e73); + --pf-c-search-input__menu-item-description--FontSize: var(--pf-global--FontSize--xs, 0.75rem); + --pf-c-search-input__menu-item-description--Color: var(--pf-global--Color--200, #6a6e73); + --pf-c-search-input__menu-item-description--PaddingRight: var(--pf-c-search-input__menu-item--PaddingRight); + --pf-c-search-input__menu-item-main--PaddingRight: var(--pf-c-search-input__menu-item--PaddingRight); + --pf-c-search-input__menu-item--m-selected__menu-item-main--PaddingRight: var(--pf-c-search-input__menu-item--m-selected--PaddingRight); + --pf-c-search-input__menu-footer--BoxShadow: var(--pf-global--BoxShadow--sm-top, 0 -0.125rem 0.25rem -0.0625rem rgba(3, 3, 3, 0.16)); + --pf-c-search-input__menu-footer--PaddingTop: var(--pf-global--spacer--md, 1rem); + --pf-c-search-input__menu-footer--PaddingRight: var(--pf-global--spacer--md, 1rem); + --pf-c-search-input__menu-footer--PaddingBottom: var(--pf-global--spacer--md, 1rem); + --pf-c-search-input__menu-footer--PaddingLeft: var(--pf-global--spacer--md, 1rem); + --pf-c-search-input__menu-footer--MarginTop: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__menu-footer--MarginBottom: calc(var(--pf-global--spacer--sm, 0.5rem) * -1); + --pf-c-search-input-menu--c-divider--MarginTop: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input-menu--c-divider--MarginBottom: var(--pf-global--spacer--sm, 0.5rem); } :host, #outer { @@ -291,30 +281,20 @@ #toggle-button:focus:before { - border-bottom-color: var(--pf-c-select__toggle--focus--before--BorderBottomColor); - border-bottom-width: var(--pf-c-select__toggle--focus--before--BorderBottomWidth); + border-bottom-color: var(--pf-c-search-input__toggle--focus--before--BorderBottomColor); + border-bottom-width: var(--pf-c-search-input__toggle--focus--before--BorderBottomWidth); } /* #outer.typeahead #toggle-button { flex: 0 0 auto; } */ -#toggle-badge { - flex: 1 0 auto; - margin-inline-start: 0.25em; -} + #toggle-text { flex: 1 1 auto; } -#toggle-text.badge { - flex: 0 1 auto; -} - -pf-badge { - padding: 0; -} #description { display: block; @@ -371,8 +351,8 @@ pf-badge { flex-direction: var(--pf-c-divider--FlexDirection); border: 0; width: 100%; - margin-top: var(--pf-c-select-menu--c-divider--MarginTop); - margin-bottom: var(--pf-c-select-menu--c-divider--MarginBottom); + margin-top: var(--pf-c-search-input-menu--c-divider--MarginTop); + margin-bottom: var(--pf-c-search-input-menu--c-divider--MarginBottom); } ::slotted(hr)::after { From 657370384410424bd2bcf21904140ce88ec88109 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Wed, 2 Apr 2025 18:16:30 +0530 Subject: [PATCH 09/85] chore: styles updated --- .../pf-search-input-option.css | 17 ++------- elements/pf-search-input/pf-search-input.css | 35 +++++++++++++++---- elements/pf-search-input/pf-search-input.ts | 4 +-- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/elements/pf-search-input/pf-search-input-option.css b/elements/pf-search-input/pf-search-input-option.css index a8c488e628..da9f4600c3 100644 --- a/elements/pf-search-input/pf-search-input-option.css +++ b/elements/pf-search-input/pf-search-input-option.css @@ -13,8 +13,7 @@ } :host(:focus) #outer, -:host(:hover) #outer, -#outer.selected { +:host(:hover) #outer{ background-color: #e0e0e0; } @@ -37,10 +36,7 @@ } input[type="checkbox"] { - margin-inline-end: 1em; - display: var(--_pf-option-checkboxes-display, none); - pointer-events: none; - flex: 0 0 auto; + display: none; } span { @@ -48,14 +44,7 @@ span { } svg { - font-size: var(--pf-c-select__menu-item-icon--FontSize, var(--pf-global--icon--FontSize--sm, 0.675rem)); - color: var(--_svg-color, var(--pf-theme--color--accent, #0066cc)); - width: 1em; - height: 1em; - margin-inline-start: 1em; - text-align: right; - flex: 0 0 auto; - display: var(--_pf-option-svg-display, block); + display: none; } #description { diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index 0808249b6c..98f7d3455c 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -211,13 +211,13 @@ #toggle { background-color: var(--pf-theme--color--surface--lightest, #fff) !important; + /* align-items: center; */ } #toggle, /* #toggle-button, */ #toggle-input { display: flex; - align-items: center; font-family: var(--pf-global--FontFamily--sans-serif, "RedHatTextUpdated", "Overpass", overpass, helvetica, arial, sans-serif); font-size: var(--pf-global--FontSize--md, 16px); font-weight: var(--pf-global--FontWeight--normal, 400); @@ -228,11 +228,18 @@ border: 1px solid var(--pf-global--BorderColor--100, #d2d2d2); border-bottom-color: var(--pf-theme--color--text, #151515); justify-content: space-between; + /* &:focus{ + border-radius: 4px; + border-bottom: 2px solid #06c; + } */ } .expanded #toggle { - border-bottom-width: 2px; - border-bottom-color: var(--pf-theme--color--accent, #0066cc); + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + border-bottom: 2px solid #06c; + /* border-bottom-width: 2px; + border-bottom-color: var(--pf-theme--color--accent, #0066cc); */ } .disabled #toggle { @@ -249,6 +256,12 @@ text-align: left; border-radius: 0; flex: 1 0 auto; + outline: none; + &:focus{ + border: 2px solid #06c; + /* border-bottom: none; */ + border-radius: 4px; + } } #toggle-input { @@ -275,14 +288,18 @@ display: flex; align-items: center; justify-content: center; + border-radius: 0px; +} + +#close-button svg{ position: relative; top: 3px; } #toggle-button:focus:before { - border-bottom-color: var(--pf-c-search-input__toggle--focus--before--BorderBottomColor); - border-bottom-width: var(--pf-c-search-input__toggle--focus--before--BorderBottomWidth); + /* border-bottom-color: var(--pf-c-search-input__toggle--focus--before--BorderBottomColor); + border-bottom-width: var(--pf-c-search-input__toggle--focus--before--BorderBottomWidth); */ } /* #outer.typeahead #toggle-button { @@ -370,4 +387,10 @@ div.search-icon{ transform: translateY(-50%); display: flex; align-items: center; -} \ No newline at end of file +} + +.expanded #close-button{ + /* border-bottom-width: 2px; + border-bottom-color: var(--pf-theme--color--accent, #0066cc); */ +} + diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index cadf0aefb3..108f7bf1c9 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -76,7 +76,7 @@ export class PfSearchInput extends LitElement { @query('#toggle-input') private _toggleInput?: HTMLInputElement; - @query('#toggle-button') private _toggleButton?: PfButton; + @query('#toggle-button') private _toggleButton?: HTMLDivElement; @query('#listbox') private _listbox?: HTMLElement; @@ -174,7 +174,6 @@ export class PfSearchInput extends LitElement { ?disabled="${disabled}" placeholder="${placeholder || this.#buttonLabel}" > - +
Date: Thu, 3 Apr 2025 14:21:55 +0530 Subject: [PATCH 10/85] chore: outside click implementation --- .../pf-search-input-option.css | 2 +- elements/pf-search-input/pf-search-input.ts | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/elements/pf-search-input/pf-search-input-option.css b/elements/pf-search-input/pf-search-input-option.css index da9f4600c3..cdca0e954d 100644 --- a/elements/pf-search-input/pf-search-input-option.css +++ b/elements/pf-search-input/pf-search-input-option.css @@ -13,7 +13,7 @@ } :host(:focus) #outer, -:host(:hover) #outer{ +:host(:hover) #outer { background-color: #e0e0e0; } diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 108f7bf1c9..b167b22a0c 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -19,6 +19,7 @@ import { observes } from '@patternfly/pfe-core/decorators/observes.js'; import { PfSearchInputOption } from './pf-search-input-option.js'; import styles from './pf-search-input.css'; import type { PfButton } from '../pf-button/pf-button.js'; +import { bound } from '@patternfly/pfe-core/decorators.js'; export class PfSelectChangeEvent extends Event { constructor() { @@ -84,6 +85,8 @@ export class PfSearchInput extends LitElement { @query('#placeholder') private _placeholder?: PfSearchInputOption; + @query('#outer') private _searchInputContainer!: HTMLElement; + #isNotPlaceholderOption = (option: PfSearchInputOption) => option !== this._placeholder; #internals = InternalsController.of(this); @@ -110,6 +113,29 @@ export class PfSearchInput extends LitElement { setItemSelected: (item, selected) => item.selected = selected, }); + connectedCallback(): void { + super.connectedCallback(); + document.addEventListener('click', this._onOutsideClick); + } + + disconnectedCallback(): void { + super.disconnectedCallback(); + document.removeEventListener('click', this._onOutsideClick); + } + + + // Function to handle the closing of popover and month select popup on outside click + @bound private _onOutsideClick(event: MouseEvent) { + const path = event.composedPath(); + if (!path.includes(this._searchInputContainer)) { + if (this.expanded) { + this.expanded = false; + } else { + //this._popover.hide(); + } + } + } + /** * Single select option value for single select menus, * or array of select option values for multi select. From a4491fd375b3acaf9dd062b463cced90ef87fde9 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Thu, 3 Apr 2025 16:47:41 +0530 Subject: [PATCH 11/85] chore: added pf-option instead of pf-search-input-option --- .../demo/pf-search-input-autocomplete.html | 10 +++++----- elements/pf-search-input/pf-search-input.css | 1 - elements/pf-search-input/pf-search-input.ts | 19 ++++++++++--------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/elements/pf-search-input/demo/pf-search-input-autocomplete.html b/elements/pf-search-input/demo/pf-search-input-autocomplete.html index ba8c18aee7..3ff7577ec9 100644 --- a/elements/pf-search-input/demo/pf-search-input-autocomplete.html +++ b/elements/pf-search-input/demo/pf-search-input-autocomplete.html @@ -1,11 +1,11 @@

Search with autocomplete

- Alabama - New Jersey - New York - New Mexico - North Carolina + Alabama + New Jersey + New York + New Mexico + North Carolina
diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index 98f7d3455c..cbaaba5b9c 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -393,4 +393,3 @@ div.search-icon{ /* border-bottom-width: 2px; border-bottom-color: var(--pf-theme--color--accent, #0066cc); */ } - diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index b167b22a0c..87d2df228c 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -19,6 +19,7 @@ import { observes } from '@patternfly/pfe-core/decorators/observes.js'; import { PfSearchInputOption } from './pf-search-input-option.js'; import styles from './pf-search-input.css'; import type { PfButton } from '../pf-button/pf-button.js'; +import { PfOption } from '../pf-select/pf-option.js'; import { bound } from '@patternfly/pfe-core/decorators.js'; export class PfSelectChangeEvent extends Event { @@ -83,11 +84,11 @@ export class PfSearchInput extends LitElement { @query('#listbox-container') private _listboxContainer?: HTMLElement; - @query('#placeholder') private _placeholder?: PfSearchInputOption; + @query('#placeholder') private _placeholder?: PfOption; @query('#outer') private _searchInputContainer!: HTMLElement; - #isNotPlaceholderOption = (option: PfSearchInputOption) => option !== this._placeholder; + #isNotPlaceholderOption = (option: PfOption) => option !== this._placeholder; #internals = InternalsController.of(this); @@ -108,7 +109,7 @@ export class PfSearchInput extends LitElement { requestShowListbox: () => void (this.expanded ||= true), requestHideListbox: () => void (this.expanded &&= false), setItemHidden: (item, hidden) => (item.id !== 'placeholder') && void (item.hidden = hidden), - isItem: item => item instanceof PfSearchInputOption, + isItem: item => item instanceof PfOption, setItemActive: (item, active) => item.active = active, setItemSelected: (item, selected) => item.selected = selected, }); @@ -141,24 +142,24 @@ export class PfSearchInput extends LitElement { * or array of select option values for multi select. */ @property({ hasChanged: (a, b) => !arraysAreEquivalent(a, b) }) - set selected(selected: PfSearchInputOption | PfSearchInputOption[]) { + set selected(selected: PfOption | PfOption[]) { const list = Array.isArray(selected) ? selected : [selected]; this.#combobox.selected = list; } - get selected(): PfSearchInputOption[] { + get selected(): PfOption[] { return this.#combobox.selected; } /** List of options */ - get options(): PfSearchInputOption[] { + get options(): PfOption[] { if (isServer) { return []; // TODO: expose a DOM property to allow setting options in SSR scenarios } else { return [ this._placeholder, - ...Array.from(this.querySelectorAll('pf-search-input-option')), - ].filter((x): x is PfSearchInputOption => !!x && !x.hidden); + ...Array.from(this.querySelectorAll('pf-option')), + ].filter((x): x is PfOption => !!x && !x.hidden); } } @@ -254,7 +255,7 @@ export class PfSearchInput extends LitElement { } @observes('selected') - private async selectedChanged(_: PfSearchInputOption[], selected: PfSearchInputOption[]) { + private async selectedChanged(_: PfOption[], selected: PfOption[]) { this.value = selected.map(x => x.value).join(); await this.updateComplete; this._toggleInput!.value = this.value; From 6eaa40c7dee555fc2b043cc3e65e217950cd52e3 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Thu, 3 Apr 2025 17:18:26 +0530 Subject: [PATCH 12/85] chore: style issues resolved --- elements/pf-search-input/pf-search-input.css | 77 ++++++-------------- 1 file changed, 22 insertions(+), 55 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index cbaaba5b9c..dab6599b4d 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -179,11 +179,11 @@ /* TODO(bennyp): see if we can get rid of this wrapping node, for perf reasons */ #listbox-container { display: inline-flex; - border: 1px solid var(--pf-global--BorderColor--100, #d2d2d2); position: absolute; background-color: var(--pf-theme--color--surface--lightest, #fff) !important; opacity: 0; - --_active-descendant-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important + --_active-descendant-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; + box-shadow: 0 0.25rem 0.5rem 0rem rgba(3, 3, 3, 0.12), 0 0 0.25rem 0 rgba(3, 3, 3, 0.06); } #outer.expanded #listbox-container { @@ -208,14 +208,11 @@ --_svg-color: var(--pf-c-list__item-icon--Color, #6a6e73) !important; } - #toggle { background-color: var(--pf-theme--color--surface--lightest, #fff) !important; - /* align-items: center; */ } #toggle, -/* #toggle-button, */ #toggle-input { display: flex; font-family: var(--pf-global--FontFamily--sans-serif, "RedHatTextUpdated", "Overpass", overpass, helvetica, arial, sans-serif); @@ -228,18 +225,6 @@ border: 1px solid var(--pf-global--BorderColor--100, #d2d2d2); border-bottom-color: var(--pf-theme--color--text, #151515); justify-content: space-between; - /* &:focus{ - border-radius: 4px; - border-bottom: 2px solid #06c; - } */ -} - -.expanded #toggle { - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; - border-bottom: 2px solid #06c; - /* border-bottom-width: 2px; - border-bottom-color: var(--pf-theme--color--accent, #0066cc); */ } .disabled #toggle { @@ -256,21 +241,15 @@ text-align: left; border-radius: 0; flex: 1 0 auto; - outline: none; - &:focus{ - border: 2px solid #06c; - /* border-bottom: none; */ - border-radius: 4px; - } } #toggle-input { justify-content: space-between; padding: var(--pf-global--spacer--xs, 0.25rem) var(--pf-global--spacer--sm, 0.5rem); - padding-left: 40px; + padding-left: 2.5rem; width: 90%; box-sizing: border-box; - max-height: 36px; + max-height: 2.25rem; } .disabled #toggle-input { @@ -282,8 +261,8 @@ background-color: transparent; justify-content: flex-end; padding: var(--pf-global--spacer--sm, 0.5rem); - max-height: 36px; - max-width: 36px; + max-height: 2.25rem; + max-width: 2.25rem; box-sizing: border-box; display: flex; align-items: center; @@ -291,23 +270,11 @@ border-radius: 0px; } -#close-button svg{ +#close-button svg { position: relative; top: 3px; } - -#toggle-button:focus:before { - /* border-bottom-color: var(--pf-c-search-input__toggle--focus--before--BorderBottomColor); - border-bottom-width: var(--pf-c-search-input__toggle--focus--before--BorderBottomWidth); */ -} - -/* #outer.typeahead #toggle-button { - flex: 0 0 auto; -} */ - - - #toggle-text { flex: 1 1 auto; } @@ -318,18 +285,10 @@ } #listbox.checkboxes { - --_pf-option-checkboxes-display: inline; + --_pf-option-checkboxes-display: none; --_pf-option-svg-display: none; } -::slotted(pf-option-group + hr) { - display: none !important; -} - -::slotted(hr:has(+ pf-option-group)) { - display: none !important; -} - .visually-hidden { border: 0; clip: rect(0, 0, 0, 0); @@ -380,16 +339,24 @@ flex: 1 0 100%; } -div.search-icon{ +div.search-icon { position: absolute; top: 50%; - left: 1rem; + left: var(--pf-global--spacer--md, 1rem); transform: translateY(-50%); display: flex; align-items: center; } -.expanded #close-button{ - /* border-bottom-width: 2px; - border-bottom-color: var(--pf-theme--color--accent, #0066cc); */ -} +#outer:focus-within { + #toggle { + border-top-left-radius: var(--pf-global--spacer--sm, 0.5rem); + border-bottom-left-radius: var(--pf-global--spacer--sm, 0.5rem); + border-bottom: var(--pf-global--spacer--xs, 0.25rem) solid transparent; + } + #close-button { + border-bottom-width: var(--pf-global--spacer--xs, 0.125rem); + border-bottom-color: var(--pf-theme--color--accent, #0066cc); + box-sizing: border-box; + } +} \ No newline at end of file From fe4c0ef6bfd95f9871bfc322135be76c8d9ae6ff Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Thu, 3 Apr 2025 17:30:14 +0530 Subject: [PATCH 13/85] chore: style issues resolved --- elements/pf-search-input/demo/pf-search-input.html | 12 ++++++------ elements/pf-search-input/pf-search-input.css | 11 +++-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/elements/pf-search-input/demo/pf-search-input.html b/elements/pf-search-input/demo/pf-search-input.html index 88c2e63f65..4f45de098a 100644 --- a/elements/pf-search-input/demo/pf-search-input.html +++ b/elements/pf-search-input/demo/pf-search-input.html @@ -1,12 +1,12 @@ - Mr - Miss - Mrs - Ms + Mr + Miss + Mrs + Ms
- Dr - Other + Dr + Other
- - - From 84c19bd19c13f0a0f20e46c0e0bcf232ac6276c8 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Wed, 4 Jun 2025 18:15:55 +0530 Subject: [PATCH 30/85] feat(search-input): add pf-search-input element --- elements/pf-search-input/pf-search-input.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 4b70ebc0f4..bcbd665c1f 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -268,19 +268,6 @@ export class PfSearchInput extends LitElement { } } - // #computePlaceholderText() { - // return this.placeholder - // || this.querySelector?.('[slot=placeholder]') - // ?.assignedNodes() - // ?.reduce((acc, node) => `${acc}${node.textContent}`, '') - // ?.trim() - // || this.#combobox.items - // .filter(this.#isNotPlaceholderOption) - // .at(0) - // ?.value - // || ''; - // } - /** * Opens the dropdown */ From 616475b9f764d6e4cc1e8f4de68de7de9de2f387 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Thu, 5 Jun 2025 17:43:44 +0530 Subject: [PATCH 31/85] chore: search change event updated --- .../demo/pf-search-input-autocomplete.html | 11 ++++++++++- elements/pf-search-input/pf-search-input.ts | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/elements/pf-search-input/demo/pf-search-input-autocomplete.html b/elements/pf-search-input/demo/pf-search-input-autocomplete.html index 712a57b958..034e1e9221 100644 --- a/elements/pf-search-input/demo/pf-search-input-autocomplete.html +++ b/elements/pf-search-input/demo/pf-search-input-autocomplete.html @@ -1,6 +1,6 @@

Search with autocomplete

- + Alabama New Jersey New York @@ -26,6 +26,15 @@

Search with autocomplete

- diff --git a/elements/pf-search-input/demo/pf-search-input.html b/elements/pf-search-input/demo/pf-search-input.html index 420fa0b74a..034e1e9221 100644 --- a/elements/pf-search-input/demo/pf-search-input.html +++ b/elements/pf-search-input/demo/pf-search-input.html @@ -1,14 +1,45 @@ - - Mr - Miss - Mrs - Ms -
- Dr - Other -
+
+

Search with autocomplete

+ + Alabama + New Jersey + New York + New Mexico + North Carolina + Alabama 1 + New Jersey 1 + New York 1 + New Mexico 1 + North Carolina 1 + Alabama 2 + New Jersey 2 + New York 2 + New Mexico 2 + North Carolina 2 + Alabama 3 + New Jersey 3 + New York 3 + New Mexico 3 + North Carolina 3 + +
+ + + From 8f5d6f39c17e4e81124c8cc7ded1f9fc2036c24f Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Thu, 19 Jun 2025 18:11:28 +0530 Subject: [PATCH 36/85] chore: updated readme --- elements/pf-search-input/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/elements/pf-search-input/README.md b/elements/pf-search-input/README.md index f7e06c1c24..3b4180e2ce 100644 --- a/elements/pf-search-input/README.md +++ b/elements/pf-search-input/README.md @@ -1,11 +1,15 @@ # Search Input -Add a description of the component here. +A search input lets users type in words to find specific items or information. As they type, it can show matching results to help them quickly find what they are looking for. ## Usage -Describe how best to use this web component along with best practices. +A search input consists of a text field where users can type to find specific content or items. Unlike selects or dropdowns, which offer predefined options, a search input lets users enter their own keywords to filter or locate results. It includes a clear (×) button to easily remove the current input, allowing users to start a new search quickly. ```html - + Alabama + New Jersey + New York + New Mexico + North Carolina ``` From 011a221e8ec138181d392be7cfa564c76e7b4427 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Mon, 30 Jun 2025 14:19:36 +0530 Subject: [PATCH 37/85] chore: removed duplicate style --- elements/pf-search-input/pf-search-input.css | 7 ------- 1 file changed, 7 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index 2a1cf43a42..385e9fb1fc 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -364,13 +364,6 @@ div.search-icon { } } -div.visually-hidden { - width: 0; - height: 0; - padding: 0; - visibility: hidden; -} - ::slotted(pf-option[selected]) { --_pf-option-svg-display: none; --_pf-option-selected-background-color: var(--pf-global--BackgroundColor--100, #fff); From c8ad1ace61a81ad9b004942e92fbce9fdde29784 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Mon, 7 Jul 2025 00:24:12 +0530 Subject: [PATCH 38/85] chore: test cases added - draft --- elements/pf-search-input/pf-search-input.ts | 4 +- .../test/pf-search-input.spec.ts | 1114 ++++++++++++++++- 2 files changed, 1114 insertions(+), 4 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index b52ec36ab1..fb8b2b874a 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -188,7 +188,6 @@ export class PfSearchInput extends LitElement {
close -
+
+ 1 + 2 + 3 + `); + }); + + it('passes aXe audit', async function() { + await expect(element).to.be.accessible(); + }); + + it('labels the combobox with the accessible-label attribuet', async function() { + expect(await a11ySnapshot()).to.axContainQuery({ + role: 'combobox', + name: 'label', + }); + }); + + it('does not have redundant role', async function() { + expect(element.shadowRoot?.firstElementChild).to.not.contain('[role="button"]'); + }); + + it('sets aria-setsize="3" and aria-posinset on items', function() { + element.options.forEach((option, i) => { + expect(option).to.have.attr('aria-setsize', '3'); + expect(option).to.have.attr('aria-posinset', `${i + 1}`); + }); + }); + + describe('focus()', function() { + beforeEach(focus); + beforeEach(updateComplete); + describe('ArrowDown', async function() { + beforeEach(press('ArrowDown')); + beforeEach(updateComplete); + await aTimeout(30); + + it('labels the listbox with the accessible-label attribute', async function() { + const snap = await a11ySnapshot(); + expect(snap).to.axContainQuery({ + role: 'listbox', + name: 'label', + }); + }); + + it('focuses on the first item', async function() { + expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axName('1'); + }); + + describe('Space', function() { + beforeEach(press(' ')); + beforeEach(updateComplete); + // it('selects option 1', function() { + // expect(getSelectedOptionValue(element)).to.deep.equal(['1']); + // }); + + // it('exposes selection to assistive technology', async function() { + // expect(await a11ySnapshot()).to.axContainQuery({ + // role: 'combobox', + // value: '1', + // }); + // }); + }); + }); + }); + }); + + describe('with 3 items and associated
Date: Sat, 12 Jul 2025 00:16:37 +0530 Subject: [PATCH 43/85] chore: submit button variant added --- .../demo/pf-search-input-with-submit.html | 45 ++++++++ elements/pf-search-input/pf-search-input.css | 15 ++- elements/pf-search-input/pf-search-input.ts | 100 +++++++++++------- 3 files changed, 122 insertions(+), 38 deletions(-) create mode 100644 elements/pf-search-input/demo/pf-search-input-with-submit.html diff --git a/elements/pf-search-input/demo/pf-search-input-with-submit.html b/elements/pf-search-input/demo/pf-search-input-with-submit.html new file mode 100644 index 0000000000..d35cb11ea1 --- /dev/null +++ b/elements/pf-search-input/demo/pf-search-input-with-submit.html @@ -0,0 +1,45 @@ +
+

Search with autocomplete

+ + Search + Alabama + New Jersey + New York + New Mexico + North Carolina + Alabama 1 + New Jersey 1 + New York 1 + New Mexico 1 + North Carolina 1 + Alabama 2 + New Jersey 2 + New York 2 + New Mexico 2 + North Carolina 2 + Alabama 3 + New Jersey 3 + New York 3 + New Mexico 3 + North Carolina 3 + +
+ + + + \ No newline at end of file diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index 3c47530f85..f6544525c7 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -157,6 +157,7 @@ display: flex; flex-direction: column; align-items: stretch; + width: fit-content; } :host([hidden]), @@ -176,7 +177,6 @@ position: relative; } -/* TODO(bennyp): see if we can get rid of this wrapping node, for perf reasons */ #listbox-container { display: inline-flex; position: absolute; @@ -394,4 +394,17 @@ pf-text-input { border: none; box-sizing: border-box; +} + +.search-input-container { + display: flex; + align-items: center; + justify-content: flex-start; + position: relative; +} + +.submit-button-container { + position: absolute; + top: 0; + right: -100px; } \ No newline at end of file diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index f3257e113d..9114a7e607 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -172,47 +172,52 @@ export class PfSearchInput extends LitElement { const hideLightDomItems = !ComboboxController.supportsCrossRootActiveDescendant; return html` -
-
-
- search -
- -
- - close - -
- -
+
-
- ${this.#combobox.renderItemsToShadowRoot()} - +
+
+ search +
+ +
+ + close + +
+ +
+
+
+ ${this.#combobox.renderItemsToShadowRoot()} + +
+
+ +
`; } @@ -316,6 +321,27 @@ export class PfSearchInput extends LitElement { this.dispatchEvent(new PfSearchChangeEvent()); } } + + #onSubmit(event: MouseEvent | KeyboardEvent) { + const path = event.composedPath(); + const slottedSearchButton = path.find(el => + el instanceof HTMLElement + && el.tagName === 'PF-BUTTON' + && el.getAttribute('data-action') === 'search' + ); + + if (slottedSearchButton && this._toggleInput?.value) { + this.value = this._toggleInput?.value; + this.#internals.setFormValue(this.value ?? ''); + this.dispatchEvent(new PfSearchChangeEvent()); + } + } + + #handleKeyDown(e: KeyboardEvent) { + if (e.key === 'Enter' || e.key === ' ') { + this.#onSubmit(e); + } + } } declare global { From f9198e57a41e9abfb2374f7a705c4600899da586 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Sat, 12 Jul 2025 00:19:35 +0530 Subject: [PATCH 44/85] chore: code cleanup --- .../demo/pf-search-input-with-submit.html | 8 +- .../pf-search-input/demo/pf-search-input.html | 11 +- elements/pf-search-input/pf-search-input.css | 216 +++++++++--------- elements/pf-search-input/pf-search-input.ts | 6 +- 4 files changed, 123 insertions(+), 118 deletions(-) diff --git a/elements/pf-search-input/demo/pf-search-input-with-submit.html b/elements/pf-search-input/demo/pf-search-input-with-submit.html index d35cb11ea1..bad39ab083 100644 --- a/elements/pf-search-input/demo/pf-search-input-with-submit.html +++ b/elements/pf-search-input/demo/pf-search-input-with-submit.html @@ -10,7 +10,7 @@

Search with autocomplete

Alabama 1 New Jersey 1 New York 1 - New Mexico 1 + New Mexico 1 North Carolina 1 Alabama 2 New Jersey 2 @@ -39,7 +39,7 @@

Search with autocomplete

\ No newline at end of file diff --git a/elements/pf-search-input/demo/pf-search-input.html b/elements/pf-search-input/demo/pf-search-input.html index 034e1e9221..f8842937ab 100644 --- a/elements/pf-search-input/demo/pf-search-input.html +++ b/elements/pf-search-input/demo/pf-search-input.html @@ -9,7 +9,7 @@

Search with autocomplete

Alabama 1 New Jersey 1 New York 1 - New Mexico 1 + New Mexico 1 North Carolina 1 Alabama 2 New Jersey 2 @@ -38,8 +38,7 @@

Search with autocomplete

- + .container { + padding: 40px; + } + \ No newline at end of file diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index f6544525c7..a6c6a6c770 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -1,10 +1,10 @@ :host { - font-family: var(--pf-global--FontFamily--sans-serif, "RedHatTextUpdated", "Overpass", overpass, helvetica, arial, sans-serif); - font-size: var(--pf-global--FontSize--md, 16px); - font-weight: var(--pf-global--FontWeight--normal, 400); + font-family: var(--pf-global--FontFamily--sans-serif, "RedHatTextUpdated", "Overpass", overpass, helvetica, arial, sans-serif); + font-size: var(--pf-global--FontSize--md, 16px); + font-weight: var(--pf-global--FontWeight--normal, 400); color: var(--pf-global--Color--100, #151515); - --_pf-option-checkboxes-display: none; - --_pf-option-svg-display: block; + --_pf-option-checkboxes-display: none; + --_pf-option-svg-display: block; --pf-c-search-input__toggle--PaddingTop: var(--pf-global--spacer--form-element, 0.375rem); --pf-c-search-input__toggle--PaddingRight: var(--pf-global--spacer--sm, 0.5rem); --pf-c-search-input__toggle--PaddingBottom: var(--pf-global--spacer--form-element, 0.375rem); @@ -153,107 +153,110 @@ --pf-c-search-input-menu--c-divider--MarginBottom: var(--pf-global--spacer--sm, 0.5rem); } -:host, #outer { - display: flex; - flex-direction: column; - align-items: stretch; +:host, +#outer { + display: flex; + flex-direction: column; + align-items: stretch; width: fit-content; } :host([hidden]), *[hidden] { - display: none !important; + display: none !important; } :host([disabled]) { - pointer-events: none !important; + pointer-events: none !important; } #outer.disabled { - color: var(--pf-global--Color--dark-200, #6a6e73) !important; + color: var(--pf-global--Color--dark-200, #6a6e73) !important; } #outer { - position: relative; + position: relative; } #listbox-container { - display: inline-flex; - position: absolute; - background-color: var(--pf-theme--color--surface--lightest, #fff) !important; - opacity: 0; - --_active-descendant-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; + display: inline-flex; + position: absolute; + background-color: var(--pf-theme--color--surface--lightest, #fff) !important; + opacity: 0; + --_active-descendant-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; box-shadow: 0 0.25rem 0.5rem 0rem rgba(3, 3, 3, 0.12), 0 0 0.25rem 0 rgba(3, 3, 3, 0.06); } #outer.expanded #listbox-container { - opacity: 1; - z-index: 9999 !important; + opacity: 1; + z-index: 9999 !important; max-height: 220px; overflow: hidden; } #listbox { - display: flex; - flex-direction: column; - position: relative; - width: 100%; + display: flex; + flex-direction: column; + position: relative; + width: 100%; } #listbox slot.disabled { - color: var(--pf-c-list__item-icon--Color, #6a6e73) !important; - background-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; - border-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; - pointer-events: none; - cursor: not-allowed;; - --_active-descendant-color: transparent; - --_svg-color: var(--pf-c-list__item-icon--Color, #6a6e73) !important; + color: var(--pf-c-list__item-icon--Color, #6a6e73) !important; + background-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; + border-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; + pointer-events: none; + cursor: not-allowed; + ; + --_active-descendant-color: transparent; + --_svg-color: var(--pf-c-list__item-icon--Color, #6a6e73) !important; } #toggle { - background-color: var(--pf-theme--color--surface--lightest, #fff) !important; + background-color: var(--pf-theme--color--surface--lightest, #fff) !important; } #toggle, #toggle-input { - display: flex; - font-family: var(--pf-global--FontFamily--sans-serif, "RedHatTextUpdated", "Overpass", overpass, helvetica, arial, sans-serif); - font-size: var(--pf-global--FontSize--md, 16px); - font-weight: var(--pf-global--FontWeight--normal, 400); - line-height: 1.6; + display: flex; + font-family: var(--pf-global--FontFamily--sans-serif, "RedHatTextUpdated", "Overpass", overpass, helvetica, arial, sans-serif); + font-size: var(--pf-global--FontSize--md, 16px); + font-weight: var(--pf-global--FontWeight--normal, 400); + line-height: 1.6; } #toggle { - border: 1px solid var(--pf-global--BorderColor--100, #d2d2d2); - border-bottom-color: var(--pf-theme--color--text, #151515); - justify-content: space-between; + border: 1px solid var(--pf-global--BorderColor--100, #d2d2d2); + border-bottom-color: var(--pf-theme--color--text, #151515); + justify-content: space-between; } .disabled #toggle { - color: var(--pf-global--Color--dark-200, #6a6e73) !important; - background-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; - border-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; + color: var(--pf-global--Color--dark-200, #6a6e73) !important; + background-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; + border-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; } /* #toggle-button, */ #toggle-input { - background: transparent; - border: none; - text-align: left; - border-radius: 0; - padding-left: 3rem; /*Change it to variable*/ + background: transparent; + border: none; + text-align: left; + border-radius: 0; + padding-left: 3rem; + /*Change it to variable*/ } #toggle-input { - justify-content: space-between; + justify-content: space-between; min-width: calc(100% - 33px); box-sizing: border-box; height: 2.25rem; } .disabled #toggle-input { - pointer-events: none; + pointer-events: none; } #close-button { @@ -262,8 +265,8 @@ --pf-c-button--PaddingTop: var(--pf-global--spacer--xs, 0.25rem); --pf-c-button--PaddingBottom: var(--pf-global--spacer--xs, 0.25rem); - color: currentColor; - background-color: transparent; + color: currentColor; + background-color: transparent; max-height: 2.25rem; max-width: 2.25rem; box-sizing: border-box; @@ -279,98 +282,101 @@ } } -.close-button-container{ +.close-button-container { height: 2.25rem; width: 2.25rem; } #toggle-text { - flex: 1 1 auto; + flex: 1 1 auto; } #description { - display: block; + display: block; } #listbox.checkboxes { - --_pf-option-checkboxes-display: none; - --_pf-option-svg-display: none; + --_pf-option-checkboxes-display: none; + --_pf-option-svg-display: none; } .visually-hidden { - border: 0; - clip: rect(0, 0, 0, 0); - block-size: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - white-space: nowrap; - inline-size: 1px; + border: 0; + clip: rect(0, 0, 0, 0); + block-size: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + inline-size: 1px; } ::slotted(hr) { - --pf-c-divider--BorderWidth--base: var(--pf-global--BorderWidth--sm, 1px); - --pf-c-divider--BorderColor--base: var(--pf-c-divider--BackgroundColor); - --pf-c-divider--Height: var(--pf-c-divider--BorderWidth--base); - --pf-c-divider--BackgroundColor: var(--pf-global--BorderColor--100, #d2d2d2); - --pf-c-divider--after--BackgroundColor: var(--pf-c-divider--BorderColor--base); - --pf-c-divider--after--FlexBasis: 100%; - --pf-c-divider--after--Inset: 0%; - --pf-c-divider--m-vertical--after--FlexBasis: 100%; - --pf-c-divider--m-horizontal--Display: flex; - --pf-c-divider--m-horizontal--FlexDirection: row; - --pf-c-divider--m-horizontal--after--Height: var(--pf-c-divider--Height); - --pf-c-divider--m-horizontal--after--Width: auto; - --pf-c-divider--m-vertical--Display: inline-flex; - --pf-c-divider--m-vertical--FlexDirection: column; - --pf-c-divider--m-vertical--after--Height: auto; - --pf-c-divider--m-vertical--after--Width: var(--pf-c-divider--BorderWidth--base); - --pf-hidden-visible--visible--Display: var(--pf-c-divider--Display); - --pf-c-divider--Display: var(--pf-c-divider--m-horizontal--Display); - --pf-c-divider--FlexDirection: var(--pf-c-divider--m-horizontal--FlexDirection); - --pf-c-divider--after--Width: var(--pf-c-divider--m-horizontal--after--Width); - --pf-c-divider--after--Height: var(--pf-c-divider--m-horizontal--after--Height); - display: var(--pf-c-divider--Display, flex); + --pf-c-divider--BorderWidth--base: var(--pf-global--BorderWidth--sm, 1px); + --pf-c-divider--BorderColor--base: var(--pf-c-divider--BackgroundColor); + --pf-c-divider--Height: var(--pf-c-divider--BorderWidth--base); + --pf-c-divider--BackgroundColor: var(--pf-global--BorderColor--100, #d2d2d2); + --pf-c-divider--after--BackgroundColor: var(--pf-c-divider--BorderColor--base); + --pf-c-divider--after--FlexBasis: 100%; + --pf-c-divider--after--Inset: 0%; + --pf-c-divider--m-vertical--after--FlexBasis: 100%; + --pf-c-divider--m-horizontal--Display: flex; + --pf-c-divider--m-horizontal--FlexDirection: row; + --pf-c-divider--m-horizontal--after--Height: var(--pf-c-divider--Height); + --pf-c-divider--m-horizontal--after--Width: auto; + --pf-c-divider--m-vertical--Display: inline-flex; + --pf-c-divider--m-vertical--FlexDirection: column; + --pf-c-divider--m-vertical--after--Height: auto; + --pf-c-divider--m-vertical--after--Width: var(--pf-c-divider--BorderWidth--base); + --pf-hidden-visible--visible--Display: var(--pf-c-divider--Display); + --pf-c-divider--Display: var(--pf-c-divider--m-horizontal--Display); + --pf-c-divider--FlexDirection: var(--pf-c-divider--m-horizontal--FlexDirection); + --pf-c-divider--after--Width: var(--pf-c-divider--m-horizontal--after--Width); + --pf-c-divider--after--Height: var(--pf-c-divider--m-horizontal--after--Height); + display: var(--pf-c-divider--Display, flex); flex-direction: var(--pf-c-divider--FlexDirection); border: 0; - width: 100%; - margin-top: var(--pf-c-search-input-menu--c-divider--MarginTop); - margin-bottom: var(--pf-c-search-input-menu--c-divider--MarginBottom); + width: 100%; + margin-top: var(--pf-c-search-input-menu--c-divider--MarginTop); + margin-bottom: var(--pf-c-search-input-menu--c-divider--MarginBottom); } ::slotted(hr)::after { - content: ''; - width: var(--pf-c-divider--after--Width, 100%) !important; - height: var(--pf-c-divider--after--Height, 1px); - background-color: var(--pf-c-divider--after--BackgroundColor); - flex: 1 0 100%; + content: ''; + width: var(--pf-c-divider--after--Width, 100%) !important; + height: var(--pf-c-divider--after--Height, 1px); + background-color: var(--pf-c-divider--after--BackgroundColor); + flex: 1 0 100%; } div.search-icon { position: absolute; - top: 50%; - left: var(--pf-global--spacer--md, 1rem); - transform: translateY(-50%); - display: flex; - align-items: center; + top: 50%; + left: var(--pf-global--spacer--md, 1rem); + transform: translateY(-50%); + display: flex; + align-items: center; } #outer:focus-within { #toggle { border-bottom: none; border-bottom-left-radius: 4px; + #toggle-input { - border-bottom: var(--pf-global--spacer--xs, 0.125rem) solid var(--pf-theme--color--accent, #0066cc); + border-bottom: var(--pf-global--spacer--xs, 0.125rem) solid var(--pf-theme--color--accent, #0066cc); } } + .close-button-container { position: relative; - &::after{ + + &::after { content: ''; width: 2.25rem; - height: var(--pf-global--spacer--xs, 0.125rem); + height: var(--pf-global--spacer--xs, 0.125rem); bottom: 0px; left: -3px; background-color: var(--pf-theme--color--accent, #0066cc); @@ -406,5 +412,5 @@ pf-text-input { .submit-button-container { position: absolute; top: 0; - right: -100px; + right: -100px; } \ No newline at end of file diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 9114a7e607..032f6a3f06 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -94,9 +94,9 @@ export class PfSearchInput extends LitElement { #combobox = ComboboxController.of(this, { getItems: () => this.options, getFallbackLabel: () => this.accessibleLabel - || this.#internals.computedLabelText - || this.placeholder - || this.#slots.getSlotted('placeholder').map(x => x.textContent).join(''), + || this.#internals.computedLabelText + || this.placeholder + || this.#slots.getSlotted('placeholder').map(x => x.textContent).join(''), getListboxElement: () => this._listbox ?? null, getToggleButton: () => this._toggleButton ?? null, getComboboxInput: () => this._toggleInput ?? null, From fc1bcbaa678d33f0c42f0de8e241457de8fa75f9 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Mon, 14 Jul 2025 18:23:14 +0530 Subject: [PATCH 45/85] chore: submit button function updated --- elements/pf-search-input/pf-search-input.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 032f6a3f06..20711afbe2 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -172,8 +172,7 @@ export class PfSearchInput extends LitElement { const hideLightDomItems = !ComboboxController.supportsCrossRootActiveDescendant; return html` -
+
-
+
From 83faa650c1f960486db7a141be0a9a21a938ae22 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Tue, 15 Jul 2025 17:35:39 +0530 Subject: [PATCH 46/85] chore: search input with submit button variant added --- .../demo/pf-search-input-with-submit.html | 70 ++++++----- elements/pf-search-input/pf-search-input.css | 25 ---- elements/pf-search-input/pf-search-input.ts | 110 +++++++----------- 3 files changed, 86 insertions(+), 119 deletions(-) diff --git a/elements/pf-search-input/demo/pf-search-input-with-submit.html b/elements/pf-search-input/demo/pf-search-input-with-submit.html index bad39ab083..3e9d7ce954 100644 --- a/elements/pf-search-input/demo/pf-search-input-with-submit.html +++ b/elements/pf-search-input/demo/pf-search-input-with-submit.html @@ -1,29 +1,32 @@ -
+

Search with autocomplete

- - Search - Alabama - New Jersey - New York - New Mexico - North Carolina - Alabama 1 - New Jersey 1 - New York 1 - New Mexico 1 - North Carolina 1 - Alabama 2 - New Jersey 2 - New York 2 - New Mexico 2 - North Carolina 2 - Alabama 3 - New Jersey 3 - New York 3 - New Mexico 3 - North Carolina 3 - -
+
+ + Alabama + New Jersey + New York + New Mexico + North Carolina + Alabama 1 + New Jersey 1 + New York 1 + New Mexico 1 + North Carolina 1 + Alabama 2 + New Jersey 2 + New York 2 + New Mexico 2 + North Carolina 2 + Alabama 3 + New Jersey 3 + New York 3 + New Mexico 3 + North Carolina 3 + + Search +
+ + { + event.preventDefault(); + /* eslint-disable no-console */ + console.log("Value:", form.elements.search?.value); + /* eslint-disable no-console */ + }) \ No newline at end of file diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index a6c6a6c770..631dfe29e5 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -388,29 +388,4 @@ div.search-icon { ::slotted(pf-option[selected]) { --_pf-option-svg-display: none; --_pf-option-selected-background-color: var(--pf-global--BackgroundColor--100, #fff); -} - -pf-text-input { - --pf-c-form-control--LineHeight: 36px; - --pf-c-form-control--PaddingTop: 0px; - --pf-c-form-control--PaddingBottom: 0px; - --pf-c-form-control--PaddingLeft: 2.5rem; - --pf-c-form-control--BorderWidth: 0px; - --pf-c-form-control--Width: 100%; - - border: none; - box-sizing: border-box; -} - -.search-input-container { - display: flex; - align-items: center; - justify-content: flex-start; - position: relative; -} - -.submit-button-container { - position: absolute; - top: 0; - right: -100px; } \ No newline at end of file diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 20711afbe2..603b3a67ec 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -17,7 +17,6 @@ import { arraysAreEquivalent } from '@patternfly/pfe-core/functions/arraysAreEqu import { observes } from '@patternfly/pfe-core/decorators/observes.js'; import { PfOption } from '../pf-select/pf-option.js'; import { bound } from '@patternfly/pfe-core/decorators.js'; -import '@patternfly/elements/pf-text-input/pf-text-input.js'; import styles from './pf-search-input.css'; export class PfSearchChangeEvent extends Event { @@ -83,8 +82,6 @@ export class PfSearchInput extends LitElement { @query('#outer') private _searchInputContainer!: HTMLElement; - // #isNotPlaceholderOption = (option: PfOption) => option !== this._placeholder; - #internals = InternalsController.of(this); #float = new FloatingDOMController(this, { content: () => this._listboxContainer }); @@ -172,51 +169,46 @@ export class PfSearchInput extends LitElement { const hideLightDomItems = !ComboboxController.supportsCrossRootActiveDescendant; return html` -
-
-
-
- search -
- -
- - close - -
- +
+
+
+ search
-
-
- ${this.#combobox.renderItemsToShadowRoot()} - -
+
+ + close +
+
-
- +
+
+ ${this.#combobox.renderItemsToShadowRoot()} + +
`; @@ -252,7 +244,6 @@ export class PfSearchInput extends LitElement { this.dispatchEvent(new PfSearchChangeEvent()); } - async #doExpand() { try { await this.#float.show({ placement: this.position || 'bottom', flip: !!this.enableFlip }); @@ -314,34 +305,17 @@ export class PfSearchInput extends LitElement { return false; } - #onSearchInput(event: KeyboardEvent) { - if (event.key === 'Enter' || event.key === ' ') { - this.value = this._toggleInput?.value; - this.#internals.setFormValue(this.value ?? ''); - this.dispatchEvent(new PfSearchChangeEvent()); - } + #onChange(event: Event) { + this.value = this._toggleInput?.value; + this.#internals.setFormValue(this.value ?? ''); + this.dispatchEvent(new PfSearchChangeEvent()); } - #onSubmit(event: MouseEvent | KeyboardEvent) { - const path = event.composedPath(); - const slottedSearchButton = path.find(el => - el instanceof HTMLElement - && el.tagName === 'PF-BUTTON' - && el.getAttribute('data-action') === 'search' - ); - - if (slottedSearchButton && this._toggleInput?.value) { - this.value = this._toggleInput?.value; - this.#internals.setFormValue(this.value ?? ''); + #onSubmit(event: KeyboardEvent) { + if (event.key === 'Enter' || event.key === ' ') { this.dispatchEvent(new PfSearchChangeEvent()); } } - - #handleKeyDown(e: KeyboardEvent) { - if (e.key === 'Enter' || e.key === ' ') { - this.#onSubmit(e); - } - } } declare global { From b00c9ad5f2bee1c178acf0cec2abcbd3de020786 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Tue, 15 Jul 2025 21:48:10 +0530 Subject: [PATCH 47/85] chore: display listbox only when input is entered in the textbox --- elements/pf-search-input/pf-search-input.css | 2 -- elements/pf-search-input/pf-search-input.ts | 22 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index 631dfe29e5..1af6dc1ba1 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -190,8 +190,6 @@ #outer.expanded #listbox-container { opacity: 1; z-index: 9999 !important; - max-height: 220px; - overflow: hidden; } #listbox { diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 603b3a67ec..28265f3513 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -98,7 +98,7 @@ export class PfSearchInput extends LitElement { getToggleButton: () => this._toggleButton ?? null, getComboboxInput: () => this._toggleInput ?? null, isExpanded: () => this.expanded, - requestShowListbox: () => void (this.expanded ||= true), + requestShowListbox: () => this.#showListbox(), requestHideListbox: () => void (this.expanded &&= false), setItemHidden: (item, hidden) => (item.id !== 'placeholder') && void (item.hidden = hidden), isItem: item => item instanceof PfOption, @@ -181,7 +181,7 @@ export class PfSearchInput extends LitElement { @@ -244,6 +244,13 @@ export class PfSearchInput extends LitElement { this.dispatchEvent(new PfSearchChangeEvent()); } + @observes('value') + private collapseOnEmpty() { + if (this.value === '') { + this.expanded = false; + } + } + async #doExpand() { try { await this.#float.show({ placement: this.position || 'bottom', flip: !!this.enableFlip }); @@ -316,6 +323,17 @@ export class PfSearchInput extends LitElement { this.dispatchEvent(new PfSearchChangeEvent()); } } + + #delay(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + async #showListbox() { + await this.#delay(10); + if (this.value !== '') { + this.expanded ||= true; + } + } } declare global { From 7a8ac31ea7cd4b56b167c73fa5408d6c3a7497ac Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Sat, 19 Jul 2025 21:54:01 +0530 Subject: [PATCH 48/85] chore: test cases updated --- .../test/pf-search-input.spec.ts | 218 ++++++++++-------- 1 file changed, 121 insertions(+), 97 deletions(-) diff --git a/elements/pf-search-input/test/pf-search-input.spec.ts b/elements/pf-search-input/test/pf-search-input.spec.ts index 2780801e7d..65f18028ef 100644 --- a/elements/pf-search-input/test/pf-search-input.spec.ts +++ b/elements/pf-search-input/test/pf-search-input.spec.ts @@ -75,6 +75,12 @@ describe('', function() { 1 2 3 + 11 + 22 + 33 + 111 + 222 + 333 `); }); @@ -95,7 +101,7 @@ describe('', function() { it('sets aria-setsize="3" and aria-posinset on items', function() { element.options.forEach((option, i) => { - expect(option).to.have.attr('aria-setsize', '3'); + expect(option).to.have.attr('aria-setsize', '9'); expect(option).to.have.attr('aria-posinset', `${i + 1}`); }); }); @@ -103,18 +109,22 @@ describe('', function() { describe('focus()', function() { beforeEach(press('Tab')); beforeEach(updateComplete); + beforeEach(press('1')); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); + + it('labels the listbox with the accessible-label attribute', async function() { + const snap = await a11ySnapshot(); + expect(snap).to.axContainQuery({ + role: 'listbox', + name: 'label', + }); + }); + describe('ArrowDown', function() { beforeEach(press('ArrowDown')); beforeEach(updateComplete); - it('labels the listbox with the accessible-label attribute', async function() { - const snap = await a11ySnapshot(); - expect(snap).to.axContainQuery({ - role: 'listbox', - name: 'label', - }); - }); - it('focuses on the first item', async function() { expect(getActiveOption(element)).to.have.value('1'); }); @@ -163,13 +173,15 @@ describe('', function() { describe('focus()', function() { beforeEach(press('Tab')); beforeEach(updateComplete); - describe('ArrowDown', function() { - beforeEach(press('ArrowDown')); - it('labels the listbox with the label elements', async function() { - expect(await a11ySnapshot()).to.axContainQuery({ - role: 'listbox', - name: 'label1label2', - }); + beforeEach(press('1')); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); + + it('labels the listbox with the label elements', async function() { + const snap = await a11ySnapshot(); + expect(snap).to.axContainQuery({ + role: 'listbox', + name: 'label1label2', }); }); }); @@ -225,6 +237,9 @@ describe('', function() { describe('expanding', function() { beforeEach(focus); beforeEach(press('Enter')); + beforeEach(press('1')); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); describe('ArrowDown', function() { beforeEach(press('ArrowDown')); beforeEach(updateComplete); @@ -251,9 +266,9 @@ describe('', function() { element = await createFixture(html` 1 - 2 - 3 - 4 + 12 + 13 + 14 5 6 7 @@ -275,13 +290,17 @@ describe('', function() { describe('click combobox button', function() { beforeEach(() => clickElementAtCenter(element)); beforeEach(updateComplete); + beforeEach(press('1')); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); it('does not pass aXe audit', async function() { await expect(element).to.not.be.accessible(); }); it('expands the listbox', async function() { - expect(await a11ySnapshot()).to.axContainRole('listbox'); + const snap = await a11ySnapshot(); + expect(snap).to.axContainRole('listbox'); }); describe('Tab', function() { @@ -324,6 +343,9 @@ describe('', function() { describe('Home', function() { beforeEach(press('Home')); beforeEach(updateComplete); + beforeEach(press('1')); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); it('expands the listbox', async function() { expect(await a11ySnapshot()).to.axContainRole('listbox'); @@ -333,6 +355,9 @@ describe('', function() { describe('End', function() { beforeEach(press('End')); beforeEach(updateComplete); + beforeEach(press('1')); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); it('expands the listbox', async function() { expect(await a11ySnapshot()).to.axContainRole('listbox'); @@ -340,6 +365,9 @@ describe('', function() { }); describe('ArrowDown', function() { + beforeEach(press('1')); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); beforeEach(press('ArrowDown')); beforeEach(updateComplete); @@ -353,7 +381,7 @@ describe('', function() { beforeEach(updateComplete); it('focuses on option 2', async function() { - expect(getActiveOption(element)).to.have.value('2'); + expect(getActiveOption(element)).to.have.value('12'); }); describe('ArrowUp', function() { @@ -368,7 +396,7 @@ describe('', function() { beforeEach(press('ArrowDown')); beforeEach(updateComplete); it('focuses on option 3', async function() { - expect(getActiveOption(element)).to.have.value('3'); + expect(getActiveOption(element)).to.have.value('13'); }); describe('Enter', function() { @@ -377,14 +405,14 @@ describe('', function() { it('selects option 3', function() { expect(getSelectedOptionValue(element)).to.deep.equal([ - '3', + '13', ]); }); it('exposes selection to assistive technology', async function() { expect(await a11ySnapshot()).to.axContainQuery({ role: 'combobox', - value: '3', + value: '13', }); }); @@ -426,6 +454,9 @@ describe('', function() { element = await createFixture(html` Blue + Black + Brown + Bronze Green Magenta Orange @@ -479,49 +510,69 @@ describe('', function() { beforeEach(async function() { await clickElementAtOffset(element, [10, 10]); }); + describe('\'B\'', function() { + beforeEach(press('B')); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); - it('shows the listbox', async function() { - expect(element.expanded).to.be.true; - expect(await a11ySnapshot()).to.axContainRole('listbox'); - }); - - it('focuses the combobox', async function() { - expect(element.expanded).to.be.true; - expect(await a11ySnapshot()).to.axContainQuery({ - focused: true, - role: 'combobox', + it('shows the listbox', async function() { + expect(element.expanded).to.be.true; + expect(await a11ySnapshot()).to.axContainRole('listbox'); }); - }); - describe('clicking option 1', function() { - beforeEach(async function() { - await clickItemAtIndex(element, 0); + it('focuses the combobox', async function() { + expect(element.expanded).to.be.true; + expect(await a11ySnapshot()).to.axContainQuery({ + focused: true, + role: 'combobox', + }); }); - it('selects option 1', function() { - expect(getSelectedOptionValue(element)).to.deep.equal([ - 'Blue', - ]); - }); + describe('clicking option 1', function() { + beforeEach(async function() { + await clickItemAtIndex(element, 0); + }); - it('closes the listbox', async function() { - expect(await a11ySnapshot()).to.not.axContainRole('listbox'); - }); - }); + it('selects option 1', function() { + expect(getSelectedOptionValue(element)).to.deep.equal([ + 'Blue', + ]); + }); - describe('clicking option 2', function() { - beforeEach(async function() { - await clickItemAtIndex(element, 1); + it('closes the listbox', async function() { + expect(await a11ySnapshot()).to.not.axContainRole('listbox'); + }); }); - it('selects option 1', function() { - expect(getSelectedOptionValue(element)).to.deep.equal([ - 'Green', - ]); + describe('clicking option 2', function() { + beforeEach(async function() { + await clickItemAtIndex(element, 1); + }); + + it('selects option 1', function() { + expect(getSelectedOptionValue(element)).to.deep.equal([ + 'Black', + ]); + }); + + it('closes the listbox', async function() { + expect(await a11ySnapshot()).to.not.axContainRole('listbox'); + }); }); + }); + }); - it('closes the listbox', async function() { - expect(await a11ySnapshot()).to.not.axContainRole('listbox'); + describe('focus()', function() { + beforeEach(press('Tab')); + beforeEach(updateComplete); + beforeEach(press('r')); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); + describe('"r"', function() { + it('only shows options that start with "r" or "R"', async function() { + expect(getVisibleOptionValues(element)).to.deep.equal([ + 'Red', + ]); }); }); }); @@ -532,8 +583,10 @@ describe('', function() { describe('"r"', function() { beforeEach(press('r')); + beforeEach(() => aTimeout(300)); beforeEach(updateComplete); + it('only shows options that start with "r" or "R"', async function() { expect(getVisibleOptionValues(element)).to.deep.equal([ 'Red', @@ -563,6 +616,8 @@ describe('', function() { }); describe('ArrowDown', function() { + beforeEach(press('B')); + beforeEach(updateComplete); beforeEach(press('ArrowDown')); beforeEach(updateComplete); beforeEach(() => aTimeout(200)); @@ -594,7 +649,7 @@ describe('', function() { beforeEach(updateComplete); it('focuses option 2', function() { - expect(getActiveOption(element)).to.have.text('Green'); + expect(getActiveOption(element)).to.have.text('Black'); }); describe('Enter', function() { @@ -603,14 +658,14 @@ describe('', function() { it('selects option 2', function() { expect(getSelectedOptionValue(element)).to.deep.equal([ - 'Green', + 'Black', ]); }); it('sets typeahead input to second option value', async function() { expect(await a11ySnapshot()) .axTreeFocusedNode - .to.have.axProperty('value', 'Green'); + .to.have.axProperty('value', 'Black'); }); it('retains focus on combobox input', async function() { @@ -620,24 +675,6 @@ describe('', function() { it('hides the listbox', async function() { expect(await a11ySnapshot()).to.not.axContainRole('listbox'); }); - - describe('focus()', function() { - beforeEach(focus); - describe('ArrowDown', function() { - beforeEach(press('ArrowDown')); - beforeEach(updateComplete); - - it('focuses option 2', function() { - expect(getActiveOption(element)).to.have.text('Green'); - }); - - it('only shows option 2', function() { - expect(getVisibleOptionValues(element)).to.deep.equal([ - 'Green', - ]); - }); - }); - }); }); }); @@ -645,8 +682,8 @@ describe('', function() { beforeEach(press('ArrowUp')); beforeEach(updateComplete); - it('focuses the last item', async function() { - expect(getActiveOption(element)).to.have.value('Yellow'); + it('focuses the last filtered item', async function() { + expect(getActiveOption(element)).to.have.value('Bronze'); }); }); }); @@ -675,6 +712,7 @@ describe('', function() { describe('"p"', function() { beforeEach(press('p')); + beforeEach(() => aTimeout(300)); beforeEach(updateComplete); it('shows the listbox and maintains focus', async function() { @@ -697,27 +735,11 @@ describe('', function() { beforeEach(press('Backspace')); beforeEach(updateComplete); - it('shows the listbox and maintains focus', async function() { + it('hides the listbox', async function() { expect(await a11ySnapshot()) - .to.axContainRole('listbox') - .and.axTreeFocusedNode - .to.have.axRole('combobox') + .to.not.axContainRole('listbox') .and.to.not.have.axProperty('value', 'p'); }); - - it('all options are visible', async function() { - expect(getVisibleOptionValues(element)).to.deep.equal([ - 'Blue', - 'Green', - 'Magenta', - 'Orange', - 'Purple', - 'Periwinkle', - 'Pink', - 'Red', - 'Yellow', - ]); - }); }); describe('"u"', function() { @@ -754,6 +776,8 @@ describe('', function() { beforeEach(press('Backspace')); beforeEach(press('Backspace')); beforeEach(press('Backspace')); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); it('shows the options starting with "P"', function() { expect(getVisibleOptionValues(element)).to.deep.equal([ From 8d27b71aab5519f0f36946b311972488d5c1486a Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Sun, 20 Jul 2025 00:10:37 +0530 Subject: [PATCH 49/85] chore: updated documentation --- .../demo/pf-search-input-with-submit.html | 1 - .../pf-search-input/demo/pf-search-input.html | 2 - .../pf-search-input/docs/pf-search-input.md | 36 +++++++- elements/pf-search-input/pf-search-input.css | 83 ------------------- elements/pf-search-input/pf-search-input.ts | 78 ++++++++++++++++- 5 files changed, 109 insertions(+), 91 deletions(-) diff --git a/elements/pf-search-input/demo/pf-search-input-with-submit.html b/elements/pf-search-input/demo/pf-search-input-with-submit.html index 3e9d7ce954..4282ef9e0f 100644 --- a/elements/pf-search-input/demo/pf-search-input-with-submit.html +++ b/elements/pf-search-input/demo/pf-search-input-with-submit.html @@ -1,5 +1,4 @@
-

Search with autocomplete

Alabama diff --git a/elements/pf-search-input/demo/pf-search-input.html b/elements/pf-search-input/demo/pf-search-input.html index f8842937ab..bfc54a1ee2 100644 --- a/elements/pf-search-input/demo/pf-search-input.html +++ b/elements/pf-search-input/demo/pf-search-input.html @@ -1,5 +1,4 @@
-

Search with autocomplete

Alabama New Jersey @@ -34,7 +33,6 @@

Search with autocomplete

console.log('Selected:', event.target.value); /* eslint-disable no-console */ }); - \ No newline at end of file diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index edf11a81e7..c2145a932e 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -68,6 +68,11 @@ --pf-c-search-input__toggle-clear--toggle-button--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); --pf-c-search-input__toggle-button--Color: var(--pf-global--Color--100, #151515); --pf-c-search-input__list-item--m-loading--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); + + /* --pf-c-search-input__toggle--FontSize: var(--pf-global--FontSize--md, 1rem); + --pf-c-search-input__toggle--FontWeight: var(--pf-global--FontWeight--normal, 400); + --pf-c-search-input__toggle--LineHeight: var(--pf-global--LineHeight--md, 1.5); + --pf-c-search-input__toggle--BackgroundColor: var(--pf-global--BackgroundColor--100, #fff); */ } :host, @@ -83,8 +88,9 @@ display: none !important; } -:host([disabled]) { +:host([aria-disabled="true"]) { pointer-events: none !important; + cursor: not-allowed !important; } #outer.disabled { @@ -107,6 +113,8 @@ #outer.expanded #listbox-container { opacity: 1; z-index: 9999 !important; + max-height: 300px; + overflow: hidden; } #listbox { @@ -122,22 +130,22 @@ border-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; pointer-events: none; cursor: not-allowed; - ; + --_active-descendant-color: transparent; --_svg-color: var(--pf-c-list__item-icon--Color, #6a6e73) !important; } #toggle { - background-color: var(--pf-theme--color--surface--lightest, #fff) !important; + background-color: var(--pf-c-search-input__toggle--BackgroundColor, #fff) !important; } #toggle, #toggle-input { display: flex; font-family: var(--pf-global--FontFamily--sans-serif, "RedHatTextUpdated", "Overpass", overpass, helvetica, arial, sans-serif); - font-size: var(--pf-global--FontSize--md, 16px); - font-weight: var(--pf-global--FontWeight--normal, 400); - line-height: 1.6; + font-size: var(--pf-c-search-input__toggle--FontSize, 1rem); + font-weight: var( --pf-c-search-input__toggle--FontWeight, 400); + line-height: var(--pf-c-search-input__toggle--LineHeight, 1.5); } #toggle { @@ -160,7 +168,6 @@ text-align: left; border-radius: 0; padding-left: 3rem; - /*Change it to variable*/ } #toggle-input { @@ -172,6 +179,7 @@ .disabled #toggle-input { pointer-events: none; + cursor: not-allowed; } #close-button { diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 35768dfb76..efbd9938d7 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -174,8 +174,8 @@ export class PfSearchInput extends LitElement { requestHideListbox: () => void (this.expanded &&= false), setItemHidden: (item, hidden) => (item.id !== 'placeholder') && void (item.hidden = hidden), isItem: item => item instanceof PfOption, - setItemActive: (item, active) => item.active = active, - setItemSelected: (item, selected) => item.selected = selected, + setItemActive: (item, active) => this.#setItemActive(item, active), + setItemSelected: (item, selected) => this.#setItemSelected(item, selected), }); static { @@ -252,9 +252,10 @@ export class PfSearchInput extends LitElement {
@@ -316,13 +317,6 @@ export class PfSearchInput extends LitElement { this.dispatchEvent(new PfSearchChangeEvent()); } - @observes('value') - private collapseOnEmpty() { - if (this.value === '') { - this.expanded = false; - } - } - async #doExpand() { try { await this.#float.show({ placement: this.position || 'bottom', flip: !!this.enableFlip }); @@ -396,16 +390,41 @@ export class PfSearchInput extends LitElement { } } + #onKeyDown(event: KeyboardEvent) { + const target = event.target as HTMLElement; + if (target?.getAttribute('aria-disabled') === 'true') { + // Allow Tab and Shift+Tab to move focus + if (event.key === 'Tab') { + return; + } + event.preventDefault(); + event.stopImmediatePropagation(); + } + } + #delay(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } async #showListbox() { await this.#delay(10); - if (this.value !== '') { + if (!this.disabled) { this.expanded ||= true; } } + + #setItemSelected(item: PfOption, selected: boolean) { + item.selected = selected; + this.#setItemActive(item, selected); + } + + #setItemActive(item: PfOption, active: boolean) { + item.active = active; + if (this.expanded) { + const activeOption = this.querySelector('pf-option[active]'); + activeOption?.scrollIntoView({ behavior: 'auto', block: 'nearest', inline: 'nearest' }); + } + } } declare global { diff --git a/elements/pf-search-input/test/pf-search-input.spec.ts b/elements/pf-search-input/test/pf-search-input.spec.ts index 65f18028ef..2c07212add 100644 --- a/elements/pf-search-input/test/pf-search-input.spec.ts +++ b/elements/pf-search-input/test/pf-search-input.spec.ts @@ -75,12 +75,6 @@ describe('', function() { 1 2 3 - 11 - 22 - 33 - 111 - 222 - 333 `); }); @@ -101,7 +95,7 @@ describe('', function() { it('sets aria-setsize="3" and aria-posinset on items', function() { element.options.forEach((option, i) => { - expect(option).to.have.attr('aria-setsize', '9'); + expect(option).to.have.attr('aria-setsize', '3'); expect(option).to.have.attr('aria-posinset', `${i + 1}`); }); }); @@ -109,22 +103,19 @@ describe('', function() { describe('focus()', function() { beforeEach(press('Tab')); beforeEach(updateComplete); - beforeEach(press('1')); - beforeEach(() => aTimeout(300)); - beforeEach(updateComplete); - - it('labels the listbox with the accessible-label attribute', async function() { - const snap = await a11ySnapshot(); - expect(snap).to.axContainQuery({ - role: 'listbox', - name: 'label', - }); - }); - describe('ArrowDown', function() { beforeEach(press('ArrowDown')); + beforeEach(() => aTimeout(300)); beforeEach(updateComplete); + it('labels the listbox with the accessible-label attribute', async function() { + const snap = await a11ySnapshot(); + expect(snap).to.axContainQuery({ + role: 'listbox', + name: 'label', + }); + }); + it('focuses on the first item', async function() { expect(getActiveOption(element)).to.have.value('1'); }); @@ -173,15 +164,15 @@ describe('', function() { describe('focus()', function() { beforeEach(press('Tab')); beforeEach(updateComplete); - beforeEach(press('1')); - beforeEach(() => aTimeout(300)); - beforeEach(updateComplete); - - it('labels the listbox with the label elements', async function() { - const snap = await a11ySnapshot(); - expect(snap).to.axContainQuery({ - role: 'listbox', - name: 'label1label2', + describe('ArrowDown', function() { + beforeEach(press('ArrowDown')); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); + it('labels the listbox with the label elements', async function() { + expect(await a11ySnapshot()).to.axContainQuery({ + role: 'listbox', + name: 'label1label2', + }); }); }); }); @@ -237,11 +228,9 @@ describe('', function() { describe('expanding', function() { beforeEach(focus); beforeEach(press('Enter')); - beforeEach(press('1')); - beforeEach(() => aTimeout(300)); - beforeEach(updateComplete); describe('ArrowDown', function() { beforeEach(press('ArrowDown')); + beforeEach(() => aTimeout(300)); beforeEach(updateComplete); it('remains expanded', function() { expect(element.expanded).to.be.true; @@ -266,9 +255,9 @@ describe('', function() { element = await createFixture(html` 1 - 12 - 13 - 14 + 2 + 3 + 4 5 6 7 @@ -289,8 +278,6 @@ describe('', function() { describe('click combobox button', function() { beforeEach(() => clickElementAtCenter(element)); - beforeEach(updateComplete); - beforeEach(press('1')); beforeEach(() => aTimeout(300)); beforeEach(updateComplete); @@ -299,8 +286,7 @@ describe('', function() { }); it('expands the listbox', async function() { - const snap = await a11ySnapshot(); - expect(snap).to.axContainRole('listbox'); + expect(await a11ySnapshot()).to.axContainRole('listbox'); }); describe('Tab', function() { @@ -342,8 +328,6 @@ describe('', function() { describe('Home', function() { beforeEach(press('Home')); - beforeEach(updateComplete); - beforeEach(press('1')); beforeEach(() => aTimeout(300)); beforeEach(updateComplete); @@ -354,8 +338,6 @@ describe('', function() { describe('End', function() { beforeEach(press('End')); - beforeEach(updateComplete); - beforeEach(press('1')); beforeEach(() => aTimeout(300)); beforeEach(updateComplete); @@ -365,10 +347,8 @@ describe('', function() { }); describe('ArrowDown', function() { - beforeEach(press('1')); - beforeEach(() => aTimeout(300)); - beforeEach(updateComplete); beforeEach(press('ArrowDown')); + beforeEach(() => aTimeout(300)); beforeEach(updateComplete); it('expands the listbox', async function() { @@ -381,7 +361,7 @@ describe('', function() { beforeEach(updateComplete); it('focuses on option 2', async function() { - expect(getActiveOption(element)).to.have.value('12'); + expect(getActiveOption(element)).to.have.value('2'); }); describe('ArrowUp', function() { @@ -396,7 +376,7 @@ describe('', function() { beforeEach(press('ArrowDown')); beforeEach(updateComplete); it('focuses on option 3', async function() { - expect(getActiveOption(element)).to.have.value('13'); + expect(getActiveOption(element)).to.have.value('3'); }); describe('Enter', function() { @@ -405,14 +385,14 @@ describe('', function() { it('selects option 3', function() { expect(getSelectedOptionValue(element)).to.deep.equal([ - '13', + '3', ]); }); it('exposes selection to assistive technology', async function() { expect(await a11ySnapshot()).to.axContainQuery({ role: 'combobox', - value: '13', + value: '3', }); }); @@ -454,9 +434,6 @@ describe('', function() { element = await createFixture(html` Blue - Black - Brown - Bronze Green Magenta Orange @@ -510,70 +487,50 @@ describe('', function() { beforeEach(async function() { await clickElementAtOffset(element, [10, 10]); }); - describe('\'B\'', function() { - beforeEach(press('B')); - beforeEach(() => aTimeout(300)); - beforeEach(updateComplete); + beforeEach(() => aTimeout(300)); + it('shows the listbox', async function() { + expect(element.expanded).to.be.true; + expect(await a11ySnapshot()).to.axContainRole('listbox'); + }); - it('shows the listbox', async function() { - expect(element.expanded).to.be.true; - expect(await a11ySnapshot()).to.axContainRole('listbox'); + it('focuses the combobox', async function() { + expect(element.expanded).to.be.true; + expect(await a11ySnapshot()).to.axContainQuery({ + focused: true, + role: 'combobox', }); + }); - it('focuses the combobox', async function() { - expect(element.expanded).to.be.true; - expect(await a11ySnapshot()).to.axContainQuery({ - focused: true, - role: 'combobox', - }); + describe('clicking option 1', function() { + beforeEach(async function() { + await clickItemAtIndex(element, 0); }); - describe('clicking option 1', function() { - beforeEach(async function() { - await clickItemAtIndex(element, 0); - }); - - it('selects option 1', function() { - expect(getSelectedOptionValue(element)).to.deep.equal([ - 'Blue', - ]); - }); - - it('closes the listbox', async function() { - expect(await a11ySnapshot()).to.not.axContainRole('listbox'); - }); + it('selects option 1', function() { + expect(getSelectedOptionValue(element)).to.deep.equal([ + 'Blue', + ]); }); - describe('clicking option 2', function() { - beforeEach(async function() { - await clickItemAtIndex(element, 1); - }); - - it('selects option 1', function() { - expect(getSelectedOptionValue(element)).to.deep.equal([ - 'Black', - ]); - }); - - it('closes the listbox', async function() { - expect(await a11ySnapshot()).to.not.axContainRole('listbox'); - }); + it('closes the listbox', async function() { + expect(await a11ySnapshot()).to.not.axContainRole('listbox'); }); }); - }); - describe('focus()', function() { - beforeEach(press('Tab')); - beforeEach(updateComplete); - beforeEach(press('r')); - beforeEach(() => aTimeout(300)); - beforeEach(updateComplete); - describe('"r"', function() { - it('only shows options that start with "r" or "R"', async function() { - expect(getVisibleOptionValues(element)).to.deep.equal([ - 'Red', + describe('clicking option 2', function() { + beforeEach(async function() { + await clickItemAtIndex(element, 1); + }); + + it('selects option 1', function() { + expect(getSelectedOptionValue(element)).to.deep.equal([ + 'Green', ]); }); + + it('closes the listbox', async function() { + expect(await a11ySnapshot()).to.not.axContainRole('listbox'); + }); }); }); @@ -586,7 +543,6 @@ describe('', function() { beforeEach(() => aTimeout(300)); beforeEach(updateComplete); - it('only shows options that start with "r" or "R"', async function() { expect(getVisibleOptionValues(element)).to.deep.equal([ 'Red', @@ -616,8 +572,6 @@ describe('', function() { }); describe('ArrowDown', function() { - beforeEach(press('B')); - beforeEach(updateComplete); beforeEach(press('ArrowDown')); beforeEach(updateComplete); beforeEach(() => aTimeout(200)); @@ -649,7 +603,7 @@ describe('', function() { beforeEach(updateComplete); it('focuses option 2', function() { - expect(getActiveOption(element)).to.have.text('Black'); + expect(getActiveOption(element)).to.have.text('Green'); }); describe('Enter', function() { @@ -658,14 +612,14 @@ describe('', function() { it('selects option 2', function() { expect(getSelectedOptionValue(element)).to.deep.equal([ - 'Black', + 'Green', ]); }); it('sets typeahead input to second option value', async function() { expect(await a11ySnapshot()) .axTreeFocusedNode - .to.have.axProperty('value', 'Black'); + .to.have.axProperty('value', 'Green'); }); it('retains focus on combobox input', async function() { @@ -675,6 +629,21 @@ describe('', function() { it('hides the listbox', async function() { expect(await a11ySnapshot()).to.not.axContainRole('listbox'); }); + + describe('focus()', function() { + beforeEach(focus); + describe('ArrowDown', function() { + beforeEach(press('ArrowDown')); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); + + it('only shows option 2', function() { + expect(getVisibleOptionValues(element)).to.deep.equal([ + 'Green', + ]); + }); + }); + }); }); }); @@ -682,8 +651,8 @@ describe('', function() { beforeEach(press('ArrowUp')); beforeEach(updateComplete); - it('focuses the last filtered item', async function() { - expect(getActiveOption(element)).to.have.value('Bronze'); + it('focuses the last item', async function() { + expect(getActiveOption(element)).to.have.value('Yellow'); }); }); }); @@ -735,11 +704,27 @@ describe('', function() { beforeEach(press('Backspace')); beforeEach(updateComplete); - it('hides the listbox', async function() { + it('shows the listbox and maintains focus', async function() { expect(await a11ySnapshot()) - .to.not.axContainRole('listbox') + .to.axContainRole('listbox') + .and.axTreeFocusedNode + .to.have.axRole('combobox') .and.to.not.have.axProperty('value', 'p'); }); + + it('all options are visible', async function() { + expect(getVisibleOptionValues(element)).to.deep.equal([ + 'Blue', + 'Green', + 'Magenta', + 'Orange', + 'Purple', + 'Periwinkle', + 'Pink', + 'Red', + 'Yellow', + ]); + }); }); describe('"u"', function() { @@ -762,6 +747,7 @@ describe('', function() { describe('Enter', function() { beforeEach(press('Enter')); + beforeEach(() => aTimeout(300)); beforeEach(updateComplete); it('selects the option "Purple"', function() { From 0333d28ec5ad24287c978063666bb08e68d0854a Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Tue, 22 Jul 2025 14:05:10 +0530 Subject: [PATCH 51/85] chore: updated documentation --- .../pf-search-input/docs/pf-search-input.md | 44 +++++++++++++++++++ elements/pf-search-input/pf-search-input.css | 6 +-- elements/pf-search-input/pf-search-input.ts | 14 +++++- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/elements/pf-search-input/docs/pf-search-input.md b/elements/pf-search-input/docs/pf-search-input.md index 54b70fdc71..e31bbc9203 100644 --- a/elements/pf-search-input/docs/pf-search-input.md +++ b/elements/pf-search-input/docs/pf-search-input.md @@ -34,8 +34,52 @@ import '@patternfly/elements/pf-search-input/pf-search-input.js'; {% renderFile "./elements/pf-search-input/demo/pf-search-input-with-submit.html" %} {% endhtmlexample %} +#### Disabled +{% htmlexample %} + {% renderFile "./elements/pf-search-input/demo/disabled.html" %} +{% endhtmlexample %} + {% endband %} +{% band header="Accessibility" %} + +The select uses the [Combobox Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/) recommendations from the WAI ARIA [Authoring Best Practices Guide (APG)](https://www.w3.org/WAI/ARIA/apg). + +When the dropdown is disabled it follows [WAI ARIA focusability recommendations](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#focusabilityofdisabledcontrols) for composite widget elements, where dropdown items are still focusable even when the dropdown is disabled. + +#### Toggle and typeahead input + +When focus is on the toggle, the following keyboard interactions apply: + +| Key | Function | +| ---------------------- | -------------------------------------------------------------------------------------- | +| Down Arrow | Opens the listbox and moves focus to the first listbox item. | +| Tab | Moves focus out of element onto the next focusable item and closes listbox. | +| Shift + Tab | Moves focus out of element onto the previous focusable item and closes listbox. | + +#### Listbox options + +Listbox options use the [APG's Roving tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex) recommendation. When focus is on the listbox, the following keyboard interactions apply: + +| Key | Function | +| ---------------------- | ------------------------------------------------------------------------------------- | +| Enter | Selects the options and closes the listbox. | +| Space | Selects the options and closes the listbox. | +| Tab | Moves focus out of element onto the next focusable options and closes listbox. | +| Shift + Tab | Moves focus to the toggle button and closes listbox. | +| Up Arrow | Moves focus to the previous option, optionally wrapping from the first to the last. | +| Down Arrow | Moves focus to the next option, optionally wrapping from the last to the first. | +| Left Arrow | Moves focus to the previous option, optionally wrapping from the first to the last. | +| Right Arrow | Moves focus to the next option, optionally wrapping from the last to the first. | +| Home | Moves focus to the first option in the current listbox. | +| Escape | Close the listbox that contains focus and return focus to the toggle button. | +| Any letter | Navigates to the next option that starts with the letter. | + +{% endband %} + + + + {% renderSlots %}{% endrenderSlots %} {% renderAttributes %}{% endrenderAttributes %} diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index c2145a932e..874b673a22 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -89,12 +89,12 @@ } :host([aria-disabled="true"]) { - pointer-events: none !important; - cursor: not-allowed !important; + pointer-events: none; + cursor: not-allowed; } #outer.disabled { - color: var(--pf-global--Color--dark-200, #6a6e73) !important; + color: var(--pf-global--Color--dark-200, #6a6e73); } #outer { diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index efbd9938d7..35133c05de 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -185,6 +185,11 @@ export class PfSearchInput extends LitElement { instance._onOutsideClick(event); } }); + document.addEventListener('focusout', () => { + for (const instance of PfSearchInput.instances) { + instance._onFocusOut(); + } + }); } } @@ -198,7 +203,7 @@ export class PfSearchInput extends LitElement { PfSearchInput.instances.delete(this); } - // Function to handle the closing of popover + // Function to handle the closing of popover on outside click @bound private _onOutsideClick(event: MouseEvent) { const path = event.composedPath(); if (!path.includes(this._searchInputContainer)) { @@ -208,6 +213,13 @@ export class PfSearchInput extends LitElement { } } + // Function to handle the closing of popover on focus out + @bound private _onFocusOut() { + if (this.expanded) { + this.expanded = false; + } + } + /** * Single select option value for single select menus, * or array of select option values for multi select. From 1035574f5711deae78a3fe0ce2e546962c56591c Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Tue, 22 Jul 2025 15:53:37 +0530 Subject: [PATCH 52/85] chore: variable added for listbox max-height --- .../pf-search-input/docs/pf-search-input.md | 27 +++++++++---------- elements/pf-search-input/pf-search-input.css | 19 +++++-------- elements/pf-search-input/pf-search-input.ts | 6 ++--- 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/elements/pf-search-input/docs/pf-search-input.md b/elements/pf-search-input/docs/pf-search-input.md index e31bbc9203..91243248a0 100644 --- a/elements/pf-search-input/docs/pf-search-input.md +++ b/elements/pf-search-input/docs/pf-search-input.md @@ -77,17 +77,16 @@ Listbox options use the [APG's Roving tabindex](https://www.w3.org/WAI/ARIA/apg/ {% endband %} - - - -{% renderSlots %}{% endrenderSlots %} - -{% renderAttributes %}{% endrenderAttributes %} - -{% renderMethods %}{% endrenderMethods %} - -{% renderEvents %}{% endrenderEvents %} - -{% renderCssCustomProperties %}{% endrenderCssCustomProperties %} - -{% renderCssParts %}{% endrenderCssParts %} +{% renderSlots for="pf-search-input", header="Slots on `pf-search-input`" %}{% endrenderSlots %} +{% renderAttributes for="pf-search-input", header="Attributes on `pf-search-input`" %}{% endrenderAttributes %} +{% renderMethods for="pf-search-input", header="Methods on `pf-search-input`" %}{% endrenderMethods %} +{% renderEvents for="pf-search-input", header="Events on `pf-search-input`" %}{% endrenderEvents %} +{% renderCssCustomProperties for="pf-search-input", header="CSS Custom Properties on `pf-search-input`" %}{% endrenderCssCustomProperties %} +{% renderCssParts for="pf-search-input", header="CSS Parts on `pf-search-input`" %}{% endrenderCssParts %} + +{% renderSlots for="pf-option", header="Slots on `pf-option`" %}{% endrenderSlots %} +{% renderAttributes for="pf-option", header="Attributes on `pf-option`" %}{% endrenderAttributes %} +{% renderMethods for="pf-option", header="Methods on `pf-option`" %}{% endrenderMethods %} +{% renderEvents for="pf-option", header="Events on `pf-option`" %}{% endrenderEvents %} +{% renderCssCustomProperties for="pf-option", header="CSS Custom Properties on `pf-option`" %}{% endrenderCssCustomProperties %} +{% renderCssParts for="pf-option", header="CSS Parts on `pf-option`" %}{% endrenderCssParts %} diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index 874b673a22..8206fc494c 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -68,11 +68,7 @@ --pf-c-search-input__toggle-clear--toggle-button--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); --pf-c-search-input__toggle-button--Color: var(--pf-global--Color--100, #151515); --pf-c-search-input__list-item--m-loading--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); - - /* --pf-c-search-input__toggle--FontSize: var(--pf-global--FontSize--md, 1rem); - --pf-c-search-input__toggle--FontWeight: var(--pf-global--FontWeight--normal, 400); - --pf-c-search-input__toggle--LineHeight: var(--pf-global--LineHeight--md, 1.5); - --pf-c-search-input__toggle--BackgroundColor: var(--pf-global--BackgroundColor--100, #fff); */ + --pf-c-search-input__menu-content--MaxHeight: 20rem; } :host, @@ -80,7 +76,7 @@ display: flex; flex-direction: column; align-items: stretch; - width: fit-content; + width: 100%; } :host([hidden]), @@ -113,7 +109,7 @@ #outer.expanded #listbox-container { opacity: 1; z-index: 9999 !important; - max-height: 300px; + max-height: var(--pf-c-search-input__menu-content--MaxHeight, 20rem); overflow: hidden; } @@ -158,10 +154,9 @@ color: var(--pf-global--Color--dark-200, #6a6e73) !important; background-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; border-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; + caret-color: transparent; } - -/* #toggle-button, */ #toggle-input { background: transparent; border: none; @@ -172,7 +167,7 @@ #toggle-input { justify-content: space-between; - min-width: calc(100% - 33px); + width: 100%; box-sizing: border-box; height: 2.25rem; } @@ -298,10 +293,10 @@ div.search-icon { &::after { content: ''; - width: 2.25rem; + width: 36px; height: var(--pf-global--spacer--xs, 0.125rem); bottom: 0px; - left: -3px; + left: 0px; background-color: var(--pf-theme--color--accent, #0066cc); position: absolute; } diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 35133c05de..90305047dc 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -100,6 +100,7 @@ export class PfSearchChangeEvent extends Event { * @cssprop [--pf-c-search-input__toggle-clear--toggle-button--PaddingLeft=var(--pf-global--spacer--sm, 0.5rem)] * @cssprop [--pf-c-search-input__toggle-button--Color=var(--pf-global--Color--100, #151515)] * @cssprop [--pf-c-search-input__list-item--m-loading--PaddingTop=var(--pf-global--spacer--sm, 0.5rem)] + * @cssprop [--pf-c-search-input__menu-content--MaxHeight=20rem;] **/ @customElement('pf-search-input') export class PfSearchInput extends LitElement { @@ -432,9 +433,8 @@ export class PfSearchInput extends LitElement { #setItemActive(item: PfOption, active: boolean) { item.active = active; - if (this.expanded) { - const activeOption = this.querySelector('pf-option[active]'); - activeOption?.scrollIntoView({ behavior: 'auto', block: 'nearest', inline: 'nearest' }); + if (this.expanded && active) { + item?.scrollIntoView({ behavior: 'auto', block: 'nearest', inline: 'nearest' }); } } } From e085a4d92e9e6f5747952cd389256efde98d9b42 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Tue, 22 Jul 2025 16:34:36 +0530 Subject: [PATCH 53/85] chore: updated to css logical properties --- elements/pf-search-input/pf-search-input.css | 42 ++++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index 8206fc494c..36363aa483 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -76,7 +76,7 @@ display: flex; flex-direction: column; align-items: stretch; - width: 100%; + inline-size: 100%; } :host([hidden]), @@ -109,15 +109,15 @@ #outer.expanded #listbox-container { opacity: 1; z-index: 9999 !important; - max-height: var(--pf-c-search-input__menu-content--MaxHeight, 20rem); - overflow: hidden; + max-block-size: var(--pf-c-search-input__menu-content--MaxHeight, 20rem); + overflow-y: scroll; } #listbox { display: flex; flex-direction: column; position: relative; - width: 100%; + inline-size: 100%; } #listbox slot.disabled { @@ -162,14 +162,14 @@ border: none; text-align: left; border-radius: 0; - padding-left: 3rem; + padding-inline-start: 3rem; } #toggle-input { justify-content: space-between; - width: 100%; + inline-size: 100%; box-sizing: border-box; - height: 2.25rem; + block-size: 2.25rem; } .disabled #toggle-input { @@ -185,8 +185,8 @@ color: currentColor; background-color: transparent; - max-height: 2.25rem; - max-width: 2.25rem; + max-block-size: 2.25rem; + max-inline-size: 2.25rem; box-sizing: border-box; display: flex; align-items: center; @@ -196,13 +196,13 @@ pf-icon { position: relative; - top: 5px; + inset-block-start: 5px; } } .close-button-container { - height: 2.25rem; - width: 2.25rem; + block-size: 2.25rem; + inline-size: 2.25rem; } #toggle-text { @@ -256,23 +256,23 @@ display: var(--pf-c-divider--Display, flex); flex-direction: var(--pf-c-divider--FlexDirection); border: 0; - width: 100%; + inline-size: 100%; margin-top: var(--pf-c-search-input-menu--c-divider--MarginTop); margin-bottom: var(--pf-c-search-input-menu--c-divider--MarginBottom); } ::slotted(hr)::after { content: ''; - width: var(--pf-c-divider--after--Width, 100%) !important; - height: var(--pf-c-divider--after--Height, 1px); + inline-size: var(--pf-c-divider--after--Width, 100%) !important; + block-size: var(--pf-c-divider--after--Height, 1px); background-color: var(--pf-c-divider--after--BackgroundColor); flex: 1 0 100%; } div.search-icon { position: absolute; - top: 50%; - left: var(--pf-global--spacer--md, 1rem); + inset-block-start: 50%; + inset-inline-start: var(--pf-global--spacer--md, 1rem); transform: translateY(-50%); display: flex; align-items: center; @@ -293,10 +293,10 @@ div.search-icon { &::after { content: ''; - width: 36px; - height: var(--pf-global--spacer--xs, 0.125rem); - bottom: 0px; - left: 0px; + inline-size: 36px; + block-size: var(--pf-global--spacer--xs, 0.125rem); + inset-block-end: 0px; + inset-inline-start: 0px; background-color: var(--pf-theme--color--accent, #0066cc); position: absolute; } From 05ab6121bfd63695f4b52d5c547e95ecc64dc761 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Tue, 22 Jul 2025 19:18:09 +0530 Subject: [PATCH 54/85] chore: added negative tab index to prevent focus --- elements/pf-search-input/pf-search-input.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 90305047dc..d7fd1d9556 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -287,6 +287,7 @@ export class PfSearchInput extends LitElement {
Date: Wed, 23 Jul 2025 12:10:23 +0530 Subject: [PATCH 56/85] Update elements/pf-search-input/pf-search-input.ts Co-authored-by: Adam Johnson --- elements/pf-search-input/pf-search-input.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index d7fd1d9556..12394fd2d0 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -34,7 +34,7 @@ export class PfSearchChangeEvent extends Event { * their own keywords to filter or locate results. It includes a clear (×) button to easily * remove the current input, allowing users to start a new search quickly. * @slot - insert `pf-option` and/or `pf-option-groups` here - * @slot placeholder - placeholder text for the select. Overrides the `placeholder` attribute. + * @slot placeholder - placeholder text for the search input. Overrides the `placeholder` attribute. * @fires open - when the menu toggles open * @fires close - when the menu toggles closed * @cssprop [--pf-c-search-input__toggle--PaddingTop=var(--pf-global--spacer--form-element, 0.375rem)] From 008164fe1413f5f7c8a405e87a84b99fa4b93b36 Mon Sep 17 00:00:00 2001 From: Arathy Kumar <49025521+ArathyKumar@users.noreply.github.com> Date: Wed, 23 Jul 2025 12:10:38 +0530 Subject: [PATCH 57/85] Update elements/pf-search-input/pf-search-input.ts Co-authored-by: Adam Johnson --- elements/pf-search-input/pf-search-input.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 12394fd2d0..82bd5c60c2 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -113,7 +113,7 @@ export class PfSearchInput extends LitElement { static instances: Set = new Set(); - /** Accessible label for the select */ + /** Accessible label for the search input */ @property({ attribute: 'accessible-label' }) accessibleLabel?: string; /** Multi listbox button text */ From 0fc1cd13d145757b4ff9cd534268f77d8657d545 Mon Sep 17 00:00:00 2001 From: Arathy Kumar <49025521+ArathyKumar@users.noreply.github.com> Date: Wed, 23 Jul 2025 12:10:48 +0530 Subject: [PATCH 58/85] Update elements/pf-search-input/pf-search-input.ts Co-authored-by: Adam Johnson --- elements/pf-search-input/pf-search-input.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 82bd5c60c2..d9a6b5dca7 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -122,7 +122,7 @@ export class PfSearchInput extends LitElement { /** Whether the select is disabled */ @property({ type: Boolean, reflect: true }) disabled = false; - /** Whether the select listbox is expanded */ + /** Whether the search input's listbox is expanded */ @property({ type: Boolean, reflect: true }) expanded = false; /** From 485a8d8f3a126739dbe175756f18862ffc4e3e95 Mon Sep 17 00:00:00 2001 From: Arathy Kumar <49025521+ArathyKumar@users.noreply.github.com> Date: Wed, 23 Jul 2025 12:10:57 +0530 Subject: [PATCH 59/85] Update elements/pf-search-input/pf-search-input.ts Co-authored-by: Adam Johnson --- elements/pf-search-input/pf-search-input.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index d9a6b5dca7..738665a9f1 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -119,7 +119,7 @@ export class PfSearchInput extends LitElement { /** Multi listbox button text */ @property({ attribute: 'items-selected-text' }) itemsSelectedText = 'items selected'; - /** Whether the select is disabled */ + /** Whether the search input is disabled */ @property({ type: Boolean, reflect: true }) disabled = false; /** Whether the search input's listbox is expanded */ From 4ce4511396c01785cb98f26abafd94996edea700 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Wed, 23 Jul 2025 12:29:43 +0530 Subject: [PATCH 60/85] chore: resolved tab indentation issues --- elements/pf-search-input/pf-search-input.css | 445 +++++++++---------- elements/pf-search-input/pf-search-input.ts | 2 +- 2 files changed, 223 insertions(+), 224 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index 36363aa483..e32184d64c 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -1,309 +1,308 @@ :host { - font-family: var(--pf-global--FontFamily--sans-serif, "RedHatTextUpdated", "Overpass", overpass, helvetica, arial, sans-serif); - font-size: var(--pf-global--FontSize--md, 16px); - font-weight: var(--pf-global--FontWeight--normal, 400); - color: var(--pf-global--Color--100, #151515); - --_pf-option-checkboxes-display: none; - --_pf-option-svg-display: block; - --pf-c-search-input__toggle--PaddingTop: var(--pf-global--spacer--form-element, 0.375rem); - --pf-c-search-input__toggle--PaddingRight: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-search-input__toggle--PaddingBottom: var(--pf-global--spacer--form-element, 0.375rem); - --pf-c-search-input__toggle--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-search-input__toggle--MinWidth: var(--pf-global--target-size--MinWidth, 44px); - --pf-c-search-input__toggle--FontSize: var(--pf-global--FontSize--md, 1rem); - --pf-c-search-input__toggle--FontWeight: var(--pf-global--FontWeight--normal, 400); - --pf-c-search-input__toggle--LineHeight: var(--pf-global--LineHeight--md, 1.5); - --pf-c-search-input__toggle--BackgroundColor: var(--pf-global--BackgroundColor--100, #fff); - --pf-c-search-input__toggle--before--BorderTopWidth: var(--pf-global--BorderWidth--sm, 1px); - --pf-c-search-input__toggle--before--BorderRightWidth: var(--pf-global--BorderWidth--sm, 1px); - --pf-c-search-input__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--sm, 1px); - --pf-c-search-input__toggle--before--BorderLeftWidth: var(--pf-global--BorderWidth--sm, 1px); - --pf-c-search-input__toggle--before--BorderWidth: initial; - --pf-c-search-input__toggle--before--BorderTopColor: var(--pf-global--BorderColor--300, #f0f0f0); - --pf-c-search-input__toggle--before--BorderRightColor: var(--pf-global--BorderColor--300, #f0f0f0); - --pf-c-search-input__toggle--before--BorderBottomColor: var(--pf-global--BorderColor--200, #8a8d90); - --pf-c-search-input__toggle--before--BorderLeftColor: var(--pf-global--BorderColor--300, #f0f0f0); - --pf-c-search-input__toggle--Color: var(--pf-global--Color--100, #151515); - --pf-c-search-input__toggle--hover--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); - --pf-c-search-input__toggle--focus--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); - --pf-c-search-input__toggle--focus--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); - --pf-c-search-input__toggle--active--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); - --pf-c-search-input__toggle--active--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); - --pf-c-search-input__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); - --pf-c-search-input__toggle--m-expanded--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); - --pf-c-search-input__toggle--disabled--BackgroundColor: var(--pf-global--disabled-color--300, #f0f0f0); - --pf-c-search-input__toggle--m-plain--before--BorderColor: transparent; - --pf-c-search-input__toggle--m-placeholder--Color: transparent; - --pf-c-search-input--m-invalid__toggle--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); - --pf-c-search-input--m-invalid__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); - --pf-c-search-input--m-invalid__toggle--hover--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); - --pf-c-search-input--m-invalid__toggle--focus--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); - --pf-c-search-input--m-invalid__toggle--active--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); - --pf-c-search-input--m-invalid__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); - --pf-c-search-input--m-invalid__toggle-status-icon--Color: var(--pf-global--danger-color--100, #c9190b); - --pf-c-search-input--m-success__toggle--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); - --pf-c-search-input--m-success__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); - --pf-c-search-input--m-success__toggle--hover--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); - --pf-c-search-input--m-success__toggle--focus--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); - --pf-c-search-input--m-success__toggle--active--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); - --pf-c-search-input--m-success__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); - --pf-c-search-input--m-success__toggle-status-icon--Color: var(--pf-global--success-color--100, #3e8635); - --pf-c-search-input--m-warning__toggle--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); - --pf-c-search-input--m-warning__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); - --pf-c-search-input--m-warning__toggle--hover--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); - --pf-c-search-input--m-warning__toggle--focus--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); - --pf-c-search-input--m-warning__toggle--active--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); - --pf-c-search-input--m-warning__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); - --pf-c-search-input--m-warning__toggle-status-icon--Color: var(--pf-global--warning-color--100, #f0ab00); - --pf-c-search-input__toggle-wrapper--not-last-child--MarginRight: var(--pf-global--spacer--xs, 0.25rem); - --pf-c-search-input__toggle-wrapper--MaxWidth: calc(100% - var(--pf-global--spacer--lg, 1.5rem)); - --pf-c-search-input__toggle--m-placeholder__toggle-text--Color: var(--pf-global--Color--dark-200, #6a6e73); - --pf-c-search-input__toggle-icon--toggle-text--MarginLeft: var(--pf-global--spacer--xs, 0.25rem); - --pf-c-search-input__toggle-status-icon--MarginLeft: var(--pf-global--spacer--xs, 0.25rem); - --pf-c-search-input__toggle-status-icon--Color: var(--pf-global--Color--100, #151515); - --pf-c-search-input--m-plain__toggle-arrow--Color: var(--pf-global--Color--200, #6a6e73); - --pf-c-search-input--m-plain--hover__toggle-arrow--Color: var(--pf-global--Color--100, #151515); - --pf-c-search-input__toggle-clear--PaddingRight: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-search-input__toggle-clear--PaddingLeft: var(--pf-global--spacer--md, 1rem); - --pf-c-search-input__toggle-clear--toggle-button--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-search-input__toggle-button--Color: var(--pf-global--Color--100, #151515); - --pf-c-search-input__list-item--m-loading--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-search-input__menu-content--MaxHeight: 20rem; + font-family: var(--pf-global--FontFamily--sans-serif, "RedHatTextUpdated", "Overpass", overpass, helvetica, arial, sans-serif); + font-size: var(--pf-global--FontSize--md, 16px); + font-weight: var(--pf-global--FontWeight--normal, 400); + color: var(--pf-global--Color--100, #151515); + --_pf-option-checkboxes-display: none; + --_pf-option-svg-display: block; + --pf-c-search-input__toggle--PaddingTop: var(--pf-global--spacer--form-element, 0.375rem); + --pf-c-search-input__toggle--PaddingRight: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__toggle--PaddingBottom: var(--pf-global--spacer--form-element, 0.375rem); + --pf-c-search-input__toggle--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__toggle--MinWidth: var(--pf-global--target-size--MinWidth, 44px); + --pf-c-search-input__toggle--FontSize: var(--pf-global--FontSize--md, 1rem); + --pf-c-search-input__toggle--FontWeight: var(--pf-global--FontWeight--normal, 400); + --pf-c-search-input__toggle--LineHeight: var(--pf-global--LineHeight--md, 1.5); + --pf-c-search-input__toggle--BackgroundColor: var(--pf-global--BackgroundColor--100, #fff); + --pf-c-search-input__toggle--before--BorderTopWidth: var(--pf-global--BorderWidth--sm, 1px); + --pf-c-search-input__toggle--before--BorderRightWidth: var(--pf-global--BorderWidth--sm, 1px); + --pf-c-search-input__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--sm, 1px); + --pf-c-search-input__toggle--before--BorderLeftWidth: var(--pf-global--BorderWidth--sm, 1px); + --pf-c-search-input__toggle--before--BorderWidth: initial; + --pf-c-search-input__toggle--before--BorderTopColor: var(--pf-global--BorderColor--300, #f0f0f0); + --pf-c-search-input__toggle--before--BorderRightColor: var(--pf-global--BorderColor--300, #f0f0f0); + --pf-c-search-input__toggle--before--BorderBottomColor: var(--pf-global--BorderColor--200, #8a8d90); + --pf-c-search-input__toggle--before--BorderLeftColor: var(--pf-global--BorderColor--300, #f0f0f0); + --pf-c-search-input__toggle--Color: var(--pf-global--Color--100, #151515); + --pf-c-search-input__toggle--hover--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); + --pf-c-search-input__toggle--focus--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); + --pf-c-search-input__toggle--focus--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); + --pf-c-search-input__toggle--active--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); + --pf-c-search-input__toggle--active--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); + --pf-c-search-input__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--active-color--100, #06c); + --pf-c-search-input__toggle--m-expanded--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); + --pf-c-search-input__toggle--disabled--BackgroundColor: var(--pf-global--disabled-color--300, #f0f0f0); + --pf-c-search-input__toggle--m-plain--before--BorderColor: transparent; + --pf-c-search-input__toggle--m-placeholder--Color: transparent; + --pf-c-search-input--m-invalid__toggle--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); + --pf-c-search-input--m-invalid__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); + --pf-c-search-input--m-invalid__toggle--hover--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); + --pf-c-search-input--m-invalid__toggle--focus--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); + --pf-c-search-input--m-invalid__toggle--active--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); + --pf-c-search-input--m-invalid__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--danger-color--100, #c9190b); + --pf-c-search-input--m-invalid__toggle-status-icon--Color: var(--pf-global--danger-color--100, #c9190b); + --pf-c-search-input--m-success__toggle--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); + --pf-c-search-input--m-success__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); + --pf-c-search-input--m-success__toggle--hover--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); + --pf-c-search-input--m-success__toggle--focus--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); + --pf-c-search-input--m-success__toggle--active--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); + --pf-c-search-input--m-success__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--success-color--100, #3e8635); + --pf-c-search-input--m-success__toggle-status-icon--Color: var(--pf-global--success-color--100, #3e8635); + --pf-c-search-input--m-warning__toggle--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); + --pf-c-search-input--m-warning__toggle--before--BorderBottomWidth: var(--pf-global--BorderWidth--md, 2px); + --pf-c-search-input--m-warning__toggle--hover--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); + --pf-c-search-input--m-warning__toggle--focus--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); + --pf-c-search-input--m-warning__toggle--active--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); + --pf-c-search-input--m-warning__toggle--m-expanded--before--BorderBottomColor: var(--pf-global--warning-color--100, #f0ab00); + --pf-c-search-input--m-warning__toggle-status-icon--Color: var(--pf-global--warning-color--100, #f0ab00); + --pf-c-search-input__toggle-wrapper--not-last-child--MarginRight: var(--pf-global--spacer--xs, 0.25rem); + --pf-c-search-input__toggle-wrapper--MaxWidth: calc(100% - var(--pf-global--spacer--lg, 1.5rem)); + --pf-c-search-input__toggle--m-placeholder__toggle-text--Color: var(--pf-global--Color--dark-200, #6a6e73); + --pf-c-search-input__toggle-icon--toggle-text--MarginLeft: var(--pf-global--spacer--xs, 0.25rem); + --pf-c-search-input__toggle-status-icon--MarginLeft: var(--pf-global--spacer--xs, 0.25rem); + --pf-c-search-input__toggle-status-icon--Color: var(--pf-global--Color--100, #151515); + --pf-c-search-input--m-plain__toggle-arrow--Color: var(--pf-global--Color--200, #6a6e73); + --pf-c-search-input--m-plain--hover__toggle-arrow--Color: var(--pf-global--Color--100, #151515); + --pf-c-search-input__toggle-clear--PaddingRight: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__toggle-clear--PaddingLeft: var(--pf-global--spacer--md, 1rem); + --pf-c-search-input__toggle-clear--toggle-button--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__toggle-button--Color: var(--pf-global--Color--100, #151515); + --pf-c-search-input__list-item--m-loading--PaddingTop: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-search-input__menu-content--MaxHeight: 20rem; } :host, #outer { - display: flex; - flex-direction: column; - align-items: stretch; - inline-size: 100%; + display: flex; + flex-direction: column; + align-items: stretch; + inline-size: 100%; } :host([hidden]), *[hidden] { - display: none !important; + display: none !important; } :host([aria-disabled="true"]) { - pointer-events: none; - cursor: not-allowed; + pointer-events: none; + cursor: not-allowed; } #outer.disabled { - color: var(--pf-global--Color--dark-200, #6a6e73); + color: var(--pf-global--Color--dark-200, #6a6e73); } #outer { - position: relative; + position: relative; } #listbox-container { - display: inline-flex; - position: absolute; - background-color: var(--pf-theme--color--surface--lightest, #fff) !important; - opacity: 0; - --_active-descendant-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; - box-shadow: 0 0.25rem 0.5rem 0rem rgba(3, 3, 3, 0.12), 0 0 0.25rem 0 rgba(3, 3, 3, 0.06); + display: inline-flex; + position: absolute; + background-color: var(--pf-theme--color--surface--lightest, #fff) !important; + opacity: 0; + --_active-descendant-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; + box-shadow: 0 0.25rem 0.5rem 0rem rgba(3, 3, 3, 0.12), 0 0 0.25rem 0 rgba(3, 3, 3, 0.06); } #outer.expanded #listbox-container { - opacity: 1; - z-index: 9999 !important; - max-block-size: var(--pf-c-search-input__menu-content--MaxHeight, 20rem); - overflow-y: scroll; + opacity: 1; + z-index: 9999 !important; + max-block-size: var(--pf-c-search-input__menu-content--MaxHeight, 20rem); + overflow-y: scroll; } #listbox { - display: flex; - flex-direction: column; - position: relative; - inline-size: 100%; + display: flex; + flex-direction: column; + position: relative; + inline-size: 100%; } #listbox slot.disabled { - color: var(--pf-c-list__item-icon--Color, #6a6e73) !important; - background-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; - border-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; - pointer-events: none; - cursor: not-allowed; - - --_active-descendant-color: transparent; - --_svg-color: var(--pf-c-list__item-icon--Color, #6a6e73) !important; + color: var(--pf-c-list__item-icon--Color, #6a6e73) !important; + background-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; + border-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; + pointer-events: none; + cursor: not-allowed; + + --_active-descendant-color: transparent; + --_svg-color: var(--pf-c-list__item-icon--Color, #6a6e73) !important; } #toggle { - background-color: var(--pf-c-search-input__toggle--BackgroundColor, #fff) !important; + background-color: var(--pf-c-search-input__toggle--BackgroundColor, #fff) !important; } #toggle, #toggle-input { - display: flex; - font-family: var(--pf-global--FontFamily--sans-serif, "RedHatTextUpdated", "Overpass", overpass, helvetica, arial, sans-serif); - font-size: var(--pf-c-search-input__toggle--FontSize, 1rem); - font-weight: var( --pf-c-search-input__toggle--FontWeight, 400); - line-height: var(--pf-c-search-input__toggle--LineHeight, 1.5); + display: flex; + font-family: var(--pf-global--FontFamily--sans-serif, "RedHatTextUpdated", "Overpass", overpass, helvetica, arial, sans-serif); + font-size: var(--pf-c-search-input__toggle--FontSize, 1rem); + font-weight: var(--pf-c-search-input__toggle--FontWeight, 400); + line-height: var(--pf-c-search-input__toggle--LineHeight, 1.5); } #toggle { - border: 1px solid var(--pf-global--BorderColor--100, #d2d2d2); - border-bottom-color: var(--pf-theme--color--text, #151515); - justify-content: space-between; + border: 1px solid var(--pf-global--BorderColor--100, #d2d2d2); + border-bottom-color: var(--pf-theme--color--text, #151515); + justify-content: space-between; } .disabled #toggle { - color: var(--pf-global--Color--dark-200, #6a6e73) !important; - background-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; - border-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; - caret-color: transparent; + color: var(--pf-global--Color--dark-200, #6a6e73) !important; + background-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; + border-color: var(--pf-theme--color--surface--lighter, #f0f0f0) !important; + caret-color: transparent; } #toggle-input { - background: transparent; - border: none; - text-align: left; - border-radius: 0; - padding-inline-start: 3rem; + background: transparent; + border: none; + text-align: left; + border-radius: 0; + padding-inline-start: 3rem; } #toggle-input { - justify-content: space-between; - inline-size: 100%; - box-sizing: border-box; - block-size: 2.25rem; + justify-content: space-between; + inline-size: 100%; + box-sizing: border-box; + block-size: 2.25rem; } .disabled #toggle-input { - pointer-events: none; - cursor: not-allowed; + pointer-events: none; + cursor: not-allowed; } #close-button { - --pf-c-button--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-button--PaddingRight: var(--pf-global--spacer--sm, 0.5rem); - --pf-c-button--PaddingTop: var(--pf-global--spacer--xs, 0.25rem); - --pf-c-button--PaddingBottom: var(--pf-global--spacer--xs, 0.25rem); - - color: currentColor; - background-color: transparent; - max-block-size: 2.25rem; - max-inline-size: 2.25rem; - box-sizing: border-box; - display: flex; - align-items: center; - justify-content: center; - border-radius: 0px; - position: relative; - - pf-icon { - position: relative; - inset-block-start: 5px; - } + --pf-c-button--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-button--PaddingRight: var(--pf-global--spacer--sm, 0.5rem); + --pf-c-button--PaddingTop: var(--pf-global--spacer--xs, 0.25rem); + --pf-c-button--PaddingBottom: var(--pf-global--spacer--xs, 0.25rem); + + color: currentColor; + background-color: transparent; + max-block-size: 2.25rem; + max-inline-size: 2.25rem; + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: center; + border-radius: 0px; + position: relative; + + pf-icon { + position: relative; + inset-block-start: 5px; + } } .close-button-container { - block-size: 2.25rem; - inline-size: 2.25rem; + block-size: 2.25rem; + inline-size: 2.25rem; } #toggle-text { - flex: 1 1 auto; + flex: 1 1 auto; } - #description { - display: block; + display: block; } #listbox.checkboxes { - --_pf-option-checkboxes-display: none; - --_pf-option-svg-display: none; + --_pf-option-checkboxes-display: none; + --_pf-option-svg-display: none; } .visually-hidden { - border: 0; - clip: rect(0, 0, 0, 0); - block-size: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - white-space: nowrap; - inline-size: 1px; + border: 0; + clip: rect(0, 0, 0, 0); + block-size: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + white-space: nowrap; + inline-size: 1px; } ::slotted(hr) { - --pf-c-divider--BorderWidth--base: var(--pf-global--BorderWidth--sm, 1px); - --pf-c-divider--BorderColor--base: var(--pf-c-divider--BackgroundColor); - --pf-c-divider--Height: var(--pf-c-divider--BorderWidth--base); - --pf-c-divider--BackgroundColor: var(--pf-global--BorderColor--100, #d2d2d2); - --pf-c-divider--after--BackgroundColor: var(--pf-c-divider--BorderColor--base); - --pf-c-divider--after--FlexBasis: 100%; - --pf-c-divider--after--Inset: 0%; - --pf-c-divider--m-vertical--after--FlexBasis: 100%; - --pf-c-divider--m-horizontal--Display: flex; - --pf-c-divider--m-horizontal--FlexDirection: row; - --pf-c-divider--m-horizontal--after--Height: var(--pf-c-divider--Height); - --pf-c-divider--m-horizontal--after--Width: auto; - --pf-c-divider--m-vertical--Display: inline-flex; - --pf-c-divider--m-vertical--FlexDirection: column; - --pf-c-divider--m-vertical--after--Height: auto; - --pf-c-divider--m-vertical--after--Width: var(--pf-c-divider--BorderWidth--base); - --pf-hidden-visible--visible--Display: var(--pf-c-divider--Display); - --pf-c-divider--Display: var(--pf-c-divider--m-horizontal--Display); - --pf-c-divider--FlexDirection: var(--pf-c-divider--m-horizontal--FlexDirection); - --pf-c-divider--after--Width: var(--pf-c-divider--m-horizontal--after--Width); - --pf-c-divider--after--Height: var(--pf-c-divider--m-horizontal--after--Height); - display: var(--pf-c-divider--Display, flex); - flex-direction: var(--pf-c-divider--FlexDirection); - border: 0; - inline-size: 100%; - margin-top: var(--pf-c-search-input-menu--c-divider--MarginTop); - margin-bottom: var(--pf-c-search-input-menu--c-divider--MarginBottom); + --pf-c-divider--BorderWidth--base: var(--pf-global--BorderWidth--sm, 1px); + --pf-c-divider--BorderColor--base: var(--pf-c-divider--BackgroundColor); + --pf-c-divider--Height: var(--pf-c-divider--BorderWidth--base); + --pf-c-divider--BackgroundColor: var(--pf-global--BorderColor--100, #d2d2d2); + --pf-c-divider--after--BackgroundColor: var(--pf-c-divider--BorderColor--base); + --pf-c-divider--after--FlexBasis: 100%; + --pf-c-divider--after--Inset: 0%; + --pf-c-divider--m-vertical--after--FlexBasis: 100%; + --pf-c-divider--m-horizontal--Display: flex; + --pf-c-divider--m-horizontal--FlexDirection: row; + --pf-c-divider--m-horizontal--after--Height: var(--pf-c-divider--Height); + --pf-c-divider--m-horizontal--after--Width: auto; + --pf-c-divider--m-vertical--Display: inline-flex; + --pf-c-divider--m-vertical--FlexDirection: column; + --pf-c-divider--m-vertical--after--Height: auto; + --pf-c-divider--m-vertical--after--Width: var(--pf-c-divider--BorderWidth--base); + --pf-hidden-visible--visible--Display: var(--pf-c-divider--Display); + --pf-c-divider--Display: var(--pf-c-divider--m-horizontal--Display); + --pf-c-divider--FlexDirection: var(--pf-c-divider--m-horizontal--FlexDirection); + --pf-c-divider--after--Width: var(--pf-c-divider--m-horizontal--after--Width); + --pf-c-divider--after--Height: var(--pf-c-divider--m-horizontal--after--Height); + display: var(--pf-c-divider--Display, flex); + flex-direction: var(--pf-c-divider--FlexDirection); + border: 0; + inline-size: 100%; + margin-top: var(--pf-c-search-input-menu--c-divider--MarginTop); + margin-bottom: var(--pf-c-search-input-menu--c-divider--MarginBottom); } ::slotted(hr)::after { - content: ''; - inline-size: var(--pf-c-divider--after--Width, 100%) !important; - block-size: var(--pf-c-divider--after--Height, 1px); - background-color: var(--pf-c-divider--after--BackgroundColor); - flex: 1 0 100%; + content: ''; + inline-size: var(--pf-c-divider--after--Width, 100%) !important; + block-size: var(--pf-c-divider--after--Height, 1px); + background-color: var(--pf-c-divider--after--BackgroundColor); + flex: 1 0 100%; } div.search-icon { - position: absolute; - inset-block-start: 50%; - inset-inline-start: var(--pf-global--spacer--md, 1rem); - transform: translateY(-50%); - display: flex; - align-items: center; + position: absolute; + inset-block-start: 50%; + inset-inline-start: var(--pf-global--spacer--md, 1rem); + transform: translateY(-50%); + display: flex; + align-items: center; } #outer:focus-within { - #toggle { - border-bottom: none; - border-bottom-left-radius: 4px; - - #toggle-input { - border-bottom: var(--pf-global--spacer--xs, 0.125rem) solid var(--pf-theme--color--accent, #0066cc); - } - } - - .close-button-container { - position: relative; - - &::after { - content: ''; - inline-size: 36px; - block-size: var(--pf-global--spacer--xs, 0.125rem); - inset-block-end: 0px; - inset-inline-start: 0px; - background-color: var(--pf-theme--color--accent, #0066cc); - position: absolute; - } - } + #toggle { + border-bottom: none; + border-bottom-left-radius: 4px; + + #toggle-input { + border-bottom: var(--pf-global--spacer--xs, 0.125rem) solid var(--pf-theme--color--accent, #0066cc); + } + } + + .close-button-container { + position: relative; + + &::after { + content: ''; + inline-size: 36px; + block-size: var(--pf-global--spacer--xs, 0.125rem); + inset-block-end: 0px; + inset-inline-start: 0px; + background-color: var(--pf-theme--color--accent, #0066cc); + position: absolute; + } + } } ::slotted(pf-option[selected]) { - --_pf-option-svg-display: none; - --_pf-option-selected-background-color: var(--pf-global--BackgroundColor--100, #fff); + --_pf-option-svg-display: none; + --_pf-option-selected-background-color: var(--pf-global--BackgroundColor--100, #fff); } \ No newline at end of file diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index d7fd1d9556..fa3584eee1 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -33,7 +33,7 @@ export class PfSearchChangeEvent extends Event { * Unlike selects or dropdowns, which offer predefined options, a search input lets users enter * their own keywords to filter or locate results. It includes a clear (×) button to easily * remove the current input, allowing users to start a new search quickly. - * @slot - insert `pf-option` and/or `pf-option-groups` here + * @slot - insert `pf-option` here * @slot placeholder - placeholder text for the select. Overrides the `placeholder` attribute. * @fires open - when the menu toggles open * @fires close - when the menu toggles closed From 831c66fd1df5cc05b756e80574065a75fbaaf750 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Wed, 23 Jul 2025 14:10:19 +0530 Subject: [PATCH 61/85] chore: documentation update --- elements/pf-search-input/docs/pf-search-input.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/elements/pf-search-input/docs/pf-search-input.md b/elements/pf-search-input/docs/pf-search-input.md index dc2fb7ffc4..a56408d544 100644 --- a/elements/pf-search-input/docs/pf-search-input.md +++ b/elements/pf-search-input/docs/pf-search-input.md @@ -69,8 +69,8 @@ Listbox options use the [APG's Roving tabindex](https://www.w3.org/WAI/ARIA/apg/ | Shift + Tab | Moves focus to the toggle button and closes listbox. | | Up Arrow | Moves focus to the previous option, optionally wrapping from the first to the last. | | Down Arrow | Moves focus to the next option, optionally wrapping from the last to the first. | -| Left Arrow | Moves focus to the previous option, optionally wrapping from the first to the last. | -| Right Arrow | Moves focus to the next option, optionally wrapping from the last to the first. | +| Left Arrow | Returns focus to the combobox without closing the popup and moves the input cursor one character to the left. If the input cursor is on the left-most character, the cursor does not move. | +| Right Arrow | Returns focus to the combobox without closing the popup and moves the input cursor one character to the right. If the input cursor is on the right-most character, the cursor does not move. | | Home | Moves focus to the first option in the current listbox. | | Escape | Close the listbox that contains focus and return focus to the toggle button. | | Any letter | Navigates to the next option that starts with the letter. | From 9c6b207918707ad3b2683cc911b18ee49e5ef721 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Wed, 23 Jul 2025 18:37:53 +0530 Subject: [PATCH 62/85] chore: set selected option function updated --- elements/pf-search-input/pf-search-input.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 84ce0fdd05..254b4f1602 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -222,13 +222,11 @@ export class PfSearchInput extends LitElement { } /** - * Single select option value for single select menus, - * or array of select option values for multi select. + * Set selected option */ @property({ hasChanged: (a, b) => !arraysAreEquivalent(a, b) }) - set selected(selected: PfOption | PfOption[]) { - const list = Array.isArray(selected) ? selected : [selected]; - this.#combobox.selected = list; + set selected(selected: PfOption) { + this.#combobox.selected = [selected]; } get selected(): PfOption[] { From fe699bf44090f687d55c6ae273e209c6c559ba13 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Wed, 23 Jul 2025 20:43:44 +0530 Subject: [PATCH 63/85] chore: set focus back to toggle input on clicking close button --- elements/pf-search-input/pf-search-input.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 254b4f1602..03a3c2b97b 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -381,6 +381,7 @@ export class PfSearchInput extends LitElement { this.value = ''; this._toggleInput!.value = this.value; this.#combobox.selected = []; + this._toggleInput?.focus(); } #hideCloseButton() { From e343b81452f7f4c2fc33afc7c973afeb5d17a9bb Mon Sep 17 00:00:00 2001 From: Arathy Kumar <49025521+ArathyKumar@users.noreply.github.com> Date: Wed, 23 Jul 2025 20:59:11 +0530 Subject: [PATCH 64/85] Update elements/pf-search-input/docs/pf-search-input.md Co-authored-by: Adam Johnson --- elements/pf-search-input/docs/pf-search-input.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/elements/pf-search-input/docs/pf-search-input.md b/elements/pf-search-input/docs/pf-search-input.md index a56408d544..0f3abb1518 100644 --- a/elements/pf-search-input/docs/pf-search-input.md +++ b/elements/pf-search-input/docs/pf-search-input.md @@ -71,8 +71,7 @@ Listbox options use the [APG's Roving tabindex](https://www.w3.org/WAI/ARIA/apg/ | Down Arrow | Moves focus to the next option, optionally wrapping from the last to the first. | | Left Arrow | Returns focus to the combobox without closing the popup and moves the input cursor one character to the left. If the input cursor is on the left-most character, the cursor does not move. | | Right Arrow | Returns focus to the combobox without closing the popup and moves the input cursor one character to the right. If the input cursor is on the right-most character, the cursor does not move. | -| Home | Moves focus to the first option in the current listbox. | -| Escape | Close the listbox that contains focus and return focus to the toggle button. | +| Escape | Close the listbox that contains focus and return focus to the input. | | Any letter | Navigates to the next option that starts with the letter. | {% endband %} From 27911f36c876944d77d75382c84a64dd8c8021d0 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Thu, 24 Jul 2025 13:07:15 +0530 Subject: [PATCH 65/85] chore: added type button for hidden button --- elements/pf-search-input/pf-search-input.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 03a3c2b97b..2d2df5fa25 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -280,7 +280,7 @@ export class PfSearchInput extends LitElement { close
- +
Date: Thu, 24 Jul 2025 17:44:13 +0530 Subject: [PATCH 66/85] docs: changeset --- .changeset/famous-parts-add.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .changeset/famous-parts-add.md diff --git a/.changeset/famous-parts-add.md b/.changeset/famous-parts-add.md new file mode 100644 index 0000000000..b60aca0be8 --- /dev/null +++ b/.changeset/famous-parts-add.md @@ -0,0 +1,20 @@ +--- +"@patternfly/elements": minor +--- + +✨ Added ``. + +A search input consists of a text field where users can type to find specific content or items. Unlike selects or dropdowns, which offer predefined options, a search input lets users enter their own keywords to filter or locate results. It includes a clear (×) button to easily remove the current input, allowing users to start a new search quickly. + +Use this when users need to search freely using their own terms — ideal for large or frequently changing sets of content. +Do not use when the options are limited and known ahead of time — consider a dropdown or select instead + +```html + + Alabama + New Jersey + New York + New Mexico + North Carolina + +``` \ No newline at end of file From f90a262ef96bd0e143488a3c7079247bfe645f78 Mon Sep 17 00:00:00 2001 From: Benny Powers Date: Fri, 25 Jul 2025 09:11:42 +0300 Subject: [PATCH 67/85] chore: update cem dependency --- package-lock.json | 66 +++++++++++++++++++++++------------------------ package.json | 10 +++---- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/package-lock.json b/package-lock.json index 22c8a4b1c6..b930cc82d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,7 @@ "@lit/react": "^1.0.5", "@octokit/core": "^6.1.2", "@patternfly/patternfly": "^4.224.5", - "@pwrs/cem": "^0.2.3", + "@pwrs/cem": "^0.2.14", "@rhds/elements": "^1.4.5", "@types/koa__router": "^12.0.4", "@types/node": "^22.15.32", @@ -50,10 +50,10 @@ "optionalDependencies": { "@esbuild/darwin-arm64": "^0.23.1", "@esbuild/linux-x64": "^0.23.1", - "@pwrs/cem-darwin-arm64": "^0.2.3", - "@pwrs/cem-darwin-x64": "^0.2.3", - "@pwrs/cem-linux-arm64": "^0.2.3", - "@pwrs/cem-linux-x64": "^0.2.3", + "@pwrs/cem-darwin-arm64": "^0.2.14", + "@pwrs/cem-darwin-x64": "^0.2.14", + "@pwrs/cem-linux-arm64": "^0.2.14", + "@pwrs/cem-linux-x64": "^0.2.14", "@rollup/rollup-darwin-arm64": "^4.21.0" } }, @@ -2908,9 +2908,9 @@ } }, "node_modules/@pwrs/cem": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@pwrs/cem/-/cem-0.2.3.tgz", - "integrity": "sha512-EtPwk5uoJX/FtnjcsGa58Pd2vN42pzEA4rq7xYS+4gOpvrjwUrK/e4uQ1wyBkE79iT721mwpZhCfNvT3jdVMvw==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@pwrs/cem/-/cem-0.2.14.tgz", + "integrity": "sha512-Z7AqS0qGZDsNOrVDkJSozaph/8KPrtMsceqzPacGev6Li1iCgXxOEBQdNStbRe/Z8jHWrMJyj9roTzKsRlZmrA==", "dev": true, "hasInstallScript": true, "bin": { @@ -2920,18 +2920,18 @@ "node": ">=22.0.0" }, "optionalDependencies": { - "@pwrs/cem-darwin-arm64": "0.2.3", - "@pwrs/cem-darwin-x64": "0.2.3", - "@pwrs/cem-linux-arm64": "0.2.3", - "@pwrs/cem-linux-x64": "0.2.3", - "@pwrs/cem-win32-arm64": "0.2.3", - "@pwrs/cem-win32-x64": "0.2.3" + "@pwrs/cem-darwin-arm64": "0.2.14", + "@pwrs/cem-darwin-x64": "0.2.14", + "@pwrs/cem-linux-arm64": "0.2.14", + "@pwrs/cem-linux-x64": "0.2.14", + "@pwrs/cem-win32-arm64": "0.2.14", + "@pwrs/cem-win32-x64": "0.2.14" } }, "node_modules/@pwrs/cem-darwin-arm64": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@pwrs/cem-darwin-arm64/-/cem-darwin-arm64-0.2.3.tgz", - "integrity": "sha512-vEVtA7ULjFA/ErxEIORkgfi7VKYSeULHO/T+Nsx2tfkkS26UYZgsOMtWidEDPgetoN0/pbT22i+ZMCXI+yOHeg==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@pwrs/cem-darwin-arm64/-/cem-darwin-arm64-0.2.14.tgz", + "integrity": "sha512-5LSa3AZDJ8hRGBKWWQx1jG9AIX4GiXwnejaSb3m9H4QplEM53gCeOtDVi2tUdrWUaWSa4jkCIqbcBLk0ouZzfw==", "cpu": [ "arm64" ], @@ -2945,9 +2945,9 @@ } }, "node_modules/@pwrs/cem-darwin-x64": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@pwrs/cem-darwin-x64/-/cem-darwin-x64-0.2.3.tgz", - "integrity": "sha512-wOJZwOTCNmcUmzianKNnqBt9sei54gil0G3b8w7yvsupUaxhd4qOazgUxpt/g070drNFQ94YvlYd5CMEnY8iTw==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@pwrs/cem-darwin-x64/-/cem-darwin-x64-0.2.14.tgz", + "integrity": "sha512-olyVHNNDZ/yFD/+F1pEp0vVwPyDIKskDSSXMOAjN93FbnrlBjCWKRqV46xvegpXlgu5BpK2zayCWzhIrDc6Kgw==", "cpu": [ "x64" ], @@ -2961,9 +2961,9 @@ } }, "node_modules/@pwrs/cem-linux-arm64": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@pwrs/cem-linux-arm64/-/cem-linux-arm64-0.2.3.tgz", - "integrity": "sha512-mHAcg2sSemq5WSK888PccSlO17P1dScpLYblzOxZVNpyILsIpmLrV8czqBzGVFvSK4S95QmkTBD9ziXTl1O84A==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@pwrs/cem-linux-arm64/-/cem-linux-arm64-0.2.14.tgz", + "integrity": "sha512-+NbvjhZh4D59xeZ1lreHn5CVE2Ik1kbpdCLWJOGh7cxR9G264I15FBExqGuD1GFH9dkkt5H0XlIfYQ15mjN83w==", "cpu": [ "arm64" ], @@ -2977,9 +2977,9 @@ } }, "node_modules/@pwrs/cem-linux-x64": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@pwrs/cem-linux-x64/-/cem-linux-x64-0.2.3.tgz", - "integrity": "sha512-iKC9ZXvMa8/P1obooT1kvwT2I6MyjU6Vj3K4ZXQ5FnbA+OBZq8S4/Y5ydUeWlHyNpgsu+IwRBsAKWKOz4hBXOw==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@pwrs/cem-linux-x64/-/cem-linux-x64-0.2.14.tgz", + "integrity": "sha512-5XDRR+nO7xEuR61AB4vp/4k/NBbH4rvTqGg7wiEpempRK4791zODodkzhQswCcfdEZDqD4c4q7FqtQX06bzOyg==", "cpu": [ "x64" ], @@ -2993,9 +2993,9 @@ } }, "node_modules/@pwrs/cem-win32-arm64": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@pwrs/cem-win32-arm64/-/cem-win32-arm64-0.2.3.tgz", - "integrity": "sha512-s1eTweuInPZyElmpQActA25cJxlmRY0FO1PfCGVBu+RtbygbiML7jujZnKRDbWssdfa+2cw6I9jnrv4isH9Dag==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@pwrs/cem-win32-arm64/-/cem-win32-arm64-0.2.14.tgz", + "integrity": "sha512-t80RdOliVBT/rghUJKxEdDJtMnjRZhOcUFY9ET1DEvCcnpUZbXjnSllw53OcpQY5YXCq0GyhLNGBEgkZ1OpjMQ==", "cpu": [ "arm64" ], @@ -3010,9 +3010,9 @@ } }, "node_modules/@pwrs/cem-win32-x64": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@pwrs/cem-win32-x64/-/cem-win32-x64-0.2.3.tgz", - "integrity": "sha512-HMHZjbxE51hDB43Gww+2QZvCU1o7ZTJjmdIy7rsAA167vxY5J//F8ElaO7I/fH9JRrzSOyPadkEbX0JHyye/zQ==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@pwrs/cem-win32-x64/-/cem-win32-x64-0.2.14.tgz", + "integrity": "sha512-dsL7MWn5JcTFSL1sI3O65ou6VP3cMntUc0pESaR0H1hwp9NpcI+It9cUgkjEZRASEZcglMkfUVrop0mDzinTBg==", "cpu": [ "x64" ], @@ -17398,7 +17398,7 @@ }, "tools/pfe-tools": { "name": "@patternfly/pfe-tools", - "version": "5.0.1", + "version": "5.0.3", "license": "MIT", "devDependencies": { "@types/dedent": "^0.7.2", diff --git a/package.json b/package.json index 657bc129c3..aeaad72049 100644 --- a/package.json +++ b/package.json @@ -290,7 +290,7 @@ "@lit/react": "^1.0.5", "@octokit/core": "^6.1.2", "@patternfly/patternfly": "^4.224.5", - "@pwrs/cem": "^0.2.3", + "@pwrs/cem": "^0.2.14", "@rhds/elements": "^1.4.5", "@types/koa__router": "^12.0.4", "@types/node": "^22.15.32", @@ -316,10 +316,10 @@ "optionalDependencies": { "@esbuild/darwin-arm64": "^0.23.1", "@esbuild/linux-x64": "^0.23.1", - "@pwrs/cem-darwin-arm64": "^0.2.3", - "@pwrs/cem-darwin-x64": "^0.2.3", - "@pwrs/cem-linux-arm64": "^0.2.3", - "@pwrs/cem-linux-x64": "^0.2.3", + "@pwrs/cem-darwin-arm64": "^0.2.14", + "@pwrs/cem-darwin-x64": "^0.2.14", + "@pwrs/cem-linux-arm64": "^0.2.14", + "@pwrs/cem-linux-x64": "^0.2.14", "@rollup/rollup-darwin-arm64": "^4.21.0" }, "workspaces": [ From faf70a4eb08fb4f47bc6938e323ade516d72f7ca Mon Sep 17 00:00:00 2001 From: Benny Powers Date: Fri, 25 Jul 2025 09:11:52 +0300 Subject: [PATCH 68/85] style: formatting, docs --- elements/pf-search-input/pf-search-input.ts | 165 ++++++-------------- 1 file changed, 50 insertions(+), 115 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 2d2df5fa25..49064ac607 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -19,6 +19,7 @@ import { PfOption } from '../pf-select/pf-option.js'; import { bound } from '@patternfly/pfe-core/decorators.js'; import styles from './pf-search-input.css'; +/** Fired when a `` element's value changes */ export class PfSearchChangeEvent extends Event { constructor() { super('change', { bubbles: true }); @@ -33,79 +34,18 @@ export class PfSearchChangeEvent extends Event { * Unlike selects or dropdowns, which offer predefined options, a search input lets users enter * their own keywords to filter or locate results. It includes a clear (×) button to easily * remove the current input, allowing users to start a new search quickly. - * @slot - insert `pf-option` here - * @slot placeholder - placeholder text for the search input. Overrides the `placeholder` attribute. + * + * @summary Allows users to search through a list for specific search terms + * * @fires open - when the menu toggles open * @fires close - when the menu toggles closed - * @cssprop [--pf-c-search-input__toggle--PaddingTop=var(--pf-global--spacer--form-element, 0.375rem)] - * @cssprop [--pf-c-search-input__toggle--PaddingRight=var(--pf-global--spacer--sm, 0.5rem)] - * @cssprop [--pf-c-search-input__toggle--PaddingBottom=var(--pf-global--spacer--form-element, 0.375rem)] - * @cssprop [--pf-c-search-input__toggle--PaddingLeft=var(--pf-global--spacer--sm, 0.5rem)] - * @cssprop [--pf-c-search-input__toggle--MinWidth=var(--pf-global--target-size--MinWidth, 44px)] - * @cssprop [--pf-c-search-input__toggle--FontSize=var(--pf-global--FontSize--md, 1rem)] - * @cssprop [--pf-c-search-input__toggle--FontWeight=var(--pf-global--FontWeight--normal, 400)] - * @cssprop [--pf-c-search-input__toggle--LineHeight=var(--pf-global--LineHeight--md, 1.5)] - * @cssprop [--pf-c-search-input__toggle--BackgroundColor=var(--pf-global--BackgroundColor--100, #fff)] - * @cssprop [--pf-c-search-input__toggle--before--BorderTopWidth=var(--pf-global--BorderWidth--sm, 1px)] - * @cssprop [--pf-c-search-input__toggle--before--BorderRightWidth=var(--pf-global--BorderWidth--sm, 1px)] - * @cssprop [--pf-c-search-input__toggle--before--BorderBottomWidth=var(--pf-global--BorderWidth--sm, 1px)] - * @cssprop [--pf-c-search-input__toggle--before--BorderLeftWidth=var(--pf-global--BorderWidth--sm, 1px)] - * @cssprop [--pf-c-search-input__toggle--before--BorderWidth=initial] - * @cssprop [--pf-c-search-input__toggle--before--BorderTopColor=var(--pf-global--BorderColor--300, #f0f0f0)] - * @cssprop [--pf-c-search-input__toggle--before--BorderRightColor=var(--pf-global--BorderColor--300, #f0f0f0)] - * @cssprop [--pf-c-search-input__toggle--before--BorderBottomColor=var(--pf-global--BorderColor--200, #8a8d90)] - * @cssprop [--pf-c-search-input__toggle--before--BorderLeftColor=var(--pf-global--BorderColor--300, #f0f0f0)] - * @cssprop [--pf-c-search-input__toggle--Color=var(--pf-global--Color--100, #151515)] - * @cssprop [--pf-c-search-input__toggle--hover--before--BorderBottomColor=var(--pf-global--active-color--100, #06c)] - * @cssprop [--pf-c-search-input__toggle--focus--before--BorderBottomColor=var(--pf-global--active-color--100, #06c)] - * @cssprop [--pf-c-search-input__toggle--focus--before--BorderBottomWidth=var(--pf-global--BorderWidth--md, 2px)] - * @cssprop [--pf-c-search-input__toggle--active--before--BorderBottomColor=var(--pf-global--active-color--100, #06c)] - * @cssprop [--pf-c-search-input__toggle--active--before--BorderBottomWidth=var(--pf-global--BorderWidth--md, 2px)] - * @cssprop [--pf-c-search-input__toggle--m-expanded--before--BorderBottomColor=var(--pf-global--active-color--100, #06c)] - * @cssprop [--pf-c-search-input__toggle--m-expanded--before--BorderBottomWidth=var(--pf-global--BorderWidth--md, 2px)] - * @cssprop [--pf-c-search-input__toggle--disabled--BackgroundColor=var(--pf-global--disabled-color--300, #f0f0f0)] - * @cssprop [--pf-c-search-input__toggle--m-plain--before--BorderColor=transparent] - * @cssprop [--pf-c-search-input__toggle--m-placeholder--Color=transparent] - * @cssprop [--pf-c-search-input--m-invalid__toggle--before--BorderBottomColor=var(--pf-global--danger-color--100, #c9190b)] - * @cssprop [--pf-c-search-input--m-invalid__toggle--before--BorderBottomWidth=var(--pf-global--BorderWidth--md, 2px)] - * @cssprop [--pf-c-search-input--m-invalid__toggle--hover--before--BorderBottomColor=var(--pf-global--danger-color--100, #c9190b)] - * @cssprop [--pf-c-search-input--m-invalid__toggle--focus--before--BorderBottomColor=var(--pf-global--danger-color--100, #c9190b)] - * @cssprop [--pf-c-search-input--m-invalid__toggle--active--before--BorderBottomColor=var(--pf-global--danger-color--100, #c9190b)] - * @cssprop [--pf-c-search-input--m-invalid__toggle--m-expanded--before--BorderBottomColor=var(--pf-global--danger-color--100, #c9190b)] - * @cssprop [--pf-c-search-input--m-invalid__toggle-status-icon--Color=var(--pf-global--danger-color--100, #c9190b)] - * @cssprop [--pf-c-search-input--m-success__toggle--before--BorderBottomColor=var(--pf-global--success-color--100, #3e8635)] - * @cssprop [--pf-c-search-input--m-success__toggle--before--BorderBottomWidth=var(--pf-global--BorderWidth--md, 2px)] - * @cssprop [--pf-c-search-input--m-success__toggle--hover--before--BorderBottomColor=var(--pf-global--success-color--100, #3e8635)] - * @cssprop [--pf-c-search-input--m-success__toggle--focus--before--BorderBottomColor=var(--pf-global--success-color--100, #3e8635)] - * @cssprop [--pf-c-search-input--m-success__toggle--active--before--BorderBottomColor=var(--pf-global--success-color--100, #3e8635)] - * @cssprop [--pf-c-search-input--m-success__toggle--m-expanded--before--BorderBottomColor=var(--pf-global--success-color--100, #3e8635)] - * @cssprop [--pf-c-search-input--m-success__toggle-status-icon--Color=var(--pf-global--success-color--100, #3e8635)] - * @cssprop [--pf-c-search-input--m-warning__toggle--before--BorderBottomColor=var(--pf-global--warning-color--100, #f0ab00)] - * @cssprop [--pf-c-search-input--m-warning__toggle--before--BorderBottomWidth=var(--pf-global--BorderWidth--md, 2px)] - * @cssprop [--pf-c-search-input--m-warning__toggle--hover--before--BorderBottomColor=var(--pf-global--warning-color--100, #f0ab00)] - * @cssprop [--pf-c-search-input--m-warning__toggle--focus--before--BorderBottomColor=var(--pf-global--warning-color--100, #f0ab00)] - * @cssprop [--pf-c-search-input--m-warning__toggle--active--before--BorderBottomColor=var(--pf-global--warning-color--100, #f0ab00)] - * @cssprop [--pf-c-search-input--m-warning__toggle--m-expanded--before--BorderBottomColor=var(--pf-global--warning-color--100, #f0ab00)] - * @cssprop [--pf-c-search-input--m-warning__toggle-status-icon--Color=var(--pf-global--warning-color--100, #f0ab00)] - * @cssprop [--pf-c-search-input__toggle-wrapper--not-last-child--MarginRight=var(--pf-global--spacer--xs, 0.25rem)] - * @cssprop [--pf-c-search-input__toggle-wrapper--MaxWidth=calc(100% - var(--pf-global--spacer--lg, 1.5rem))] - * @cssprop [--pf-c-search-input__toggle--m-placeholder__toggle-text--Color=var(--pf-global--Color--dark-200, #6a6e73)] - * @cssprop [--pf-c-search-input__toggle-icon--toggle-text--MarginLeft=var(--pf-global--spacer--xs, 0.25rem)] - * @cssprop [--pf-c-search-input__toggle-status-icon--MarginLeft=var(--pf-global--spacer--xs, 0.25rem)] - * @cssprop [--pf-c-search-input__toggle-status-icon--Color=var(--pf-global--Color--100, #151515)] - * @cssprop [--pf-c-search-input--m-plain__toggle-arrow--Color=var(--pf-global--Color--200, #6a6e73)] - * @cssprop [--pf-c-search-input--m-plain--hover__toggle-arrow--Color=var(--pf-global--Color--100, #151515)] - * @cssprop [--pf-c-search-input__toggle-clear--PaddingRight=var(--pf-global--spacer--sm, 0.5rem)] - * @cssprop [--pf-c-search-input__toggle-clear--PaddingLeft=var(--pf-global--spacer--md, 1rem)] - * @cssprop [--pf-c-search-input__toggle-clear--toggle-button--PaddingLeft=var(--pf-global--spacer--sm, 0.5rem)] - * @cssprop [--pf-c-search-input__toggle-button--Color=var(--pf-global--Color--100, #151515)] - * @cssprop [--pf-c-search-input__list-item--m-loading--PaddingTop=var(--pf-global--spacer--sm, 0.5rem)] - * @cssprop [--pf-c-search-input__menu-content--MaxHeight=20rem;] - **/ + */ @customElement('pf-search-input') export class PfSearchInput extends LitElement { static readonly styles: CSSStyleSheet[] = [styles]; + static readonly formAssociated = true; + static override readonly shadowRootOptions: ShadowRootInit = { ...LitElement.shadowRootOptions, delegatesFocus: true, @@ -113,6 +53,21 @@ export class PfSearchInput extends LitElement { static instances: Set = new Set(); + static { + if (!isServer) { + document.addEventListener('click', event => { + for (const instance of PfSearchInput.instances) { + instance._onOutsideClick(event); + } + }); + document.addEventListener('focusout', () => { + for (const instance of PfSearchInput.instances) { + instance._onFocusOut(); + } + }); + } + } + /** Accessible label for the search input */ @property({ attribute: 'accessible-label' }) accessibleLabel?: string; @@ -179,21 +134,6 @@ export class PfSearchInput extends LitElement { setItemSelected: (item, selected) => this.#setItemSelected(item, selected), }); - static { - if (!isServer) { - document.addEventListener('click', event => { - for (const instance of PfSearchInput.instances) { - instance._onOutsideClick(event); - } - }); - document.addEventListener('focusout', () => { - for (const instance of PfSearchInput.instances) { - instance._onFocusOut(); - } - }); - } - } - connectedCallback(): void { super.connectedCallback(); PfSearchInput.instances.add(this); @@ -249,50 +189,45 @@ export class PfSearchInput extends LitElement { const { disabled, expanded, placeholder } = this; const { anchor = 'bottom', alignment = 'start', styles = {} } = this.#float; const { height, width } = this.getBoundingClientRect?.() || {}; - const hideLightDomItems = !ComboboxController.supportsCrossRootActiveDescendant; return html` -
+
search
- +
- - close + + close
-
+
${this.#combobox.renderItemsToShadowRoot()} - + +
@@ -374,7 +309,7 @@ export class PfSearchInput extends LitElement { } } - async #OnClose() { + async #onClose() { if (this.expanded) { await this.hide(); } @@ -391,7 +326,7 @@ export class PfSearchInput extends LitElement { return false; } - #onChange(event: Event) { + #onChange() { this.value = this._toggleInput?.value; this.#internals.setFormValue(this.value ?? ''); this.dispatchEvent(new PfSearchChangeEvent()); From 46bfb598e47edf82215ad8b7ce4a9635e8857662 Mon Sep 17 00:00:00 2001 From: Arathy Kumar <49025521+ArathyKumar@users.noreply.github.com> Date: Fri, 25 Jul 2025 15:58:59 +0530 Subject: [PATCH 69/85] Update elements/pf-search-input/pf-search-input.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Benny Powers - עם ישראל חי! --- elements/pf-search-input/pf-search-input.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 49064ac607..42f2f1c0cc 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -71,9 +71,6 @@ export class PfSearchInput extends LitElement { /** Accessible label for the search input */ @property({ attribute: 'accessible-label' }) accessibleLabel?: string; - /** Multi listbox button text */ - @property({ attribute: 'items-selected-text' }) itemsSelectedText = 'items selected'; - /** Whether the search input is disabled */ @property({ type: Boolean, reflect: true }) disabled = false; From f2c6d5e159b0d32a050a30718c6832c646cf1352 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Fri, 25 Jul 2025 17:26:12 +0530 Subject: [PATCH 70/85] fix: selected property removed --- .../pf-search-input/demo/pf-search-input.html | 40 +++++++++---------- elements/pf-search-input/pf-search-input.ts | 28 ++++--------- 2 files changed, 27 insertions(+), 41 deletions(-) diff --git a/elements/pf-search-input/demo/pf-search-input.html b/elements/pf-search-input/demo/pf-search-input.html index bfc54a1ee2..9a48121cba 100644 --- a/elements/pf-search-input/demo/pf-search-input.html +++ b/elements/pf-search-input/demo/pf-search-input.html @@ -1,25 +1,25 @@
- Alabama - New Jersey - New York - New Mexico - North Carolina - Alabama 1 - New Jersey 1 - New York 1 - New Mexico 1 - North Carolina 1 - Alabama 2 - New Jersey 2 - New York 2 - New Mexico 2 - North Carolina 2 - Alabama 3 - New Jersey 3 - New York 3 - New Mexico 3 - North Carolina 3 + What is Red Hat Enterprise Linux? + How does Red Hat OpenShift work? + Why use Red Hat Ansible for automation? + Where can Red Hat OpenShift be deployed? + When should you use Red Hat Enterprise Linux? + What is Red Hat Satellite? + How does Red Hat integrate with AWS and other clouds? + Why choose Red Hat over other Linux vendors? + Where can I learn Red Hat technologies? + When does support end for RHEL versions? + What are Red Hat certifications? + How do you secure a RHEL server? + Why use OpenShift instead of vanilla Kubernetes? + Where is Red Hat headquartered? + When should you use Red Hat CoreOS? + What is Red Hat Insights? + How do you manage Red Hat subscriptions? + Why is RHEL considered enterprise-grade? + Where can I download RHEL for testing? + When was Red Hat founded?
diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 42f2f1c0cc..fbb433d1a0 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -158,18 +158,6 @@ export class PfSearchInput extends LitElement { } } - /** - * Set selected option - */ - @property({ hasChanged: (a, b) => !arraysAreEquivalent(a, b) }) - set selected(selected: PfOption) { - this.#combobox.selected = [selected]; - } - - get selected(): PfOption[] { - return this.#combobox.selected; - } - /** List of options */ get options(): PfOption[] { if (isServer) { @@ -247,14 +235,6 @@ export class PfSearchInput extends LitElement { } } - @observes('selected') - private async selectedChanged(_: PfOption[], selected: PfOption[]) { - this.value = selected.map(x => x.value).join(); - await this.updateComplete; - this._toggleInput!.value = this.value; - } - - @observes('value') private valueChanged() { this.#internals.setFormValue(this.value ?? ''); @@ -325,6 +305,9 @@ export class PfSearchInput extends LitElement { #onChange() { this.value = this._toggleInput?.value; + if (this.value !== this.#combobox.selected[0]?.value) { + this.#combobox.selected = []; + } this.#internals.setFormValue(this.value ?? ''); this.dispatchEvent(new PfSearchChangeEvent()); } @@ -360,7 +343,10 @@ export class PfSearchInput extends LitElement { #setItemSelected(item: PfOption, selected: boolean) { item.selected = selected; - this.#setItemActive(item, selected); + if (selected) { + this.value = item.value; + this._toggleInput!.value = this.value; + } } #setItemActive(item: PfOption, active: boolean) { From dcad921d677830238407dc80a7f4c803e5e1616b Mon Sep 17 00:00:00 2001 From: Arathy Kumar <49025521+ArathyKumar@users.noreply.github.com> Date: Fri, 25 Jul 2025 17:33:39 +0530 Subject: [PATCH 71/85] Update elements/pf-search-input/pf-search-input.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Benny Powers - עם ישראל חי! --- elements/pf-search-input/pf-search-input.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index fbb433d1a0..278c92475b 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -330,12 +330,8 @@ export class PfSearchInput extends LitElement { } } - #delay(ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)); - } - async #showListbox() { - await this.#delay(10); + await new Promise(requestAnimationFrame); if (!this.disabled) { this.expanded ||= true; } From b034fcf5cf69ba1df3fe54620745449de22c6b2a Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Mon, 28 Jul 2025 18:14:18 +0530 Subject: [PATCH 72/85] fix: move focusout handling into ComboboxController --- .../controllers/combobox-controller.ts | 37 ++++++++++++++++ elements/pf-search-input/pf-search-input.ts | 43 +------------------ 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/core/pfe-core/controllers/combobox-controller.ts b/core/pfe-core/controllers/combobox-controller.ts index a15669032d..70f34c3fd5 100644 --- a/core/pfe-core/controllers/combobox-controller.ts +++ b/core/pfe-core/controllers/combobox-controller.ts @@ -188,6 +188,10 @@ export class ComboboxController< private static langsRE = new RegExp(ComboboxController.langs.join('|')); + private static instances = new WeakMap>(); + + private static hosts = new Set(); + static { // apply visually-hidden styles this.#alertTemplate.innerHTML = ` @@ -205,6 +209,19 @@ export class ComboboxController< `; } + // Hide listbox on focusout + static { + document.addEventListener('focusout', event => { + const target = event.target as HTMLElement; + for (const host of ComboboxController.hosts) { + if (host instanceof Node && host.contains(target)) { + const instance = ComboboxController.instances.get(host); + instance?._onFocusoutElement(); + } + } + }); + } + private options: RequireProps, | 'isItemDisabled' | 'isItem' @@ -333,6 +350,8 @@ export class ComboboxController< isItemDisabled: this.options.isItemDisabled, setItemSelected: this.options.setItemSelected, }); + ComboboxController.instances.set(host, this); + ComboboxController.hosts.add(host); } async hostConnected(): Promise { @@ -359,6 +378,24 @@ export class ComboboxController< this.#fc?.hostDisconnected(); } + disconnect(): void { + ComboboxController.instances.delete(this.host); + ComboboxController.hosts.delete(this.host); + } + + async _onFocusoutElement(): Promise { + if (this.#hasTextInput && this.options.isExpanded()) { + const root = this.#element?.getRootNode(); + await new Promise(requestAnimationFrame); + if (root instanceof ShadowRoot || root instanceof Document) { + const { activeElement } = root; + if (!this.#element?.contains(activeElement)) { + this.#hide(); + } + } + } + } + /** * Order of operations is important */ diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 278c92475b..45ad3c8b5c 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -51,23 +51,6 @@ export class PfSearchInput extends LitElement { delegatesFocus: true, }; - static instances: Set = new Set(); - - static { - if (!isServer) { - document.addEventListener('click', event => { - for (const instance of PfSearchInput.instances) { - instance._onOutsideClick(event); - } - }); - document.addEventListener('focusout', () => { - for (const instance of PfSearchInput.instances) { - instance._onFocusOut(); - } - }); - } - } - /** Accessible label for the search input */ @property({ attribute: 'accessible-label' }) accessibleLabel?: string; @@ -77,11 +60,6 @@ export class PfSearchInput extends LitElement { /** Whether the search input's listbox is expanded */ @property({ type: Boolean, reflect: true }) expanded = false; - /** - * Enable to flip listbox when it reaches boundary - */ - @property({ attribute: 'enable-flip', type: Boolean }) enableFlip = false; - /** Current form value */ @property() value?: string; @@ -133,29 +111,10 @@ export class PfSearchInput extends LitElement { connectedCallback(): void { super.connectedCallback(); - PfSearchInput.instances.add(this); } disconnectedCallback(): void { super.disconnectedCallback(); - PfSearchInput.instances.delete(this); - } - - // Function to handle the closing of popover on outside click - @bound private _onOutsideClick(event: MouseEvent) { - const path = event.composedPath(); - if (!path.includes(this._searchInputContainer)) { - if (this.expanded) { - this.expanded = false; - } - } - } - - // Function to handle the closing of popover on focus out - @bound private _onFocusOut() { - if (this.expanded) { - this.expanded = false; - } } /** List of options */ @@ -243,7 +202,7 @@ export class PfSearchInput extends LitElement { async #doExpand() { try { - await this.#float.show({ placement: this.position || 'bottom', flip: !!this.enableFlip }); + await this.#float.show({ placement: this.position || 'bottom', flip: true }); return true; } catch { return false; From 22e9d392d92d1814742d127354f202b43c88b047 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Mon, 28 Jul 2025 18:25:15 +0530 Subject: [PATCH 73/85] fix: ssr issue --- .../controllers/combobox-controller.ts | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/core/pfe-core/controllers/combobox-controller.ts b/core/pfe-core/controllers/combobox-controller.ts index 70f34c3fd5..cfdb749006 100644 --- a/core/pfe-core/controllers/combobox-controller.ts +++ b/core/pfe-core/controllers/combobox-controller.ts @@ -1,4 +1,4 @@ -import { nothing, type ReactiveController, type ReactiveControllerHost } from 'lit'; +import { isServer, nothing, type ReactiveController, type ReactiveControllerHost } from 'lit'; import type { ActivedescendantControllerOptions } from './activedescendant-controller.js'; import type { RovingTabindexControllerOptions } from './roving-tabindex-controller.js'; import type { ATFocusController } from './at-focus-controller'; @@ -211,15 +211,17 @@ export class ComboboxController< // Hide listbox on focusout static { - document.addEventListener('focusout', event => { - const target = event.target as HTMLElement; - for (const host of ComboboxController.hosts) { - if (host instanceof Node && host.contains(target)) { - const instance = ComboboxController.instances.get(host); - instance?._onFocusoutElement(); + if (!isServer) { + document.addEventListener('focusout', event => { + const target = event.target as HTMLElement; + for (const host of ComboboxController.hosts) { + if (host instanceof Node && host.contains(target)) { + const instance = ComboboxController.instances.get(host); + instance?._onFocusoutElement(); + } } - } - }); + }); + } } private options: RequireProps, From 175f56be43bbf8fd129ada358fc76f18dd16ef76 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Wed, 30 Jul 2025 16:37:04 +0530 Subject: [PATCH 74/85] chore: extend toggle button to support close functionality --- .../controllers/combobox-controller.ts | 5 --- .../test/combobox-controller.spec.ts | 18 +++++------ elements/pf-search-input/pf-search-input.css | 2 +- elements/pf-search-input/pf-search-input.ts | 32 +++++++++++-------- elements/pf-select/pf-select.ts | 4 +-- 5 files changed, 31 insertions(+), 30 deletions(-) diff --git a/core/pfe-core/controllers/combobox-controller.ts b/core/pfe-core/controllers/combobox-controller.ts index cfdb749006..c69e129ea5 100644 --- a/core/pfe-core/controllers/combobox-controller.ts +++ b/core/pfe-core/controllers/combobox-controller.ts @@ -368,11 +368,6 @@ export class ComboboxController< const expanded = this.options.isExpanded(); this.#button?.setAttribute('aria-expanded', String(expanded)); this.#input?.setAttribute('aria-expanded', String(expanded)); - if (this.#hasTextInput) { - this.#button?.setAttribute('tabindex', '-1'); - } else { - this.#button?.removeAttribute('tabindex'); - } this.#initLabels(); } diff --git a/core/pfe-core/controllers/test/combobox-controller.spec.ts b/core/pfe-core/controllers/test/combobox-controller.spec.ts index 6bf92712db..1249ab1d34 100644 --- a/core/pfe-core/controllers/test/combobox-controller.spec.ts +++ b/core/pfe-core/controllers/test/combobox-controller.spec.ts @@ -108,15 +108,15 @@ abstract class TestCombobox extends ReactiveElement { expect(await a11ySnapshot()).axTreeFocusedNode.to.have.axRole('combobox'); }); - describe('Tab', function() { - beforeEach(press('Tab')); - beforeEach(updateComplete); - beforeEach(nextFrame); - - it('does not focus the toggle button', async function() { - expect(await a11ySnapshot()).to.not.axContainQuery({ focused: true }); - }); - }); + // describe('Tab', function() { + // beforeEach(press('Tab')); + // beforeEach(updateComplete); + // beforeEach(nextFrame); + + // it('does not focus the toggle button', async function() { + // expect(await a11ySnapshot()).to.not.axContainQuery({ focused: true }); + // }); + // }); describe('ArrowDown', function() { beforeEach(press('ArrowDown')); diff --git a/elements/pf-search-input/pf-search-input.css b/elements/pf-search-input/pf-search-input.css index e32184d64c..0e6bb54862 100644 --- a/elements/pf-search-input/pf-search-input.css +++ b/elements/pf-search-input/pf-search-input.css @@ -177,7 +177,7 @@ cursor: not-allowed; } -#close-button { +.close-button { --pf-c-button--PaddingLeft: var(--pf-global--spacer--sm, 0.5rem); --pf-c-button--PaddingRight: var(--pf-global--spacer--sm, 0.5rem); --pf-c-button--PaddingTop: var(--pf-global--spacer--xs, 0.25rem); diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index 45ad3c8b5c..0c4d14b867 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -83,14 +83,15 @@ export class PfSearchInput extends LitElement { @query('#placeholder') private _placeholder?: PfOption; - @query('#outer') private _searchInputContainer!: HTMLElement; - #internals = InternalsController.of(this); #float = new FloatingDOMController(this, { content: () => this._listboxContainer }); #slots = new SlotController(this, null, 'placeholder'); + /** True when the user just clicked the close button */ + #clickedCloseButton = false; + #combobox = ComboboxController.of(this, { getItems: () => this.options, getFallbackLabel: () => this.accessibleLabel @@ -100,7 +101,7 @@ export class PfSearchInput extends LitElement { getListboxElement: () => this._listbox ?? null, getToggleButton: () => this._toggleButton ?? null, getComboboxInput: () => this._toggleInput ?? null, - isExpanded: () => this.expanded, + isExpanded: () => this.#setIsExpanded(), requestShowListbox: () => this.#showListbox(), requestHideListbox: () => void (this.expanded &&= false), setItemHidden: (item, hidden) => (item.id !== 'placeholder') && void (item.hidden = hidden), @@ -149,17 +150,17 @@ export class PfSearchInput extends LitElement { @keyup="${this.#onSubmit}" @keydown="${this.#onKeyDown}">
- + @click="${this.#onClickCloseButton}"> close
-
`} - + + `); + + searchInput = form.querySelector('pf-search-input')!; + beforeEach(updateComplete); + + form.addEventListener('submit', e => { + e.preventDefault(); + submittedData = new FormData(form); + }); + }); + + describe('when a user types and selects an option', function() { + describe('focus', function() { + beforeEach(focus); + beforeEach(() => aTimeout(300)); + beforeEach(updateComplete); + describe('press `New`', function() { + beforeEach(updateComplete); + beforeEach(() => aTimeout(300)); + beforeEach(press('N')); + beforeEach(() => aTimeout(300)); + beforeEach(press('e')); + beforeEach(() => aTimeout(300)); + beforeEach(press('w')); + + describe('select the first option starting with `New` and submit the form', function() { + beforeEach(updateComplete); + beforeEach(() => aTimeout(300)); + beforeEach(press('ArrowDown')); + beforeEach(() => aTimeout(300)); + beforeEach(press('Enter')); + beforeEach(updateComplete); + + it('should select the option', function() { + expect(getSelectedOptionValue(searchInput)).to.deep.equal([ + 'New York', + ]); + }); + + it('should close the dropdown after selection', function() { + expect(searchInput.expanded).to.be.false; + }); + + it('should keep selected value in input after submission', function() { + const input = searchInput.shadowRoot?.querySelector('input'); + expect(input?.value).to.equal('New York'); + }); + + describe('on form submit event', function() { + it('should submit the selected value from pf-search-input', async function() { + const event = new SubmitEvent('submit', { + bubbles: true, + cancelable: true, + }); + + form.dispatchEvent(event); + expect(event.defaultPrevented).to.be.true; + + expect(submittedData).to.not.be.null; + expect(submittedData?.get('search')).to.equal('New York'); + }); + }); + + describe('on submit button click', function() { + it('should submit the selected value', async function() { + form.querySelector('button')?.click(); + beforeEach(() => aTimeout(300)); + + expect(submittedData).to.not.be.null; + expect(submittedData?.get('search')).to.equal('New York'); + }); + }); + + describe('form submit on clicking `enter` key', function() { + beforeEach(press('Enter')); + beforeEach(updateComplete); + + it('should submit the selected value', function() { + expect(submittedData).to.not.be.null; + expect(submittedData?.get('search')).to.equal('New York'); + }); + }); + }); + }); + }); + }); + }); }); }); From 6c23f3e796d39db152d32060b329beca1b262712 Mon Sep 17 00:00:00 2001 From: ArathyKumar Date: Tue, 5 Aug 2025 17:01:30 +0530 Subject: [PATCH 82/85] chore: code cleanup --- elements/pf-search-input/pf-search-input.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index eb81af2924..ab2e4e4e29 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -265,15 +265,6 @@ export class PfSearchInput extends LitElement { if (this.value !== this.#combobox.selected[0]?.value) { this.#combobox.selected = []; } - // Will remove after review - // for (const item of this.#combobox.items){ - // if (item.hasAttribute('selected')) { - // if(item.value !== this.value){ - // this.#setItemSelected(item, false); - // this.requestUpdate(); - // } - // } - // } } #onSubmit(event: KeyboardEvent) { From c8fc771d4d5f178ad5ad3c629e5118b017fe2a30 Mon Sep 17 00:00:00 2001 From: Benny Powers Date: Wed, 6 Aug 2025 15:12:31 +0300 Subject: [PATCH 83/85] fix: reset combobox selected state --- elements/pf-search-input/pf-search-input.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/elements/pf-search-input/pf-search-input.ts b/elements/pf-search-input/pf-search-input.ts index ab2e4e4e29..46c6e35178 100644 --- a/elements/pf-search-input/pf-search-input.ts +++ b/elements/pf-search-input/pf-search-input.ts @@ -248,7 +248,6 @@ export class PfSearchInput extends LitElement { #onClickCloseButton() { this._toggleInput!.value = ''; this.#updateValue(this._toggleInput?.value ?? ''); - this.#combobox.selected = []; this.#clickedCloseButton = true; this._toggleInput?.focus(); } @@ -262,9 +261,6 @@ export class PfSearchInput extends LitElement { #onChange() { this.#updateValue(this._toggleInput?.value ?? ''); - if (this.value !== this.#combobox.selected[0]?.value) { - this.#combobox.selected = []; - } } #onSubmit(event: KeyboardEvent) { @@ -275,6 +271,11 @@ export class PfSearchInput extends LitElement { #updateValue(value: string) { this.value = value; + // it's necessary to reset the 'selected' state of combobox + // since otherwise, combobox controller will attempt to prevent us from + // re-selecting the last-selected item, even though pf-search-input + // doesn't have a selected property + this.#combobox.selected = []; } #onKeyDown(event: KeyboardEvent) { From 5bc1ecd2b5525c6e790c559d8a2e0290a88ddca2 Mon Sep 17 00:00:00 2001 From: Benny Powers Date: Wed, 6 Aug 2025 16:52:17 +0300 Subject: [PATCH 84/85] test(search-input): reorganize suites --- .../test/pf-search-input.spec.ts | 1668 ++++++++--------- 1 file changed, 834 insertions(+), 834 deletions(-) diff --git a/elements/pf-search-input/test/pf-search-input.spec.ts b/elements/pf-search-input/test/pf-search-input.spec.ts index b6386624bb..0c6a95fab6 100644 --- a/elements/pf-search-input/test/pf-search-input.spec.ts +++ b/elements/pf-search-input/test/pf-search-input.spec.ts @@ -64,602 +64,623 @@ describe('', function() { .and .to.be.an.instanceOf(PfSearchInput); }); + }); - describe('with accessible-label attribute and 3 items', function() { - let element: PfSearchInput; - const updateComplete = () => element.updateComplete; + describe('with accessible-label attribute and 3 items', function() { + let element: PfSearchInput; + const updateComplete = () => element.updateComplete; + + beforeEach(async function() { + element = await createFixture(html` + + 1 + 2 + 3 + `); + }); - beforeEach(async function() { - element = await createFixture(html` - - 1 - 2 - 3 - `); - }); + it('passes aXe audit', async function() { + await expect(element).to.be.accessible(); + }); - it('passes aXe audit', async function() { - await expect(element).to.be.accessible(); - }); - - it('labels the combobox with the accessible-label attribuet', async function() { - expect(await a11ySnapshot()).to.axContainQuery({ - role: 'combobox', - name: 'label', - }); + it('labels the combobox with the accessible-label attribuet', async function() { + expect(await a11ySnapshot()).to.axContainQuery({ + role: 'combobox', + name: 'label', }); + }); - it('does not have redundant role', async function() { - expect(element.shadowRoot?.firstElementChild).to.not.contain('[role="button"]'); - }); + it('does not have redundant role', async function() { + expect(element.shadowRoot?.firstElementChild).to.not.contain('[role="button"]'); + }); - it('sets aria-setsize="3" and aria-posinset on items', function() { - element.options.forEach((option, i) => { - expect(option).to.have.attr('aria-setsize', '3'); - expect(option).to.have.attr('aria-posinset', `${i + 1}`); - }); + it('sets aria-setsize="3" and aria-posinset on items', function() { + element.options.forEach((option, i) => { + expect(option).to.have.attr('aria-setsize', '3'); + expect(option).to.have.attr('aria-posinset', `${i + 1}`); }); + }); - describe('focus()', function() { - beforeEach(press('Tab')); + describe('focus()', function() { + beforeEach(press('Tab')); + beforeEach(updateComplete); + describe('ArrowDown', function() { + beforeEach(press('ArrowDown')); + beforeEach(() => aTimeout(300)); beforeEach(updateComplete); - describe('ArrowDown', function() { - beforeEach(press('ArrowDown')); - beforeEach(() => aTimeout(300)); - beforeEach(updateComplete); - it('labels the listbox with the accessible-label attribute', async function() { - const snap = await a11ySnapshot(); - expect(snap).to.axContainQuery({ - role: 'listbox', - name: 'label', - }); + it('labels the listbox with the accessible-label attribute', async function() { + const snap = await a11ySnapshot(); + expect(snap).to.axContainQuery({ + role: 'listbox', + name: 'label', }); + }); - it('focuses on the first item', async function() { - expect(getActiveOption(element)).to.have.value('1'); - }); + it('focuses on the first item', async function() { + expect(getActiveOption(element)).to.have.value('1'); }); }); }); + }); - describe('with 3 items and associated