Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui5-segmentedbutton): initial implementation #1164

Merged
merged 14 commits into from
Feb 10, 2020
Merged
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";
ilhan007 marked this conversation as resolved.
Show resolved Hide resolved
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
ilhan007 marked this conversation as resolved.
Show resolved Hide resolved
* 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