Skip to content

Commit

Permalink
feat(ui5-segmentedbutton): initial implementation (#1164)
Browse files Browse the repository at this point in the history
  • Loading branch information
ivoplashkov authored Feb 10, 2020
1 parent 323968e commit 931fbe0
Show file tree
Hide file tree
Showing 11 changed files with 453 additions and 6 deletions.
1 change: 1 addition & 0 deletions packages/main/bundle.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import Popover from "./dist/Popover.js";
import Panel from "./dist/Panel.js";
import RadioButton from "./dist/RadioButton.js";
import ResponsivePopover from "./dist/ResponsivePopover.js";
import SegmentedButton from "./dist/SegmentedButton.js";
import Select from "./dist/Select.js";
import Option from "./dist/Option.js";
import Switch from "./dist/Switch.js";
Expand Down
18 changes: 17 additions & 1 deletion packages/main/src/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,16 @@ const metadata = {
_iconSettings: {
type: Object,
},

/**
* Defines the tabIndex of the component.
* @private
*/
_tabIndex: {
type: String,
defaultValue: "0",
noAttribute: true,
},
},
slots: /** @lends sap.ui.webcomponents.main.Button.prototype */ {
/**
Expand Down Expand Up @@ -314,7 +324,13 @@ class Button extends UI5Element {
}

get tabIndexValue() {
return this.nonFocusable ? "-1" : "0";
const tabindex = this.getAttribute("tabindex");

if (tabindex) {
return tabindex;
}

return this.nonFocusable ? "-1" : this._tabIndex;
}

static async define(...params) {
Expand Down
6 changes: 6 additions & 0 deletions packages/main/src/SegmentedButton.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div
@click="{{_onclick}}"
class="ui5-segmentedbutton-root"
>
<slot></slot>
</div>
185 changes: 185 additions & 0 deletions packages/main/src/SegmentedButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";

// Template
import SegmentedButtonTemplate from "./generated/templates/SegmentedButtonTemplate.lit.js";

// Styles
import SegmentedButtonCss from "./generated/themes/SegmentedButton.css.js";

/**
* @public
*/
const metadata = {
tag: "ui5-segmentedbutton",
properties: /** @lends sap.ui.webcomponents.main.SegmentedButton.prototype */ {},
slots: /** @lends sap.ui.webcomponents.main.SegmentedButton.prototype */ {

/**
* Defines the buttons of <code>ui5-segmentedbutton</code>.
* <br><br>
* <b>Note:</b> Multiple buttons are allowed.
* <br><br>
* <b>Note:</b> Use the <code>ui5-togglebutton</code> for the intended design.
* @type {HTMLElement[]}
* @slot
* @public
*/
"default": {
propertyName: "buttons",
type: HTMLElement,
},
},
events: /** @lends sap.ui.webcomponents.main.SegmentedButton.prototype */ {

/**
* Fired when the selected button changes.
*
* @event
* @param {HTMLElement} selectedButton the pressed button.
* @public
*/
selectionChange: {
detail: {
selectedButton: { type: HTMLElement },
},
},
},
};

/**
* @class
*
* <h3 class="comment-api-title">Overview</h3>
*
* The <code>SegmentedButton</code> shows a group of buttons. When the user clicks or taps
* one of the buttons, it stays in a pressed state. It automatically resizes the buttons
* to fit proportionally within the component. When no width is set, the component uses the available width.
* <br><br>
* <b>Note:</b> There can be just one selected <code>button</code> at a time.
*
* <h3>ES6 Module Import</h3>
*
* <code>import "@ui5/webcomponents/dist/SegmentedButton";</code>
*
* @constructor
* @author SAP SE
* @alias sap.ui.webcomponents.main.SegmentedButton
* @extends sap.ui.webcomponents.base.UI5Element
* @tagname ui5-segmentedbutton
* @since 1.0.0-rc.6
* @public
*/
class SegmentedButton extends UI5Element {
static get metadata() {
return metadata;
}

static get render() {
return litRender;
}

static get template() {
return SegmentedButtonTemplate;
}

static get styles() {
return SegmentedButtonCss;
}

constructor() {
super();
this.initItemNavigation();

this.absoluteWidthSet = false; // set to true whenever we set absolute width to the component
this.percentageWidthSet = false; // set to true whenever we set 100% width to the component
}

onEnterDOM() {
this._handleResizeBound = this._handleResize.bind(this);

ResizeHandler.register(document.body, this._handleResizeBound);
}

onExitDOM() {
ResizeHandler.deregister(document.body, this._handleResizeBound);
}

onBeforeRendering() {
this.normalizeSelection();
}

async onAfterRendering() {
await Promise.all(this.buttons.map(button => button._waitForDomRef));
this.widths = this.buttons.map(button => button.offsetWidth);
}

initItemNavigation() {
this._itemNavigation = new ItemNavigation(this);

this._itemNavigation.getItemsCallback = () => this.getSlottedNodes("buttons");
}

normalizeSelection() {
this._selectedButton = this.buttons.filter(button => button.pressed).pop();

if (this._selectedButton) {
this.buttons.forEach(button => {
button.pressed = false;
});
this._selectedButton.pressed = true;
}
}

_onclick(event) {
if (event.target !== this._selectedButton) {
if (this._selectedButton) {
this._selectedButton.pressed = false;
}
this._selectedButton = event.target;
this.fireEvent("selectionChange", {
selectedButton: this._selectedButton,
});
}
this._selectedButton.pressed = true;

this._itemNavigation.update(this._selectedButton);

return this;
}

_handleResize() {
const parentWidth = this.parentNode.offsetWidth;

if (!this.style.width || this.percentageWidthSet) {
this.style.width = `${Math.max(...this.widths) * this.buttons.length}px`;
this.absoluteWidthSet = true;
}

this.buttons.forEach(button => {
button.style.width = "100%";
});

if (parentWidth <= this.offsetWidth && this.absoluteWidthSet) {
this.style.width = "100%";
this.percentageWidthSet = true;
}
}

/**
* Currently selected button.
*
* @readonly
* @type { ui5-togglebutton }
* @public
*/
get selectedButton() {
return this._selectedButton;
}
}

SegmentedButton.define();

export default SegmentedButton;
4 changes: 2 additions & 2 deletions packages/main/src/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ const metadata = {
},
events: /** @lends sap.ui.webcomponents.main.Select.prototype */ {
/**
* Fired when the selected item changes.
* Fired when the selected option changes.
*
* @event
* @param {HTMLElement} item the selected item.
* @param {HTMLElement} selectedOption the selected option.
* @public
*/
change: {
Expand Down
13 changes: 10 additions & 3 deletions packages/main/src/themes/Button.css
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
color: inherit;
text-shadow: inherit;
font: inherit;
white-space: inherit;
overflow: inherit;
text-overflow: inherit;
}

:host(:not([active]):hover) {
Expand Down Expand Up @@ -83,6 +86,9 @@
.ui5-button-text {
outline: none;
position: relative;
white-space: inherit;
overflow: inherit;
text-overflow: inherit;
}

:host([has-icon]) .ui5-button-text {
Expand All @@ -104,9 +110,10 @@
}

bdi {
display: flex;
justify-content: flex-start;
align-items: center;
display: block;
white-space: inherit;
overflow: inherit;
text-overflow: inherit;
}

:host([active]:not([disabled])) {
Expand Down
34 changes: 34 additions & 0 deletions packages/main/src/themes/SegmentedButton.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
:host(:not([hidden])) {
display: inline-block;
}

.ui5-segmentedbutton-root {
display: flex;
}

::slotted(ui5-togglebutton) {
border-radius: 0;
height: 2.75rem;
min-width: 2.5rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

::slotted(ui5-togglebutton:nth-child(odd)) {
border: 1px solid var(--sapButton_Selected_BorderColor);
border-right: 0;
border-left: 0;
}

::slotted(ui5-togglebutton:last-child) {
border-top-right-radius: 0.375rem;
border-bottom-right-radius: 0.375rem;
border-right: 1px solid var(--sapButton_Selected_BorderColor);
}

::slotted(ui5-togglebutton:first-child) {
border-top-left-radius: 0.375rem;
border-bottom-left-radius: 0.375rem;
border-left: 1px solid var(--sapButton_Selected_BorderColor);
}
Loading

0 comments on commit 931fbe0

Please sign in to comment.