UNPKG

@limetech/lime-elements

Version:
214 lines (213 loc) • 7.8 kB
import { h, Host, } from "@stencil/core"; import { createRandomString } from "../../util/random-string"; /** * A button group control is a linear set of two or more buttons. * * ## Usage * * Button groups are often used to display different views of the same thing. A * common example of this component is when you switch between [ Map | Transit * | Satellite ] views to look at an area on the map. * * In some cases, button groups may serve as quick filters as well. For example * a list of contacts, in which the user can switch to [ All | Favorites * | Frequently contacted ] can incorporate a button group to quickly filter out * items and display subsets of them. * * ## Layout * * The button groups are usually placed in top headers and action bars, * sometimes with other elements. Since the group items will always be rendered * in a row, you must make sure not to have too many buttons in the group. * Because if the container of your button group does not get enough space to * fit in all its buttons, they will have to truncate their text and may appear * very cramped together. Always think about how your button group will appear * on a small screen such as phones. * :::note * Button can contain text or icons, but not both simultaneously! * ::: * * Within the group, icon buttons will all have the same width, while each text button * inherits its width from its content. * * @exampleComponent limel-example-button-group-icons * @exampleComponent limel-example-button-group-basic * @exampleComponent limel-example-button-group-mix * @exampleComponent limel-example-button-group-badges * @exampleComponent limel-example-button-group-composite */ export class ButtonGroup { constructor() { /** * List of buttons for the group */ this.value = []; /** * True if the button-group should be disabled */ this.disabled = false; this.radioGroupName = createRandomString(); this.setSelectedButton = () => { var _a; this.selectedButtonId = (_a = this.value.find((button) => { return button.selected; })) === null || _a === void 0 ? void 0 : _a.id; }; this.renderButton = this.renderButton.bind(this); this.onChange = this.onChange.bind(this); this.renderContent = this.renderContent.bind(this); } componentWillLoad() { this.setSelectedButton(); } render() { return (h(Host, { key: '2295d3bf146ae9d3aa44c4a4c3281ce1b72d8a63', role: "radiogroup" }, this.value.map(this.renderButton))); } renderButton(button) { // Prefix with 'b' because html IDs cannot start with a digit, // and we need to differentiate from the ID on the limel-icon. /Ads const buttonId = `b${button.id}`; const classes = { button: true, 'button--selected': this.isButtonChecked(button), }; return (h("div", { class: classes }, h("input", { type: "radio", name: this.radioGroupName, checked: this.isButtonChecked(button), disabled: this.disabled, id: buttonId, onChange: this.onChange }), h("label", { htmlFor: buttonId }, this.renderContent(button), this.renderBadge(button)))); } renderContent(button) { if (button.icon) { return this.renderIcon(button); } return this.renderLabel(button); } isButtonChecked(button) { return button.id === this.selectedButtonId; } renderLabel(button) { return h("span", { class: "button__label" }, button.title); } renderIcon(button) { // Prefix with 'i' because html IDs cannot start with a digit, // and we need to differentiate from the "buttonId". /Ads const iconId = `i${button.id}`; return [ h("limel-icon", { id: iconId, class: "button__icon", "aria-label": button.title, name: button.icon, size: "small", badge: true }), h("limel-tooltip", { elementId: iconId, label: button.title }), ]; } renderBadge(button) { if (!button.badge) { return; } return h("limel-badge", { label: button.badge }); } onChange(event) { event.stopPropagation(); const target = event.target; // The ID is prefixed with `b` in the HTML, remember? /Ads this.selectedButtonId = target.id.slice(1); const button = this.value.find((item) => { return item.id === this.selectedButtonId; }); this.change.emit(button); } valueChanged() { this.setSelectedButton(); } static get is() { return "limel-button-group"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["button-group.scss"] }; } static get styleUrls() { return { "$": ["button-group.css"] }; } static get properties() { return { "value": { "type": "unknown", "mutable": false, "complexType": { "original": "Button[]", "resolved": "Button[]", "references": { "Button": { "location": "import", "path": "../button/button.types", "id": "src/components/button/button.types.ts::Button", "referenceLocation": "Button" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "List of buttons for the group" }, "getter": false, "setter": false, "defaultValue": "[]" }, "disabled": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "True if the button-group should be disabled" }, "getter": false, "setter": false, "reflect": true, "attribute": "disabled", "defaultValue": "false" } }; } static get states() { return { "selectedButtonId": {} }; } static get events() { return [{ "method": "change", "name": "change", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Dispatched when a button is selected/deselected" }, "complexType": { "original": "Button", "resolved": "Button", "references": { "Button": { "location": "import", "path": "../button/button.types", "id": "src/components/button/button.types.ts::Button", "referenceLocation": "Button" } } } }]; } static get watchers() { return [{ "propName": "value", "methodName": "valueChanged" }]; } }