Skip to content

feat(ui5-side-navigation): initial implementation #1889

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

Merged
merged 31 commits into from
Jul 23, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
776f98a
feat(ui5-side-navigation): initial implementation
fifoosid Jun 26, 2020
c706570
implement kbh & collapse/expand behaviour
fifoosid Jun 29, 2020
c4410c1
implement events
fifoosid Jun 30, 2020
db8f9b6
add samples & docs
fifoosid Jun 30, 2020
94887af
refactor icons
fifoosid Jul 1, 2020
d7a9c92
fix comments
fifoosid Jul 2, 2020
f444d10
wip
fifoosid Jul 7, 2020
b75e828
finish implementation
fifoosid Jul 8, 2020
1a19ffc
move to fiori package, add tests, fix comments
fifoosid Jul 9, 2020
3c9dc6d
fix comments and styling issues
fifoosid Jul 10, 2020
a64bcf1
fix background
fifoosid Jul 10, 2020
d89a614
Merge remote-tracking branch 'origin/master' into side-navigation
vladitasev Jul 15, 2020
3ad734a
simplification and disambiguation
vladitasev Jul 15, 2020
d55bb10
remove unnecessary parameters and functions
vladitasev Jul 15, 2020
7b3d14f
delete level
vladitasev Jul 15, 2020
ccb96d9
delete expandable 1
vladitasev Jul 15, 2020
f43dbc8
use existing tree function, fix module imports help
vladitasev Jul 16, 2020
941651b
delete expandable - it is the same as showToggleButton
vladitasev Jul 16, 2020
14cf96c
move _collapsed and _showToggleButtonEnd to tree level and don't pass…
vladitasev Jul 16, 2020
ff7b909
fix for IE: do not override the CSS var, directly override width instead
vladitasev Jul 16, 2020
e7236df
selected state fixed
vladitasev Jul 16, 2020
d7df553
Merge branch 'master' into side-navigation
fifoosid Jul 20, 2020
45c2d28
apply invalidateParent & fix failing tests
fifoosid Jul 20, 2020
9b37a3b
selected can be changed programmatically
vladitasev Jul 20, 2020
63fb073
remove _selectedItem
vladitasev Jul 20, 2020
49e3ab3
make fixed items nestable & fix event firing for collapsed items
fifoosid Jul 21, 2020
8c0620d
fix comments
fifoosid Jul 21, 2020
8ed1eec
fix bug: cannot select fixed subitem
vladitasev Jul 23, 2020
44f89f1
slots docs, support for .hbs hooks, fix spacers in hbs
vladitasev Jul 23, 2020
23f5b50
sample fix
vladitasev Jul 23, 2020
d632e4c
add min height to the spacer for scenarios with many items
vladitasev Jul 23, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions packages/fiori/test/pages/SideNavigationSample.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Shell Bar</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

<script data-ui5-config type="application/json">
{
"rtl": false
}
</script>

<script src="../../webcomponentsjs/webcomponents-loader.js"></script>
<script src="../../resources/bundle.esm.js" type="module"></script>
<script nomodule src="../../resources/bundle.es5.js"></script>

<style>
html, body {
margin: 0;
padding: 0;
}

body {
height: 100vh;
display: flex;
flex-direction: column;
}
</style>
</head>

<body style="background-color: var(--sapBackgroundColor);">
<ui5-shellbar
primary-title="UI5 Web Components"
secondary-title="The Best Run SAP"
show-co-pilot
>
<ui5-button icon="menu" slot="startButton" id="startButton"></ui5-button>
</ui5-shellbar>

<ui5-side-navigation>
<ui5-side-navigation-item text="Home" icon="home"></ui5-side-navigation-item>
<ui5-side-navigation-item text="People" expandable expanded icon="group">
<ui5-side-navigation-sub-item text="From My Team" icon="employee-approvals"></ui5-side-navigation-sub-item>
<ui5-side-navigation-sub-item text="From Other Teams" icon="employee-rejections"></ui5-side-navigation-sub-item>
</ui5-side-navigation-item>
<ui5-side-navigation-item text="Locations" icon="locate-me" selected></ui5-side-navigation-item>
<ui5-side-navigation-item text="Events" expandable icon="calendar">
<ui5-side-navigation-sub-item text="Local"></ui5-side-navigation-sub-item>
<ui5-side-navigation-sub-item text="Others"></ui5-side-navigation-sub-item>
</ui5-side-navigation-item>

