Commit 51607ae9 authored by Kenton Lam's avatar Kenton Lam Committed by Chromium LUCI CQ

Add buttons for emoji groups with click handlers.

On click, the group is set as active (with blue colour) and
the emoji picker is scrolled to that group. Currently, the
active group binding is only one way (i.e. scrolling the
list of emoji manually will not change the active group button).

Bug: 1152237
Change-Id: I9e847c541ceb3b2f32b9649dce2cd8bed30e7994
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2596733Reviewed-by: default avatarJohn Palmer <jopalmer@chromium.org>
Reviewed-by: default avatarKeith Lee <keithlee@chromium.org>
Commit-Queue: Kenton Lam <kentonlam@google.com>
Cr-Commit-Position: refs/heads/master@{#842285}
parent 731821f4
......@@ -10,12 +10,10 @@ import("//ui/webui/resources/tools/generate_grd.gni")
component_js_files = [
"emoji_picker.js",
"emoji_group.js",
"emoji_group_button.js",
"icons.js",
]
polymer_deps =
[ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled" ]
resources_grd_file = "$target_gen_dir/resources.grd"
components_grdp_file = "$target_gen_dir/components.grdp"
data_grdp_file = "$target_gen_dir/data.grdp"
......@@ -69,21 +67,34 @@ grit("resources") {
js_library("emoji_picker") {
deps = [
":types",
":icons",
":emoji_group",
"//ui/webui/resources/js:load_time_data.m",
"//third_party/polymer/v3_0/components-chromium/iron-icon",
] + polymer_deps
":emoji_group_button",
":types",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/js:assert.m",
]
}
js_library("emoji_group") {
deps = [ ":types" ] + polymer_deps
deps = [
":types",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
]
}
js_library("emoji_group_button") {
deps = [
":icons",
"//third_party/polymer/v3_0/components-chromium/iron-icon",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
]
}
js_library("icons") {
deps = [ "//third_party/polymer/v3_0/components-chromium/iron-iconset-svg" ] +
polymer_deps
deps = [
"//third_party/polymer/v3_0/components-chromium/iron-iconset-svg",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
]
}
js_library("types") {
......@@ -93,6 +104,7 @@ js_type_check("closure_compile") {
is_polymer3 = true
deps = [
":emoji_group",
":emoji_group_button",
":emoji_picker",
":icons",
":types",
......
<style>
button {
background-color: transparent;
border: 5px solid transparent;
padding: 0;
width: 36px;
}
button:hover {
color: red;
}
.active {
border-bottom: 5px solid blue;
color: blue;
}
</style>
<button class$="[[_className(active)]]" on-click="handleClick">
<iron-icon icon="[[icon]]"></iron-icon>
</button>
\ No newline at end of file
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import './icons.js';
import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {GROUP_BUTTON_EVENT, GroupButtonEvent} from './types.js';
class EmojiGroupButton extends PolymerElement {
static get is() {
return 'emoji-group-button';
}
static get template() {
return html`{__html_template__}`;
}
static get properties() {
return {
/** @type {string} */
icon: {type: String},
group: {type: String},
active: {type: Boolean, value: false},
};
}
constructor() {
super();
}
handleClick(ev) {
/** @type {GroupButtonEvent} */
const event = new CustomEvent(
GROUP_BUTTON_EVENT,
{bubbles: true, composed: true, detail: {group: this.group}});
this.dispatchEvent(event);
}
_className(active) {
return active ? 'active' : '';
}
}
customElements.define(EmojiGroupButton.is, EmojiGroupButton);
......@@ -8,6 +8,17 @@
min-height: 343px;
width: calc(36px * 7);
}
.emoji-tabs {
display: flex;
overflow-x: scroll;
width: 100%;
}
.emoji-groups {
max-height: 400px;
overflow-y: scroll;
}
</style>
<div class="emoji-picker">
......@@ -18,21 +29,24 @@
></input>
<div class="emoji-tabs">
<iron-icon icon="emoji_picker:schedule"></iron-icon>
<iron-icon icon="emoji_picker:insert_emoticon"></iron-icon>
<iron-icon icon="emoji_picker:emoji_people"></iron-icon>
<iron-icon icon="emoji_picker:emoji_nature"></iron-icon>
<iron-icon icon="emoji_picker:emoji_food_beverage"></iron-icon>
<iron-icon icon="emoji_picker:emoji_transportation"></iron-icon>
<iron-icon icon="emoji_picker:emoji_events"></iron-icon>
<iron-icon icon="emoji_picker:emoji_objects"></iron-icon>
<iron-icon icon="emoji_picker:emoji_symbols"></iron-icon>
<iron-icon icon="emoji_picker:flag"></iron-icon>
<template is="dom-repeat" items="[[groups]]">
<emoji-group-button group="[[item.group]]" active="[[item.active]]"
icon="[[item.icon]]"></emoji-group-button>
</template>
</div>
<div class="emoji-groups w-100">
<template is="dom-repeat" items="{{emojiData}}">
<!--
group-history is the "frequently used" group and is populated in code,
whereas the other groups are created from the emoji metadata.
-->
<div id="group-history">
<emoji-group data="[[history]]"></emoji-group>
</div>
<template is="dom-repeat" items="[[emojiData]]">
<div id="group-[[index]]">
<emoji-group data="[[item]]"></emoji-group>
</div>
</template>
</div>
</div>
\ No newline at end of file
......@@ -2,18 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import './strings.m.js';
import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
import './icons.js';
import './emoji_group.js';
import './emoji_group_button.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {assert} from 'chrome://resources/js/assert.m.js';
import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {EmojiData} from './types.js';
import {EmojiData, EmojiGroup, GROUP_BUTTON_EVENT} from './types.js';
const EMOJI_ORDERING_JSON = '/emoji_13_1_ordering.json';
const GROUP_TABS = [
{icon: 'emoji_picker:schedule', group: 'history', active: true},
{icon: 'emoji_picker:insert_emoticon', group: '0', active: false},
{icon: 'emoji_picker:emoji_people', group: '1', active: false},
{icon: 'emoji_picker:emoji_nature', group: '2', active: false},
{icon: 'emoji_picker:emoji_food_beverage', group: '3', active: false},
{icon: 'emoji_picker:emoji_transportation', group: '4', active: false},
{icon: 'emoji_picker:emoji_events', group: '5', active: false},
{icon: 'emoji_picker:emoji_objects', group: '6', active: false},
{icon: 'emoji_picker:emoji_symbols', group: '7', active: false},
{icon: 'emoji_picker:flag', group: '8', active: false},
];
class EmojiPicker extends PolymerElement {
static get is() {
return 'emoji-picker';
......@@ -25,9 +37,11 @@ class EmojiPicker extends PolymerElement {
static get properties() {
return {
emoji: {type: Array},
groups: {type: Array},
/** @type {?EmojiData} */
emojiData: {type: Object},
/** @type {EmojiGroup} */
history: {type: Object},
search: {type: String},
};
}
......@@ -35,13 +49,55 @@ class EmojiPicker extends PolymerElement {
constructor() {
super();
this.groups = GROUP_TABS;
this.emojiData = [];
// TODO(https://crbug.com/1164828): replace placeholder frequently used
// data.
this.history = {
'group': 'Frequently used',
'emoji': [
{
'base': [128512],
'alternates': [],
},
{
'base': [128513],
'alternates': [],
},
],
};
this.search = '';
}
ready() {
super.ready();
const xhr = new XMLHttpRequest();
xhr.onloadend = () => this.onEmojiDataLoaded(xhr.responseText);
xhr.open('GET', EMOJI_ORDERING_JSON);
xhr.send();
this.emojiData = [];
this.search = '';
this.addEventListener(
GROUP_BUTTON_EVENT, ev => this.selectGroup(ev.detail.group));
}
/**
* @param {string} newGroup
*/
selectGroup(newGroup) {
let activeGroup = null;
// set active to true for selected group and false for others.
this.groups.forEach((g, i) => {
const isActive = g.group === newGroup;
this.set(['groups', i, 'active'], isActive);
if (isActive) {
activeGroup = g;
}
});
assert(activeGroup, 'no group button was activated');
// scroll to selected group's element.
this.shadowRoot.getElementById(`group-${activeGroup.group}`)
.scrollIntoView();
}
_formatEmojiData(emojiData) {
......
......@@ -16,3 +16,10 @@ export let EmojiGroup;
* @typedef {Array<EmojiGroup>} EmojiData
*/
export let EmojiData;
/**
* @typedef {!CustomEvent<{group: string}>} GroupButtonEvent
*/
export let GroupButtonEvent;
export const GROUP_BUTTON_EVENT = 'group-button';
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment