Skip to content

Commit

Permalink
Merge pull request #3589 from material-components/refactor-select-menu
Browse files Browse the repository at this point in the history
  • Loading branch information
e111077 committed Aug 12, 2022
2 parents 1f5fc52 + 88b308c commit 3c0faec
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 65 deletions.
73 changes: 49 additions & 24 deletions packages/menu/mwc-menu-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@ import {DefaultFocusState as DefaultFocusStateEnum} from '@material/menu/constan
import MDCMenuFoundation from '@material/menu/foundation.js';
import {BaseElement} from '@material/mwc-base/base-element.js';
import {observer} from '@material/mwc-base/observer.js';
import {List, MWCListIndex} from '@material/mwc-list/mwc-list.js';
import {ActionDetail} from '@material/mwc-list/mwc-list-foundation.js';
import {ListItemBase} from '@material/mwc-list/mwc-list-item-base.js';
import {List, MWCListIndex} from '@material/mwc-list/mwc-list.js';
import {html} from 'lit';
import {property, query} from 'lit/decorators.js';
import {classMap} from 'lit/directives/class-map.js';

import {MenuSurface} from './mwc-menu-surface.js';
import {Corner, MenuCorner} from './mwc-menu-surface-base.js';
import {MenuSurface} from './mwc-menu-surface.js';

export {ActionDetail, createSetFromIndex, isEventMulti, isIndexSet, MWCListIndex, SelectedDetail} from '@material/mwc-list/mwc-list-foundation.js';
export {Corner, MenuCorner} from './mwc-menu-surface-base.js';
Expand Down Expand Up @@ -131,39 +132,63 @@ export abstract class MenuBase extends BaseElement {
}

override render() {
const itemRoles = this.innerRole === 'menu' ? 'menuitem' : 'option';
return this.renderSurface();
}

protected renderSurface() {
const classes = this.getSurfaceClasses();
return html`
<mwc-menu-surface
?hidden=${!this.open}
.anchor=${this.anchor}
.open=${this.open}
.quick=${this.quick}
.corner=${this.corner}
.x=${this.x}
.y=${this.y}
.absolute=${this.absolute}
.fixed=${this.fixed}
.fullwidth=${this.fullwidth}
.menuCorner=${this.menuCorner}
?stayOpenOnBodyClick=${this.stayOpenOnBodyClick}
class="mdc-menu mdc-menu-surface"
@closed=${this.onClosed}
@opened=${this.onOpened}
@keydown=${this.onKeydown}>
<mwc-list
?hidden=${!this.open}
.anchor=${this.anchor}
.open=${this.open}
.quick=${this.quick}
.corner=${this.corner}
.x=${this.x}
.y=${this.y}
.absolute=${this.absolute}
.fixed=${this.fixed}
.fullwidth=${this.fullwidth}
.menuCorner=${this.menuCorner}
?stayOpenOnBodyClick=${this.stayOpenOnBodyClick}
class=${classMap(classes)}
@closed=${this.onClosed}
@opened=${this.onOpened}
@keydown=${this.onKeydown}>
${this.renderList()}
</mwc-menu-surface>`;
}

protected getSurfaceClasses() {
return {
'mdc-menu': true,
'mdc-menu-surface': true,
};
}

protected renderList() {
const itemRoles = this.innerRole === 'menu' ? 'menuitem' : 'option';
const classes = this.renderListClasses();

return html`
<mwc-list
rootTabbable
.innerAriaLabel=${this.innerAriaLabel}
.innerRole=${this.innerRole}
.multi=${this.multi}
class="mdc-deprecated-list"
class=${classMap(classes)}
.itemRoles=${itemRoles}
.wrapFocus=${this.wrapFocus}
.activatable=${this.activatable}
@action=${this.onAction}>
<slot></slot>
</mwc-list>
</mwc-menu-surface>`;
</mwc-list>`;
}

protected renderListClasses() {
return {
'mdc-deprecated-list': true,
};
}

protected createAdapter(): MDCMenuAdapter {
Expand Down Expand Up @@ -263,7 +288,7 @@ export abstract class MenuBase extends BaseElement {

return -1;
},
notifySelected: () => { /** handled by list */ },
notifySelected: () => {/** handled by list */},
getMenuItemCount: () => {
const listElement = this.listElement;
if (!listElement) {
Expand Down
57 changes: 38 additions & 19 deletions packages/menu/mwc-menu-surface-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,7 @@ export abstract class MenuSurfaceBase extends BaseElement {

@property({type: Boolean, reflect: true})
@observer(function(this: MenuSurfaceBase, isOpen: boolean, wasOpen: boolean) {
if (this.mdcFoundation) {
if (isOpen) {
this.mdcFoundation.open();
// wasOpen helps with first render (when it is `undefined`) perf
} else if (wasOpen !== undefined) {
this.mdcFoundation.close();
}
}
this.onOpenChanged(isOpen, wasOpen);
})
open = false;

Expand Down Expand Up @@ -173,29 +166,44 @@ export abstract class MenuSurfaceBase extends BaseElement {
protected onBodyClickBound: (evt: MouseEvent) => void = () => undefined;

override render() {
const classes = {
return this.renderSurface();
}

protected renderSurface() {
const classes = this.getRootClasses();
const styles = this.getRootStyles();
return html`
<div
class=${classMap(classes)}
style="${styleMap(styles)}"
@keydown=${this.onKeydown}
@opened=${this.registerBodyClick}
@closed=${this.deregisterBodyClick}>
${this.renderContent()}
</div>`;
}

protected getRootClasses() {
return {
'mdc-menu-surface': true,
'mdc-menu-surface--fixed': this.fixed,
'mdc-menu-surface--fullwidth': this.fullwidth,
};
}

const styles = {
protected getRootStyles() {
return {
'top': this.styleTop,
'left': this.styleLeft,
'right': this.styleRight,
'bottom': this.styleBottom,
'max-height': this.styleMaxHeight,
'transform-origin': this.styleTransformOrigin,
};
}

return html`
<div
class="mdc-menu-surface ${classMap(classes)}"
style="${styleMap(styles)}"
@keydown=${this.onKeydown}
@opened=${this.registerBodyClick}
@closed=${this.deregisterBodyClick}>
<slot></slot>
</div>`;
protected renderContent() {
return html`<slot></slot>`;
}

createAdapter(): MDCMenuSurfaceAdapter {
Expand Down Expand Up @@ -351,6 +359,17 @@ export abstract class MenuSurfaceBase extends BaseElement {
'click', this.onBodyClickBound, {capture: true});
}

protected onOpenChanged(isOpen: boolean, wasOpen: boolean) {
if (this.mdcFoundation) {
if (isOpen) {
this.mdcFoundation.open();
// wasOpen helps with first render (when it is `undefined`) perf
} else if (wasOpen !== undefined) {
this.mdcFoundation.close();
}
}
}

close() {
this.open = false;
}
Expand Down
57 changes: 35 additions & 22 deletions packages/select/mwc-select-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,6 @@ export abstract class SelectBase extends FormElement {
'mdc-select--invalid': !this.isUiValid,
};

const menuClasses = {
'mdc-select__menu--invalid': !this.isUiValid,
};

const labelledby = !!this.label ? 'label' : undefined;
const describedby = this.shouldRenderHelperText ? 'helper-text' : undefined;

Expand Down Expand Up @@ -311,28 +307,45 @@ export abstract class SelectBase extends FormElement {
</span>
${this.renderLineRipple()}
</div>
<mwc-menu
innerRole="listbox"
wrapFocus
class="mdc-select__menu mdc-menu mdc-menu-surface ${
classMap(menuClasses)}"
activatable
.fullwidth=${
this.fixedMenuPosition ? false : !this.naturalMenuWidth}
.open=${this.menuOpen}
.anchor=${this.anchorElement}
.fixed=${this.fixedMenuPosition}
@selected=${this.onSelected}
@opened=${this.onOpened}
@closed=${this.onClosed}
@items-updated=${this.onItemsUpdated}
@keydown=${this.handleTypeahead}>
<slot></slot>
</mwc-menu>
${this.renderMenu()}
</div>
${this.renderHelperText()}`;
}

protected renderMenu() {
const classes = this.getMenuClasses();
return html`
<mwc-menu
innerRole="listbox"
wrapFocus
class=" ${classMap(classes)}"
activatable
.fullwidth=${this.fixedMenuPosition ? false : !this.naturalMenuWidth}
.open=${this.menuOpen}
.anchor=${this.anchorElement}
.fixed=${this.fixedMenuPosition}
@selected=${this.onSelected}
@opened=${this.onOpened}
@closed=${this.onClosed}
@items-updated=${this.onItemsUpdated}
@keydown=${this.handleTypeahead}>
${this.renderMenuContent()}
</mwc-menu>`;
}

protected getMenuClasses() {
return {
'mdc-select__menu': true,
'mdc-menu': true,
'mdc-menu-surface': true,
'mdc-select__menu--invalid': !this.isUiValid,
};
}

protected renderMenuContent() {
return html`<slot></slot>`;
}

protected renderRipple() {
if (this.outlined) {
return nothing;
Expand Down

0 comments on commit 3c0faec

Please sign in to comment.