<ui5-side-navigation-item slot="fixedItems" text="Usefull Links" icon="chain-link"></ui5-side-navigation-item>
<ui5-side-navigation-item slot="fixedItems" text="History" icon="history"></ui5-side-navigation-item>
</ui5-side-navigation>

<script>
var sideNavigation = document.querySelector("ui5-side-navigation");
document.querySelector("#startButton").addEventListener("click", function(event) {
sideNavigation.collapsed = !sideNavigation.collapsed;
});
</script>
</body>
</html>
3 changes: 3 additions & 0 deletions packages/main/bundle.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ 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 SideNavigation from "./dist/SideNavigation.js";
import SideNavigationItem from "./dist/SideNavigationItem.js";
import SideNavigationSubItem from "./dist/SideNavigationSubItem.js";
import Switch from "./dist/Switch.js";
import MessageStrip from "./dist/MessageStrip.js";
import MultiComboBox from "./dist/MultiComboBox.js";
Expand Down
5 changes: 4 additions & 1 deletion packages/main/src/Icon.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<svg
<div class="ui5-icon-svg-wrapper">
<svg
class="ui5-icon-root"
tabindex="{{tabIndex}}"
dir="{{_dir}}"
Expand All @@ -22,3 +23,5 @@
<path transform="translate(0, 512) scale(1, -1)" d="{{pathData}}"/>
</g>
</svg>

