blob: e3005889a5a13f2dc9ac8cb49cfcecab9a685ec1 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import {LitElement, html, css} from 'lit-element';
6import 'elements/chops/chops-button/chops-button.js';
7
8/**
9 * @typedef {Object} ChoiceOption
10 * @property {string=} value a unique string identifier for this option.
11 * @property {string=} text the text displayed to the user for this option.
12 * @property {string=} url the url this option navigates to.
13 */
14
15/**
16 * Shared component for rendering a set of choice chips.
17 * @extends {LitElement}
18 */
19export class ChopsChoiceButtons extends LitElement {
20 /** @override */
21 render() {
22 return html`
23 ${(this.options).map((option) => this._renderOption(option))}
24 `;
25 }
26
27 /**
28 * Rendering helper for rendering a single option.
29 * @param {ChoiceOption} option
30 * @return {TemplateResult}
31 */
32 _renderOption(option) {
33 const isSelected = this.value === option.value;
34 if (option.url) {
35 return html`
36 <a
37 ?selected=${isSelected}
38 aria-current=${isSelected ? 'true' : 'false'}
39 href=${option.url}
40 >${option.text}</a>
41 `;
42 }
43 return html`
44 <button
45 ?selected=${isSelected}
46 aria-current=${isSelected ? 'true' : 'false'}
47 @click=${this._setValue}
48 value=${option.value}
49 >${option.text}</button>
50 `;
51 }
52
53 /** @override */
54 static get properties() {
55 return {
56 /**
57 * Array of options where each option is an Object with keys:
58 * {value, text, url}
59 */
60 options: {type: Array},
61 /**
62 * Which button is currently selected.
63 */
64 value: {type: String},
65 };
66 };
67
68 /** @override */
69 constructor() {
70 super();
71
72 /**
73 * @type {Array<ChoiceOption>}
74 */
75 this.options = [];
76 this.value = '';
77 };
78
79 /** @override */
80 static get styles() {
81 return css`
82 :host {
83 display: grid;
84 grid-auto-flow: column;
85 grid-template-columns: auto;
86 }
87 button, a {
88 display: block;
89 cursor: pointer;
90 border: 0;
91 color: var(--chops-gray-700);
92 font-weight: var(--chops-link-font-weight);
93 font-size: var(--chops-normal-font-size);
94 margin: 0.1em 4px;
95 padding: 4px 10px;
96 line-height: 1.4;
97 background: var(--chops-choice-bg);
98 text-decoration: none;
99 border-radius: 16px;
100 }
101 button[selected], a[selected] {
102 background: var(--chops-active-choice-bg);
103 color: var(--chops-link-color);
104 font-weight: var(--chops-link-font-weight);
105 border-radius: 16px;
106 }
107 `;
108 };
109
110 /**
111 * Public method for allowing parents to change the value of this component.
112 * @param {string} newValue
113 * @fires CustomEvent#change
114 */
115 setValue(newValue) {
116 if (newValue !== this.value) {
117 this.value = newValue;
118 this.dispatchEvent(new CustomEvent('change'));
119 }
120 }
121
122 /**
123 * Private setter for updating the value of the component based on an internal
124 * click event.
125 * @param {MouseEvent} e
126 * @private
127 */
128 _setValue(e) {
129 this.setValue(e.target.getAttribute('value'));
130 }
131};
132
133customElements.define('chops-choice-buttons', ChopsChoiceButtons);