Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/plain-mode-hides-ask.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@loquix/core': patch
---

Fix `loquix-search-input` rendering the "Ask AI" button in `mode="plain"`.

`show-ask-affordance` used to win over `mode`, so the plain-mode surfaces of
`loquix-search-dialog` and `loquix-search-panel` — which both set the attribute
on their inner input unconditionally — still showed the button, and clicking it
dispatched a `loquix-search-ask` event the host never opted into. Plain mode now
suppresses the affordance regardless of `show-ask-affordance`.
4 changes: 2 additions & 2 deletions packages/core/custom-elements.json
Original file line number Diff line number Diff line change
Expand Up @@ -12567,7 +12567,7 @@
"text": "boolean"
},
"default": "false",
"description": "Force the smart affordance to be visible.",
"description": "Force the smart affordance to be visible. Ignored when `mode` is `plain`.",
"attribute": "show-ask-affordance"
},
{
Expand Down Expand Up @@ -12800,7 +12800,7 @@
"text": "boolean"
},
"default": "false",
"description": "Force the smart affordance to be visible.",
"description": "Force the smart affordance to be visible. Ignored when `mode` is `plain`.",
"fieldName": "showAskAffordance"
},
{
Expand Down
26 changes: 26 additions & 0 deletions packages/core/src/components/core/loquix-search-dialog.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect, fixture, html } from '@open-wc/testing';
import type { LitElement } from 'lit';
import { waitForEvent } from '../../test-utils.js';
import './define-search-dialog.js';
import type { LoquixSearchDialog } from './loquix-search-dialog.js';
Expand Down Expand Up @@ -310,6 +311,31 @@ describe('loquix-search-dialog', () => {
expect(answer.getAttribute('state')).to.equal('generating');
});

it('shows the Ask AI affordance on the dialog input by default', async () => {
const el = await fixture<LoquixSearchDialog>(
html`<loquix-search-dialog open></loquix-search-dialog>`,
);
await el.updateComplete;

const dialogInput = el.shadowRoot!.querySelector('.dialog-input') as LitElement;
await dialogInput.updateComplete;

expect(dialogInput.shadowRoot!.querySelector('[part~="ask-button"]')).to.exist;
});

it('does not show the Ask AI affordance on the dialog input in plain mode', async () => {
const el = await fixture<LoquixSearchDialog>(
html`<loquix-search-dialog open mode="plain"></loquix-search-dialog>`,
);
await el.updateComplete;

const dialogInput = el.shadowRoot!.querySelector('.dialog-input') as LitElement;
await dialogInput.updateComplete;

const ask = dialogInput.shadowRoot!.querySelector('[part~="ask-button"]');
expect(ask === null, 'ask button must not render in plain mode').to.be.true;
});

it('syncs value from the dialog input change event', async () => {
const el = await fixture<LoquixSearchDialog>(
html`<loquix-search-dialog value="refund"></loquix-search-dialog>`,
Expand Down
13 changes: 13 additions & 0 deletions packages/core/src/components/core/loquix-search-input.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ describe('loquix-search-input', () => {
expect(ask!.querySelector('svg')).to.equal(null);
});

it('does not show Ask AI affordance in plain mode even when forced', async () => {
const el = await fixture<LoquixSearchInput>(
html`<loquix-search-input
mode="plain"
show-ask-affordance
value="What is our refund policy"
></loquix-search-input>`,
);
await el.updateComplete;
const ask = getShadowPart(el, 'ask-button');
expect(ask === null, 'ask button must not render in plain mode').to.be.true;
});

it('hides inline kbd when Ask AI affordance is visible by default', async () => {
const el = await fixture<LoquixSearchInput>(
html`<loquix-search-input
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/components/core/loquix-search-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export class LoquixSearchInput extends LitElement {
@property({ type: String, attribute: 'ask-label' })
askLabel?: string;

/** Force the smart affordance to be visible. */
/** Force the smart affordance to be visible. Ignored when `mode` is `plain`. */
@property({ type: Boolean, attribute: 'show-ask-affordance' })
showAskAffordance = false;

Expand All @@ -107,6 +107,9 @@ export class LoquixSearchInput extends LitElement {

private get _shouldShowAsk(): boolean {
if (this.disabled || this.state === 'searching') return false;
// Plain mode routes every submit to plain search, so the ask button would
// fire a smart submit the host never opted into.
if (this.mode === 'plain') return false;
if (this.showAskAffordance) return true;
return this.mode === 'auto' && this._looksLikeSmartQuery(this.value);
}
Expand Down
24 changes: 24 additions & 0 deletions packages/core/src/components/core/loquix-search-panel.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect, fixture, html } from '@open-wc/testing';
import type { LitElement } from 'lit';
import { waitForEvent } from '../../test-utils.js';
import './define-search-panel.js';
import type { LoquixSearchPanel } from './loquix-search-panel.js';
Expand Down Expand Up @@ -216,6 +217,29 @@ describe('loquix-search-panel', () => {
expect(answer.getAttribute('state')).to.equal('generating');
});

it('shows the Ask AI affordance on the inline input by default', async () => {
const el = await fixture<LoquixSearchPanel>(html`<loquix-search-panel></loquix-search-panel>`);
await el.updateComplete;

const input = el.shadowRoot!.querySelector('loquix-search-input[part="input"]') as LitElement;
await input.updateComplete;

expect(input.shadowRoot!.querySelector('[part~="ask-button"]')).to.exist;
});

it('does not show the Ask AI affordance on the inline input in plain mode', async () => {
const el = await fixture<LoquixSearchPanel>(
html`<loquix-search-panel mode="plain"></loquix-search-panel>`,
);
await el.updateComplete;

const input = el.shadowRoot!.querySelector('loquix-search-input[part="input"]') as LitElement;
await input.updateComplete;

const ask = input.shadowRoot!.querySelector('[part~="ask-button"]');
expect(ask === null, 'ask button must not render in plain mode').to.be.true;
});

it('syncs value from the input change event', async () => {
const el = await fixture<LoquixSearchPanel>(
html`<loquix-search-panel value="refund"></loquix-search-panel>`,
Expand Down
Loading