Skip to content

Commit

Permalink
Implement <vaadin-message> (#6)
Browse files Browse the repository at this point in the history
Fixes #2
  • Loading branch information
Peppe authored Feb 3, 2021
1 parent 8580b55 commit e7bbd06
Show file tree
Hide file tree
Showing 14 changed files with 189 additions and 67 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@
},
"dependencies": {
"@polymer/polymer": "^3.0.0",
"@vaadin/vaadin-themable-mixin": "^1.6.1",
"@vaadin/vaadin-avatar": "2.0.0-alpha1",
"@vaadin/vaadin-element-mixin": "^2.4.1",
"@vaadin/vaadin-lumo-styles": "^1.6.1",
"@vaadin/vaadin-material-styles": "^1.3.2",
"@vaadin/vaadin-element-mixin": "^2.4.1"
"@vaadin/vaadin-themable-mixin": "^1.6.1"
},
"devDependencies": {
"@esm-bundle/chai": "^4.1.5",
Expand Down
Binary file modified screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 6 additions & 14 deletions src/vaadin-message.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.
* `<vaadin-message>` is a Web Component for showing a single message with an author, message and time.
*
* ```html
* <vaadin-message foo="bar">
* </vaadin-message>
* <vaadin-message time="2021-01-28 10:43"
* user='{"name":"Bob Ross","abbr":"BR","img":"/static/img/avatar.jpg"}'>There is no real ending. It's
* just the place where you stop the story.</vaadin-message>
* ```
*
* ### Styling
Expand All @@ -17,21 +18,12 @@ import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.
* Part name | Description
* ----------|----------------
* `avatar` | The author's avatar
* `name` | Author's name
* `time` | When the message was posted
* `content` | The message itself as a slotted content
*
* See [ThemableMixin – how to apply styles for shadow parts](https://github.com/vaadin/vaadin-themable-mixin/wiki)
*
* The following custom properties are available:
*
* Custom property | Description | Default
*---------------------------|------------------------------------------|-------------
* `--vaadin-message-value` | value of the component (between 0 and 1) | 0
*
* The following state attributes are available for styling:
*
* Attribute | Description | Part name
* ----------------|------------------|------------
* `myattribute` | Set an attribute | :host
*
* @extends HTMLElement
* @mixes ThemableMixin
* @mixes ElementMixin
Expand Down
84 changes: 55 additions & 29 deletions src/vaadin-message.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
import { PolymerElement, html } from '@polymer/polymer/polymer-element.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/vaadin-avatar/src/vaadin-avatar.js';
/**
* `<vaadin-message>` is a Web Component for showing a single message with an author, message and time.
*
* ```html
* <vaadin-message foo="bar">
* </vaadin-message>
* <vaadin-message time="2021-01-28 10:43"
* user='{"name":"Bob Ross","abbr":"BR","img":"/static/img/avatar.jpg"}'>There is no real ending. It's
* just the place where you stop the story.</vaadin-message>
* ```
*
* ### Styling
Expand All @@ -22,21 +23,12 @@ import { ElementMixin } from '@vaadin/vaadin-element-mixin/vaadin-element-mixin.
* Part name | Description
* ----------|----------------
* `avatar` | The author's avatar
* `name` | Author's name
* `time` | When the message was posted
* `content` | The message itself as a slotted content
*
* See [ThemableMixin – how to apply styles for shadow parts](https://github.com/vaadin/vaadin-themable-mixin/wiki)
*
* The following custom properties are available:
*
* Custom property | Description | Default
*---------------------------|------------------------------------------|-------------
* `--vaadin-message-value` | value of the component (between 0 and 1) | 0
*
* The following state attributes are available for styling:
*
* Attribute | Description | Part name
* ----------------|------------------|------------
* `myattribute` | Set an attribute | :host
*
* @extends HTMLElement
* @mixes ThemableMixin
* @mixes ElementMixin
Expand All @@ -45,11 +37,27 @@ class MessageElement extends ElementMixin(ThemableMixin(PolymerElement)) {
static get properties() {
return {
/**
* Current text value.
* Time of sending the message. It is rendered as-is to the part='time' slot,
* so the formatting is up to you.
*/
value: {
time: {
type: String,
reflectToAttribute: true
},
/**
* A user object that can be used to render avatar and name.
* The user object can consist of the following properties:
* ```js
* user: {
* name: string,
* abbr: string,
* img: string,
* colorIndex: number
* }
* ```
*/
user: {
type: Object
}
};
}
Expand All @@ -58,34 +66,52 @@ class MessageElement extends ElementMixin(ThemableMixin(PolymerElement)) {
return html`
<style>
:host {
display: block;
width: 100%; /* prevent collapsing inside non-stretching column flex */
height: 8px;
display: flex;
flex-direction: row;
}
:host([hidden]) {
display: none !important;
}
[part='value'] {
height: 100%;
.vaadin-message-wrapper {
display: flex;
flex-direction: column;
flex: 1;
}
/* RTL specific styles */
:host([dir='rtl']) [part='value'] {
transform-origin: 100% 50%;
.vaadin-message-header {
display: flex;
flex-direction: row;
}
</style>
<div part="bar">
<div part="value">[[value]]</div>
[part='name'] {
flex: 1;
}
</style>
<vaadin-avatar
part="avatar"
name="[[user.name]]"
img="[[user.img]]"
abbr="[[user.abbr]]"
color-index="[[user.colorIndex]]"
tabindex="-1"
aria-hidden="true"
></vaadin-avatar>
<div class="vaadin-message-wrapper">
<div class="vaadin-message-header">
<div part="name">[[user.name]]</div>
<div part="time">[[time]]</div>
</div>
<div part="content">
<slot></slot>
</div>
</div>
`;
}

ready() {
super.ready();
this.setAttribute('value', 'hello world');
}

static get is() {
Expand Down
61 changes: 53 additions & 8 deletions test/message.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,68 @@ import { fixtureSync } from '@open-wc/testing-helpers';
import '../vaadin-message.js';

describe('message', () => {
let message, value;
let message, avatar, content, time, name, user;

beforeEach(() => {
message = fixtureSync('<vaadin-message></vaadin-message>');
value = message.shadowRoot.querySelector('[part="value"]');
let root = document.documentElement;
root.style.setProperty('--vaadin-user-color-2', 'blue');

message = fixtureSync('<vaadin-message>Hello</vaadin-message>');
avatar = message.shadowRoot.querySelector('vaadin-avatar');
name = message.shadowRoot.querySelector('[part="name"]');
content = message.shadowRoot.querySelector('[part="content"]');
time = message.shadowRoot.querySelector('[part="time"]');
user = {
name: 'Joan Doe',
abbr: 'JD',
img: '/test/visual/avatars/avatar.jpg',
colorIndex: 2
};
});

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

it('should say initially hello world', () => {
expect(value.textContent).to.be.equal('hello world');
it('avatar should be initially visible but without data', () => {
expect(avatar.getAttribute('name')).to.be.null;
expect(avatar.getAttribute('abbr')).to.be.null;
expect(avatar.getAttribute('img')).to.be.null;
expect(avatar.getAttribute('title')).to.be.equal('anonymous');
expect(avatar.getAttribute('has-color-index')).to.be.null;
});

it('name should be initially empty', () => {
expect(name.textContent.trim()).to.be.equal('');
});

it('time should be initially empty', () => {
expect(time.textContent.trim()).to.be.equal('');
});

it('avatar should be set with provided user', () => {
message.user = user;
expect(avatar.getAttribute('name')).to.be.equal('Joan Doe');
expect(avatar.getAttribute('abbr')).to.be.equal('JD');
expect(avatar.getAttribute('img')).to.be.equal('/test/visual/avatars/avatar.jpg');
expect(avatar.getAttribute('title')).to.be.equal('Joan Doe (JD)');
expect(avatar.getAttribute('has-color-index')).to.be.not.null;
expect(avatar.colorIndex).to.be.equal(2);
});

it('name should be set with provided user', () => {
message.user = user;
expect(name.textContent).to.be.equal('Joan Doe');
});

it('time should be set', () => {
message.time = 'long ago';
expect(time.textContent).to.be.equal('long ago');
});

it('should say hello tests', () => {
message.value = 'hello tests';
expect(value.textContent).to.be.equal('hello tests');
it('content should be set', () => {
const slot = content.querySelector('slot');
const nodes = slot.assignedNodes({ flatten: true });
expect(nodes[0].textContent).to.be.equal('Hello');
});
});
Binary file added test/visual/avatars/avatar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/visual/avatars/avatar2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 19 additions & 1 deletion test/visual/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,29 @@
<script>
window.polymerSkipLoadingFontRoboto = true;
</script>
<style>
html {
--vaadin-user-color-3: red;
}
</style>
</head>

<body>
<div id="tests" style="padding: 10px">
<vaadin-message value="Hello there"></vaadin-message>
<vaadin-message time="2021-01-28 10:43"
user='{"name":"Bob Ross","abbr":"BR","img":"/test/visual/avatars/avatar.jpg"}'>There is no real
ending. It's
just the place where you stop the story.</vaadin-message>
<vaadin-message time="Three years ago"
user='{"name":"Tony Robbins","abbr":"TR","img":"/test/visual/avatars/avatar2.jpg"}'>People who succeed
have
momentum. The more they succeed, the more they want to succeed and the more they find a way to succeed. Similarly,
when someone is failing, the tendency is to get on a downward spiral that can even become a self-fulfilling
prophecy.</vaadin-message>
<vaadin-message></vaadin-message>
<vaadin-message time="2021-01-28 10:43"
user='{"name":"Dean Winchester","abbr":"DW","colorIndex":"3"}'>There is no real ending. It's
just the place where you stop the story.</vaadin-message>
</div>

<script type="module">
Expand Down
Binary file modified test/visual/screens/vaadin-message/lumo-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/lumo-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.
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.
33 changes: 27 additions & 6 deletions theme/lumo/vaadin-message-styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,40 @@ 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/vaadin-avatar/theme/lumo/vaadin-avatar.js';

registerStyles(
'vaadin-message',
css`
:host {
height: calc(var(--lumo-size-l) / 10);
margin: var(--lumo-space-s) 0;
padding: var(--lumo-space-s);
}
[part='value'] {
border-radius: var(--lumo-border-radius);
background-color: var(--lumo-primary-color);
color: white;
:host {
font-family: var(--lumo-font-family);
font-size: var(--lumo-font-size-m);
}
.vaadin-message-wrapper {
padding-left: var(--lumo-space-s);
padding-right: 0;
}
:host([dir='rtl']) .vaadin-message-wrapper {
padding-left: 0;
padding-right: var(--lumo-space-s);
}
.vaadin-message-header {
padding-bottom: var(--lumo-space-s);
}
[part='name'] {
font-weight: 500;
}
[part='time'] {
color: var(--lumo-secondary-text-color);
}
`,
{ moduleId: 'lumo-message' }
Expand Down
33 changes: 26 additions & 7 deletions theme/material/vaadin-message-styles.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
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';

registerStyles(
'vaadin-message',
css`
:host {
margin: 8px 0;
height: 32px;
padding: 8px;
}
[part='value'] {
color: black;
:host {
font-family: var(--material-font-family);
font-size: var(--material-small-font-size);
}
.vaadin-message-wrapper {
padding-left: 8px;
padding-right: 0;
}
:host([dir='rtl']) .vaadin-message-wrapper {
padding-left: 0;
padding-right: 8px;
}
.vaadin-message-header {
padding-bottom: 8px;
}
[part='name'] {
font-weight: 500;
}
/* RTL specific styles */
:host([dir='rtl']) [part='value'] {
transform-origin: 100% 0;
[part='time'] {
color: var(--material-secondary-text-color);
}
`,
{ moduleId: 'material-message' }
Expand Down

0 comments on commit e7bbd06

Please sign in to comment.