Skip to content

Commit

Permalink
feat(menu,select): allow menu and select typeahead to read default sl…
Browse files Browse the repository at this point in the history
…ot text content

PiperOrigin-RevId: 587864760
  • Loading branch information
Elliott Marquez authored and copybara-github committed Dec 4, 2023
1 parent a5a40b6 commit af49b64
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 20 deletions.
45 changes: 41 additions & 4 deletions menu/internal/controllers/menuItemController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ export interface MenuItemControllerConfig {
*/
getHeadlineElements: () => HTMLElement[];

/**
* A function that returns the supporting-text element of the menu item.
*/
getSupportingTextElements: () => HTMLElement[];

/**
* A function that returns the default slot / misc content.
*/
getDefaultElements: () => Node[];

/**
* The HTML Element that accepts user interactions like click. Used for
* occasions like programmatically clicking anchor tags when `Enter` is
Expand All @@ -87,6 +97,8 @@ export interface MenuItemControllerConfig {
export class MenuItemController implements ReactiveController {
private internalTypeaheadText: string | null = null;
private readonly getHeadlineElements: MenuItemControllerConfig['getHeadlineElements'];
private readonly getSupportingTextElements: MenuItemControllerConfig['getSupportingTextElements'];
private readonly getDefaultElements: MenuItemControllerConfig['getDefaultElements'];
private readonly getInteractiveElement: MenuItemControllerConfig['getInteractiveElement'];

/**
Expand All @@ -97,15 +109,18 @@ export class MenuItemController implements ReactiveController {
private readonly host: ReactiveControllerHost & MenuItem,
config: MenuItemControllerConfig,
) {
const {getHeadlineElements, getInteractiveElement} = config;
this.getHeadlineElements = getHeadlineElements;
this.getInteractiveElement = getInteractiveElement;
this.getHeadlineElements = config.getHeadlineElements;
this.getSupportingTextElements = config.getSupportingTextElements;
this.getDefaultElements = config.getDefaultElements;
this.getInteractiveElement = config.getInteractiveElement;
this.host.addController(this);
}

/**
* The text that is selectable via typeahead. If not set, defaults to the
* innerText of the item slotted into the `"headline"` slot.
* innerText of the item slotted into the `"headline"` slot, and if there are
* no slotted elements into headline, then it checks the _default_ slot, and
* then the `"supporting-text"` slot if nothing is in _default_.
*/
get typeaheadText() {
if (this.internalTypeaheadText !== null) {
Expand All @@ -121,6 +136,28 @@ export class MenuItemController implements ReactiveController {
}
});

// If there are no headline elements, check the default slot's text content
if (textParts.length === 0) {
this.getDefaultElements().forEach((defaultElement) => {
if (defaultElement.textContent && defaultElement.textContent.trim()) {
textParts.push(defaultElement.textContent.trim());
}
});
}

// If there are no headline nor default slot elements, check the
//supporting-text slot's text content
if (textParts.length === 0) {
this.getSupportingTextElements().forEach((supportingTextElement) => {
if (
supportingTextElement.textContent &&
supportingTextElement.textContent.trim()
) {
textParts.push(supportingTextElement.textContent.trim());
}
});
}

return textParts.join(' ');
}

Expand Down
17 changes: 16 additions & 1 deletion menu/internal/menuitem/menu-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ import '../../../labs/item/item.js';
import '../../../ripple/ripple.js';

import {html, LitElement, nothing, TemplateResult} from 'lit';
import {property, query, queryAssignedElements} from 'lit/decorators.js';
import {
property,
query,
queryAssignedElements,
queryAssignedNodes,
} from 'lit/decorators.js';
import {ClassInfo, classMap} from 'lit/directives/class-map.js';
import {literal, html as staticHtml, StaticValue} from 'lit/static-html.js';

