Skip to content

Commit

Permalink
Implement <vaadin-message-list> (#9)
Browse files Browse the repository at this point in the history
Fixes #3
  • Loading branch information
Peppe authored Feb 8, 2021
1 parent bdbad38 commit 9039c5e
Show file tree
Hide file tree
Showing 19 changed files with 297 additions and 9 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
},
"dependencies": {
"@polymer/polymer": "^3.0.0",
"@vaadin/vaadin-avatar": "2.0.0-alpha1",
"@vaadin/vaadin-avatar": "^1.0.3",
"@vaadin/vaadin-element-mixin": "^2.4.1",
"@vaadin/vaadin-lumo-styles": "^1.6.1",
"@vaadin/vaadin-material-styles": "^1.3.2",
Expand Down
35 changes: 35 additions & 0 deletions src/vaadin-message-list.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';

import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js';

/**
* `<vaadin-message-list>` is a Web Component for showing an ordered list of messages. The messages are rendered as <vaadin-message>
*
* ```html
* <vaadin-message-list
* items='[{"text":"Hello list","time":"yesterday", "user": {"name":"Matt Mambo","abbr":"MM","colorIndex":"1"}},{"text":"Hello list","time":"right now", "user": {"name":"Linsey Listy","abbr":"LL","colorIndex":"2"}}]'>
* </vaadin-message-list>
* ```
*
* ### Styling
*
* The following shadow DOM parts are available for styling:
*
* Part name | Description
* ----------|----------------
*
* See [ThemableMixin – how to apply styles for shadow parts](https://github.com/vaadin/vaadin-themable-mixin/wiki)
*
* @extends HTMLElement
* @mixes ThemableMixin
* @mixes ElementMixin
*/
declare class MessageListElement extends ThemableMixin(ElementMixin(HTMLElement)) {}

declare global {
interface HTMLElementTagNameMap {
'vaadin-message-list': MessageListElement;
}
}

export { MessageListElement };
95 changes: 95 additions & 0 deletions src/vaadin-message-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* @license
* Copyright (c) 2021 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
*/
import { PolymerElement, html } from '@polymer/polymer/polymer-element.js';
import '@polymer/polymer/lib/elements/dom-repeat.js';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.js';
import './vaadin-message.js';
/**
* `<vaadin-message-list>` is a Web Component for showing an ordered list of messages. The messages are rendered as <vaadin-message>
*
* ```html
* <vaadin-message-list
* items='[{"text":"Hello list","time":"yesterday", "user": {"name":"Matt Mambo","abbr":"MM","colorIndex":"1"}},{"text":"Hello list","time":"right now", "user": {"name":"Linsey Listy","abbr":"LL","colorIndex":"2"}}]'>
* </vaadin-message-list>
* ```
*
* ### Styling
*
* The following shadow DOM parts are available for styling:
*
* Part name | Description
* ----------|----------------
*
* See [ThemableMixin – how to apply styles for shadow parts](https://github.com/vaadin/vaadin-themable-mixin/wiki)
*
* @extends HTMLElement
* @mixes ThemableMixin
* @mixes ElementMixin
*/
class MessageListElement extends ElementMixin(ThemableMixin(PolymerElement)) {
static get properties() {
return {
/**
* A user object that can be used to render avatar and name.
* The user object can consist of the folowing properties:
* ```js
* Array<{
* text: string,
* time: string,
* user: {
* name: string,
* abbr: string,
* img: string,
* colorIndex: number
* }
* }>
* ```
*/
items: {
type: Array,
value: function () {
return [];
}
}
};
}

static get template() {
return html`
<style>
:host {
display: block;
overflow: auto;
}
:host([hidden]) {
display: none !important;
}
</style>
<template is="dom-repeat" items="[[items]]">
<vaadin-message time="[[item.time]]" user="[[item.user]]">[[item.text]]</vaadin-message>
</template>
`;
}

ready() {
super.ready();
this.setAttribute('role', 'list');
}

static get is() {
return 'vaadin-message-list';
}

static get version() {
return '0.1.0';
}
}

customElements.define(MessageListElement.is, MessageListElement);

export { MessageListElement };
79 changes: 79 additions & 0 deletions test/message-list.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { expect } from '@esm-bundle/chai';
import { fixtureSync } from '@open-wc/testing-helpers';
import { afterNextRender } from '@polymer/polymer/lib/utils/render-status.js';
import '../vaadin-message-list.js';

function nextRender(target) {
return new Promise((resolve) => {
afterNextRender(target, () => {
resolve();
});
});
}

describe('message-list', () => {
let messageList, messages;

beforeEach(() => {
let root = document.documentElement;
root.style.setProperty('--vaadin-user-color-1', 'purple');
root.style.setProperty('--vaadin-user-color-2', 'blue');

messageList = fixtureSync('<vaadin-message-list></vaadin-message-list>');
messages = [
{
text: 'A message in the stream of messages',
time: '9:34 AM',
user: {
name: 'Joan Doe',
abbr: 'JD',
img: '/test/visual/avatars/avatar.jpg',
colorIndex: 1
}
},
{
text: 'Call upon the times of glory',
time: '2:34 PM',
user: {
name: 'Steve Mops',
abbr: 'SM',
colorIndex: 2
}
}
];
});

it('should have a valid version number', () => {
expect(messageList.constructor.version).to.match(/^(\d+\.)?(\d+\.)?(\d+)(-(alpha|beta)\d+)?$/);
});

it('message list should be initially empty', () => {
expect(messageList.items).to.be.empty;
});

describe('items property', () => {
beforeEach(async () => {
messageList.items = messages;
await nextRender(messageList);
});

it('message list should have two messages', () => {
const items = messageList.shadowRoot.querySelectorAll('vaadin-message');
expect(items.length).to.equal(2);
});

it('message properties should be correctly set', () => {
const firstMessage = messageList.shadowRoot.querySelectorAll('vaadin-message')[0];
expect(firstMessage.getAttribute('time')).to.be.equal(messages[0].time);
expect(firstMessage.user).to.be.equal(messages[0].user);
expect(firstMessage.textContent).to.be.equal(messages[0].text);
});

it('message list should scroll when height is less than content', () => {
messageList.style.height = '100px';
expect(messageList.scrollTop).to.be.equal(0);
messageList.scrollBy(0, 1000);
expect(messageList.scrollTop).to.be.at.least(1);
});
});
});
35 changes: 35 additions & 0 deletions test/visual/message-list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!DOCTYPE html>

<head lang="en">
<meta charset="UTF-8" />
<title>Message tests</title>
<script>
window.polymerSkipLoadingFontRoboto = true;
</script>
<style>
html {
--vaadin-user-color-1: blue;
--vaadin-user-color-2: green;
}
</style>
</head>

<body>
<div id="tests" style="padding: 10px">
<vaadin-message-list
items='[{"text":"Hello list","time":"yesterday", "user": {"name":"Matt Mambo","abbr":"MM","colorIndex":"1"}},{"text":"Another message","time":"right now", "user": {"name":"Linsey Listy","abbr":"LL","colorIndex":"2","img":"/test/visual/avatars/avatar.jpg"}}]'>
</vaadin-message-list>
</div>

<script type="module">
(async () => {
const theme = window.location.search.replace(/.*theme=(\w+).*/, '$1') || 'lumo';

await import('../../theme/' + theme + '/vaadin-message-list.js');

window.requestAnimationFrame(() => {
document.getElementById('tests').dataset.ready = true;
});
})();
</script>
</body>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/visual/screens/vaadin-message/material-message-ltr.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/visual/screens/vaadin-message/material-message-rtl.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 14 additions & 7 deletions test/visual/test.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
describe('vaadin-message', () => {
const locator = '#tests[data-ready]';

function assertView(testView, testFile) {
['lumo', 'material'].forEach((theme) => {
it(`${theme}-message`, function () {
it(`${theme}-${testView}`, function () {
const locator = '#tests[data-ready]';
return this.browser
.url(`default.html?theme=${theme}`)
.url(`${testFile}?theme=${theme}`)
.waitForVisible(locator, 15000)
.assertView(`${theme}-message-ltr`, locator)
.assertView(`${theme}-${testView}-ltr`, locator)
.execute(() => {
window.document.documentElement.setAttribute('dir', 'rtl');
})
.assertView(`${theme}-message-rtl`, locator);
.assertView(`${theme}-${testView}-rtl`, locator);
});
});
}

describe('vaadin-message', () => {
assertView('message', 'default.html');
});

describe('vaadin-message-list', () => {
assertView('message-list', 'message-list.html');
});
16 changes: 16 additions & 0 deletions theme/lumo/vaadin-message-list-styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
import '@vaadin/vaadin-lumo-styles/color.js';
import '@vaadin/vaadin-lumo-styles/sizing.js';
import '@vaadin/vaadin-lumo-styles/spacing.js';
import '@vaadin/vaadin-lumo-styles/style.js';
import './vaadin-message-styles.js';

registerStyles(
'vaadin-message-list',
css`
:host {
padding: var(--lumo-space-s);
}
`,
{ moduleId: 'lumo-message-list' }
);
2 changes: 2 additions & 0 deletions theme/lumo/vaadin-message-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import './vaadin-message-list-styles.js';
import '../../src/vaadin-message-list.js';
14 changes: 14 additions & 0 deletions theme/material/vaadin-message-list-styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
import '@vaadin/vaadin-material-styles/color.js';
import '@vaadin/vaadin-material-styles/typography.js';
import './vaadin-message-styles.js';

registerStyles(
'vaadin-message-list',
css`
:host {
padding: 8px;
}
`,
{ moduleId: 'material-message-list' }
);
2 changes: 2 additions & 0 deletions theme/material/vaadin-message-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import './vaadin-message-list-styles.js';
import '../../src/vaadin-message-list.js';
2 changes: 1 addition & 1 deletion theme/material/vaadin-message-styles.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { registerStyles, css } from '@vaadin/vaadin-themable-mixin/register-styles.js';
import '@vaadin/vaadin-material-styles/color.js';
import '@vaadin/vaadin-material-styles/typography.js';
import '@vaadin/vaadin-avatar/theme/lumo/vaadin-avatar.js';
import '@vaadin/vaadin-avatar/theme/material/vaadin-avatar-styles.js';

registerStyles(
'vaadin-message',
Expand Down
1 change: 1 addition & 0 deletions vaadin-message-list.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './src/vaadin-message-list.js';
2 changes: 2 additions & 0 deletions vaadin-message-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import './theme/lumo/vaadin-message-list.js';
export * from './src/vaadin-message-list.js';

0 comments on commit 9039c5e

Please sign in to comment.