@limetech/lime-elements
Version:
214 lines (213 loc) • 7.8 kB
JavaScript
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"
}];
}
}