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-side-navigation): initial implementation #1889

Merged
merged 31 commits into from
Jul 23, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 4 additions & 4 deletions packages/base/src/UI5Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,10 @@ class UI5Element extends HTMLElement {
* @private
*/
_invalidate() {
if (this._shouldInvalidateParent) {
this.parentNode._invalidate();
}

if (!this._upToDate) {
// console.log("already invalidated", this, ...arguments);
return;
Expand All @@ -502,10 +506,6 @@ class UI5Element extends HTMLElement {
this._upToDate = false;
// console.log("INVAL", this, ...arguments);
RenderScheduler.renderDeferred(this);

if (this._shouldInvalidateParent) {
this.parentNode._invalidate();
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions packages/fiori/bundle.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import "./dist/features/CoPilotAnimation.js";
import FlexibleColumnLayout from "./dist/FlexibleColumnLayout.js";
import ProductSwitch from "./dist/ProductSwitch.js";
import ProductSwitchItem from "./dist/ProductSwitchItem.js";
import SideNavigation from "./dist/SideNavigation.js";
import SideNavigationItem from "./dist/SideNavigationItem.js";
import SideNavigationSubItem from "./dist/SideNavigationSubItem.js";
import ShellBar from "./dist/ShellBar.js";
import ShellBarItem from "./dist/ShellBarItem.js";
import UploadCollection from "./dist/UploadCollection.js";
Expand Down
80 changes: 80 additions & 0 deletions packages/fiori/src/SideNavigation.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<div class="ui5-sn-root">
{{> header }}

{{#if items.length}}
<ui5-tree
id="ui5-sn-items-tree"
mode="None"
?_minimal="{{collapsed}}"
_toggle-button-end
@ui5-item-click="{{handleTreeItemClick}}"
>
{{#each _items}}
<ui5-tree-item
icon="{{this.item.icon}}"
.associatedItem="{{this.item}}"
text="{{this.item.text}}"
?has-children="{{this.item.items.length}}"
?expanded="{{this.item.expanded}}"
?selected="{{this.selected}}"
>
{{#unless ../collapsed}}
{{#each this.item.items}}
<ui5-tree-item
.associatedItem="{{this}}"
text="{{this.text}}"
?selected="{{this.selected}}"
>
</ui5-tree-item>
{{/each}}
{{/unless}}
</ui5-tree-item>
{{/each}}
</ui5-tree>
{{/if}}

<div class="ui5-sn-spacer"></div>

{{#if fixedItems.length}}
<div>
<div class="ui5-sn-bottom-content-border">
<span></span>
</div>
<ui5-tree
id="ui5-sn-fixed-items-tree"
mode="None"
?_minimal="{{collapsed}}"
_toggle-button-end
@ui5-item-click="{{handleTreeItemClick}}"
>
{{#each _fixedItems}}
<ui5-tree-item
icon="{{this.item.icon}}"
.associatedItem="{{this.item}}"
text="{{this.item.text}}"
?has-children="{{this.item.items.length}}"
?expanded="{{this.item.expanded}}"
?selected="{{this.selected}}"
>
{{#unless ../collapsed}}
{{#each this.item.items}}
<ui5-tree-item
.associatedItem="{{this}}"
text="{{this.text}}"
?selected="{{this.selected}}"
>
</ui5-tree-item>
{{/each}}
{{/unless}}
</ui5-tree-item>
{{/each}}
</ui5-tree>
</div>
{{/if}}

{{> footer }}
</div>

{{#*inline header}}{{/inline}}

{{#*inline footer}}{{/inline}}
238 changes: 238 additions & 0 deletions packages/fiori/src/SideNavigation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import ResponsivePopover from "@ui5/webcomponents/dist/ResponsivePopover.js";
import Tree from "@ui5/webcomponents/dist/Tree.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";

/**
* @public
*/
const metadata = {
tag: "ui5-side-navigation",
managedSlots: true,
properties: /** @lends sap.ui.webcomponents.fiori.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,
},
},
slots: /** @lends sap.ui.webcomponents.fiori.SideNavigation.prototype */ {
/**
* Defines the main items of the <code>ui5-side-navigation</code>. Use the <code>ui5-side-navigation-item</code> component
* for the top-level items, and the <code>ui5-side-navigation-subitem</code> component for second-level items, nested
* inside the items.
*
* @public
* @slot
*/
"default": {
propertyName: "items",
invalidateParent: true,
type: HTMLElement,
},

/**
* Defines the fixed items at the bottom of the <code>ui5-side-navigation</code>. Use the <code>ui5-side-navigation-item</code> component
* for the fixed items, and optionally the <code>ui5-side-navigation-subitem</code> component to provide second-level items inside them.
*
* <b>Note:</b> In order to achieve the best user experience, it is recommended that you keep the fixed items "flat" (do not pass sub-items)
*
* @public
* @slot
*/
fixedItems: {
type: HTMLElement,
invalidateParent: true,
},
},
events: /** @lends sap.ui.webcomponents.fiori.SideNavigation.prototype */ {
/**
* Fired when the selection has changed via user interaction
*
* @event sap.ui.webcomponents.fiori.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.fiori.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([
Tree.define(),
ResponsivePopover.define(),
]);
}

onBeforeRendering() {
this._items = this.items.map(item => {
return {
item,
selected: ((item.items.some(subItem => subItem.selected) && this.collapsed) || item.selected),
};
});

this._fixedItems = this.fixedItems.map(item => {
return {
item,
selected: ((item.items.some(subItem => subItem.selected) && this.collapsed) || item.selected),
};
});
}

_setSelectedItem(item) {
this._walk(current => {
current.selected = false;
});
item.selected = true;

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

_buildPopoverContent(item) {
this._popoverContent = {
mainItem: item,
mainItemSelected: item.selected && !item.items.some(subItem => subItem.selected),
subItems: item.items,
};
}

handleTreeItemClick(event) {
const treeItem = event.detail.item;
const item = treeItem.associatedItem;

if (item.selected && !this.collapsed) {
return;
}

if (this.collapsed && item.items.length) {
this._buildPopoverContent(item);
const currentTree = this._itemsTree === event.target ? this._itemsTree : this._fixedItemsTree;
this.openPicker(currentTree._getListItemForTreeItem(treeItem));
} else {
this._setSelectedItem(item);
}
}

handleListItemClick(event) {
const listItem = event.detail.item;
const item = listItem.associatedItem;

if (item.selected) {
return;
}

this._setSelectedItem(item);
this.closePicker();
}

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

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

async closePicker(opener) {
const responsivePopover = await this.getPicker();
responsivePopover.close();
}

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

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

_walk(callback) {
this.items.forEach(current => {
callback(current);

current.items.forEach(currentSubitem => {
callback(currentSubitem);
});
});

this.fixedItems.forEach(current => {
callback(current);

current.items.forEach(currentSubitem => {
callback(currentSubitem);
});
});
}
}

SideNavigation.define();

export default SideNavigation;
Loading