Skip to content

Commit

Permalink
feat(list): Add ripple to M3 list
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 463358686
  • Loading branch information
material-web-copybara authored and copybara-github committed Jul 26, 2022
1 parent 1d3701a commit 4d292f4
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 10 deletions.
15 changes: 15 additions & 0 deletions list/lib/listitem/_list-item.scss
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@
.md3-list-item--with-leading-video {
@include video-item-root;
}

.md3-list-item__ripple {
display: inline-flex;
inset: 0;
position: absolute;
z-index: 0;
}
}

@mixin host-root() {
Expand All @@ -39,21 +46,29 @@
padding-block-end: 12px;
padding-block-start: 12px;
width: 100%;
position: relative;

&.md3-list-item--enabled {
cursor: pointer;
}

.md3-list-item__start {
flex: 0 0 auto;
z-index: 1;
}

.md3-list-item__body {
box-sizing: border-box;
flex: 1 0 0;
padding-inline-start: 16px;
width: 100%;
z-index: 1;
}

.md3-list-item__end {
flex: 0 0 auto;
padding-inline-end: 24px;
z-index: 1;
}

.md3-list-item__label-text {
Expand Down
69 changes: 64 additions & 5 deletions list/lib/listitem/list-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@
* SPDX-License-Identifier: Apache-2.0
*/

import '@material/web/ripple/ripple';

import {ActionElement, BeginPressConfig, EndPressConfig} from '@material/web/actionelement/action-element';
import {MdRipple} from '@material/web/ripple/ripple';
import {ARIARole} from '@material/web/types/aria';
import {html, LitElement, TemplateResult} from 'lit';
import {property} from 'lit/decorators';
import {html, TemplateResult} from 'lit';
import {property, query} from 'lit/decorators';
import {ClassInfo, classMap} from 'lit/directives/class-map';

/** @soyCompatible */
export class ListItem extends LitElement {
export class ListItem extends ActionElement {
@property({type: String}) supportingText = '';
@property({type: String}) multiLineSupportingText = '';
@property({type: String}) trailingSupportingText = '';
@property({type: Boolean}) disabled = false;
@query('md-ripple') ripple!: MdRipple;

/** @soyTemplate */
override render(): TemplateResult {
Expand All @@ -23,13 +28,30 @@ export class ListItem extends LitElement {
tabindex="0"
role=${this.getAriaRole()}
class="md3-list-item ${classMap(this.getRenderClasses())}"
@click=${this.handleClick}>
@pointerdown=${this.handlePointerDown}
@pointerenter=${this.handlePointerEnter}
@pointerup=${this.handlePointerUp}
@pointercancel=${this.handlePointerCancel}
@pointerleave=${this.handlePointerLeave}
@keydown=${this.handleKeyDown}
@keyup=${this.handleKeyUp}
@click=${this.handleClick}
@contextmenu=${this.handleContextMenu}
>
${this.renderStart()}
${this.renderBody()}
${this.renderEnd()}
<div class="md3-list-item__ripple">
${this.renderRipple()}
</div>
</li>`;
}

/** @soyTemplate */
protected renderRipple(): TemplateResult {
return html`<md-ripple ?disabled="${this.disabled}"></md-ripple>`;
}

/** @soyTemplate */
protected getAriaRole(): ARIARole {
return 'listitem';
Expand All @@ -44,6 +66,7 @@ export class ListItem extends LitElement {
this.supportingText !== '' && this.multiLineSupportingText === '',
'md3-list-item--with-three-line': this.multiLineSupportingText !== '',
'md3-list-item--disabled': this.disabled,
'md3-list-item--enabled': !this.disabled,
};
}

Expand Down Expand Up @@ -105,5 +128,41 @@ export class ListItem extends LitElement {
this.requestUpdate();
}

handleClick() {}
override beginPress({positionEvent}: BeginPressConfig) {
this.ripple.beginPress(positionEvent);
}

override endPress({cancelled}: EndPressConfig) {
this.ripple.endPress();

if (cancelled) return;

super.endPress({cancelled, actionData: {item: this}});
}

protected handlePointerEnter(e: PointerEvent) {
this.ripple.beginHover(e);
}

override handlePointerLeave(e: PointerEvent) {
super.handlePointerLeave(e);

this.ripple.endHover();
}

protected handleKeyDown(e: KeyboardEvent) {
if (e.key !== ' ' && e.key !== 'Enter') return;

e.preventDefault();
// TODO(b/240124486): Replace with beginPress provided by action element.
this.ripple.beginPress(e);
}

protected handleKeyUp(e: KeyboardEvent) {
if (e.key !== ' ' && e.key !== 'Enter') return;

e.preventDefault();
// TODO(b/240124486): Replace with beginPress provided by action element.
this.ripple.endPress();
}
}
3 changes: 2 additions & 1 deletion list/lib/listitem/option-list-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ export class OptionListItem extends ListItem {
return 'option';
}

override handleClick() {
override handleClick(e: MouseEvent) {
this.dispatchEvent(new CustomEvent(
'list-item-interaction',
{detail: {state: {isSelected: false}}, bubbles: true, composed: true}));
super.handleClick(e);
}
}
8 changes: 4 additions & 4 deletions ripple/lib/ripple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ export class Ripple extends LitElement {
this.rippleSize = `${this.initialSize}px`;
}

protected getNormalizedEventCoords(positionEvent: Event):
protected getNormalizedPointerEventCoords(pointerEvent: PointerEvent):
{x: number, y: number} {
const {scrollX, scrollY} = window;
const {left, top} = this.getDimensions();
const documentX = scrollX + left;
const documentY = scrollY + top;
const {pageX, pageY} = (positionEvent as PointerEvent);
const {pageX, pageY} = pointerEvent;
return {x: pageX - documentX, y: pageY - documentY};
}

Expand All @@ -107,8 +107,8 @@ export class Ripple extends LitElement {
};

let startPoint;
if (positionEvent) {
startPoint = this.getNormalizedEventCoords(positionEvent);
if (positionEvent instanceof PointerEvent) {
startPoint = this.getNormalizedPointerEventCoords(positionEvent);
} else {
startPoint = {
x: width / 2,
Expand Down

0 comments on commit 4d292f4

Please sign in to comment.