Expand Down Expand Up @@ -71,6 +76,10 @@ export class MenuItemEl extends LitElement implements MenuItem {

@queryAssignedElements({slot: 'headline'})
protected readonly headlineElements!: HTMLElement[];
@queryAssignedElements({slot: 'supporting-text'})
protected readonly supportingTextElements!: HTMLElement[];
@queryAssignedNodes({slot: ''})
protected readonly defaultElements!: Node[];

/**
* The text that is selectable via typeahead. If not set, defaults to the
Expand All @@ -89,6 +98,12 @@ export class MenuItemEl extends LitElement implements MenuItem {
getHeadlineElements: () => {
return this.headlineElements;
},
getSupportingTextElements: () => {
return this.supportingTextElements;
},
getDefaultElements: () => {
return this.defaultElements;
},
getInteractiveElement: () => this.listItemRoot,
});

Expand Down
17 changes: 16 additions & 1 deletion select/internal/selectoption/select-option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ import '../../../labs/item/item.js';
import '../../../ripple/ripple.js';

import {html, LitElement, nothing} from 'lit';
import {property, query, queryAssignedElements} from 'lit/decorators.js';
import {
property,
query,
queryAssignedElements,
queryAssignedNodes,
} from 'lit/decorators.js';
import {ClassInfo, classMap} from 'lit/directives/class-map.js';

import {ARIAMixinStrict} from '../../../internal/aria/aria.js';
Expand Down Expand Up @@ -61,6 +66,10 @@ export class SelectOptionEl extends LitElement implements SelectOption {

@queryAssignedElements({slot: 'headline'})
protected readonly headlineElements!: HTMLElement[];
@queryAssignedElements({slot: 'supporting-text'})
protected readonly supportingTextElements!: HTMLElement[];
@queryAssignedNodes({slot: ''})
protected readonly defaultElements!: Element[];

type = 'option' as const;

Expand Down Expand Up @@ -94,6 +103,12 @@ export class SelectOptionEl extends LitElement implements SelectOption {
getHeadlineElements: () => {
return this.headlineElements;
},
getSupportingTextElements: () => {
return this.supportingTextElements;
},
getDefaultElements: () => {
return this.defaultElements;
},
getInteractiveElement: () => this.listItemRoot,
});

Expand Down
22 changes: 8 additions & 14 deletions select/internal/selectoption/selectOptionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ export type SelectOptionConfig = MenuItemControllerConfig;
*/
export class SelectOptionController implements ReactiveController {
private readonly menuItemController: MenuItemController;
private readonly getHeadlineElements: SelectOptionConfig['getHeadlineElements'];
private internalDisplayText: string | null = null;
private lastSelected = this.host.selected;
private firstUpdate = true;
Expand All @@ -85,7 +84,9 @@ export class SelectOptionController implements ReactiveController {

/**
* The text that is selectable via typeahead. If not set, defaults to the
* innerText of the item slotted into the `"headline"` slot.
* innerText of the item slotted into the `"headline"` slot, and if there are
* no slotted elements into headline, then it checks the _default_ slot, and
* then the `"supporting-text"` slot if nothing is in _default_.
*/
get typeaheadText() {
return this.menuItemController.typeaheadText;
Expand All @@ -97,23 +98,17 @@ export class SelectOptionController implements ReactiveController {

/**
* The text that is displayed in the select field when selected. If not set,
* defaults to the textContent of the item slotted into the `"headline"` slot.
* defaults to the textContent of the item slotted into the `"headline"` slot,
* and if there are no slotted elements into headline, then it checks the
* _default_ slot, and then the `"supporting-text"` slot if nothing is in
* _default_.
*/
get displayText() {
if (this.internalDisplayText !== null) {
return this.internalDisplayText;
}

const headlineElements = this.getHeadlineElements();

const textParts: string[] = [];
headlineElements.forEach((headlineElement) => {
if (headlineElement.textContent && headlineElement.textContent.trim()) {
textParts.push(headlineElement.textContent.trim());
}
});

return textParts.join(' ');
return this.menuItemController.typeaheadText;
}

setDisplayText(text: string) {
Expand All @@ -129,7 +124,6 @@ export class SelectOptionController implements ReactiveController {
config: SelectOptionConfig,
) {
this.menuItemController = new MenuItemController(host, config);
this.getHeadlineElements = config.getHeadlineElements;
host.addController(this);
}

Expand Down

0 comments on commit af49b64

Please sign in to comment.