</div>
71 changes: 71 additions & 0 deletions packages/main/src/SideNavigation.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<div class="ui5-sn-root">
{{#if items.length}}
<ui5-tree
id="ui5-sn-items-tree"
mode="SingleSelect"
?_show-selected-on-sub-items="true"
@ui5-item-click="{{handleItemClick}}"
>
{{#each _currentItems}}
<ui5-tree-item
icon="{{this.treeItem.icon}}"
level="{{this.treeItem.level}}"
.treeItem="{{this.treeItem}}"
show-toggle-button-end="true"
text="{{this.treeItem.text}}"
?has-children="{{this.treeItem.expandable}}"
?expanded="{{this.treeItem.expanded}}"
?_collapsed="{{this.collapsed}}"
?selected="{{this.treeItem.selected}}"
>
{{#if ../_shoudlShowSubItems}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is typo in "_shoudlShowSubItems" (should), but moreover such variable does not exist at least I could not find it

{{#if subItems}}
{{#each subItems}}
<ui5-tree-item
level="{{this.level}}"
.treeItem="{{this}}"
show-toggle-button-end="true"
text="{{this.text}}"
index="{{this.index}}"
?has-children="{{this.expandable}}"
?selected="{{this.selected}}"
>
</ui5-tree-item>
{{/each}}
{{/if}}
{{/if}}
</ui5-tree-item>
{{/each}}
</ui5-tree>
{{/if}}

{{#if _currentFixedItems.length}}
<div>
<div class="ui5-sn-bottom-content-border">
<span></span>
</div>
<ui5-tree
id="ui5-sn-fixed-items-tree"
mode="SingleSelect"
?_show-selected-on-sub-items="true"
@ui5-item-click="{{handleItemClick}}"
>
{{#each _currentFixedItems}}
<ui5-tree-item
icon="{{this.treeItem.icon}}"
level="{{this.treeItem.level}}"
.treeItem="{{this.treeItem}}"
show-toggle-button-end="true"
text="{{this.treeItem.text}}"
index="{{this.index}}"
?has-children="{{this.treeItem.expandable}}"
?expanded="{{this.treeItem.expanded}}"
?_collapsed="{{this.collapsed}}"
?selected="{{this.treeItem.selected}}"
>
</ui5-tree-item>
{{/each}}
</ui5-tree>
</div>
{{/if}}
</div>
229 changes: 229 additions & 0 deletions packages/main/src/SideNavigation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import ResponsivePopover from "./ResponsivePopover.js";
import List from "./List.js";
import SideNavigationTemplate from "./generated/templates/SideNavigationTemplate.lit.js";
import SideNavigationItemPopoverContentTemplate from "./generated/templates/SideNavigationItemPopoverContentTemplate.lit.js";

// Styles
import SideNavigationCss from "./generated/themes/SideNavigation.css.js";
import StandardListItem from "./StandardListItem.js";

/**
* @public
*/
const metadata = {
tag: "ui5-side-navigation",
managedSlots: true,
properties: /** @lends sap.ui.webcomponents.main.SideNavigation.prototype */ {
/**
* Defines whether the <code>ui5-side-navigation</code> is expanded or collapsed.
*
* @public
* @type {boolean}
* @defaultvalue false
*/
collapsed: {
type: Boolean,
},

/**
* @private
*/
_popoverContent: {
type: Object,
multiple: true,
},
},
slots: /** @lends sap.ui.webcomponents.main.SideNavigation.prototype */ {
/**
* Defines the items in the <code>ui5-side-navigation</code>.
*
* @public
* @slot
*/
"default": {
propertyName: "items",
type: HTMLElement,
},

/**
* Defines the fixed items in the bottom of the <code>ui5-side-navigation</code>.
*
* @public
* @slot
*/
fixedItems: {
type: HTMLElement,
},
},
events: /** @lends sap.ui.webcomponents.main.SideNavigation.prototype */ {
/**
* Fired when the selection has changed via user interaction
*
* @event sap.ui.webcomponents.main.SideNavigation#selection-change
* @param {HTMLElement} item the clicked item.
* @public
*/
"selection-change": {
item: {
type: HTMLElement,
},
},
},
};

/**
* @class
*
* <h3 class="comment-api-title">Overview</h3>
*
*
* <h3>Usage</h3>
*
* <code>ui5-side-navigation</code> is used as a standard menu in applications. In order to add menu items use <code>ui5-side-navigation-items</code>.
*
* For the <code>ui5-side-navigation</code>
* <h3>ES6 Module Import</h3>
*
* <code>import @ui5/webcomponents/dist/SideNavigation.js";</code>
*
* @constructor
* @author SAP SE
* @alias sap.ui.webcomponents.main.SideNavigation
* @extends UI5Element
* @tagname ui5-side-navigation
* @since 1.0.0-rc.8
* @appenddocs SideNavigationItem
* @public
*/
class SideNavigation extends UI5Element {
static get metadata() {
return metadata;
}

static get render() {
return litRender;
}

static get styles() {
return SideNavigationCss;
}

static get template() {
return SideNavigationTemplate;
}

static get staticAreaTemplate() {
return SideNavigationItemPopoverContentTemplate;
}

static async onDefine() {
await Promise.all([
ResponsivePopover.define(),
List.define(),
StandardListItem.define(),
]);
}

onBeforeRendering() {
this._currentItems = this.buildItems();
this._currentFixedItems = this.buildItems(true);
}

buildItems(isFixedItems = false) {
const currentItems = isFixedItems ? this.fixedItems : this.items;
const result = [];

currentItems.forEach(element => {
const item = {
treeItem: element,
subItems: element.items,
collapsed: this.collapsed,
};

result.push(item);
});

return result;
}

handleItemClick(event) {
const item = event.detail.item;
const currentTree = this._itemsTree === event.target ? this._itemsTree : this._fixedItemsTree; // Gets the tree which must not have selected items
const otherTree = this._fixedItemsTree === event.target ? this._itemsTree : this._fixedItemsTree; // Gets the tree which must not have selected items
otherTree._clearSelectedItems();

this.fireSelectionChange(event);

if (this.collapsed && item.treeItem.items.length) {
this._popoverContent = this._generatePopoverContent(event.detail.item);
this.openPicker(currentTree._getRealItemDomRef(item), item);
}
}

fireSelectionChange(event) {
const item = event.detail.item.treeItem // if event is fired when not collapsed
|| event.detail.item.item; // if event is fired from the list in the popover

this.fireEvent("selection-change", { item });
}

_resetSelectedItems(items) {
items.forEach(item => {
item.selected = false;

if (item.subItems) {
this._resetSelectedItems(item.subItems);
}
});
}

_generatePopoverContent(item) {
const result = [{
text: item.treeItem.text,
item: item.treeItem,
}];

item.treeItem.items.forEach(element => result.push({
text: element.text,
item: element,
}));

return result;
}

getMiddleFocusHelper() {
return this.getDomRef().querySelector(".ui5-sn-middle-focus-helper");
}

_focusOtherList() {
this.getMiddleFocusHelper().focus();
}

async getPicker() {
return (await this.getStaticAreaItemDomRef()).querySelector("ui5-responsive-popover");
}

async openPicker(opener) {
const responsivePopover = await this.getPicker();

responsivePopover.open(opener);
}

get _itemsTree() {
return this.getDomRef().querySelector("#ui5-sn-items-tree");
}

get _fixedItemsTree() {
return this.getDomRef().querySelector("#ui5-sn-fixed-items-tree");
}

get _shoudlShowSubItems() {
return !this.collapsed;
}
}

SideNavigation.define();

export default SideNavigation;
Loading