Skip to content

Commit

Permalink
feat(ui5-color-palette-popover): initial implementation (#3746)
Browse files Browse the repository at this point in the history
  • Loading branch information
tsanislavgatev authored Sep 3, 2021
1 parent 23ce10f commit 894628f
Show file tree
Hide file tree
Showing 18 changed files with 919 additions and 17 deletions.
1 change: 1 addition & 0 deletions packages/main/bundle.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import Carousel from "./dist/Carousel.js";
import CheckBox from "./dist/CheckBox.js";
import ColorPalette from "./dist/ColorPalette.js";
import ColorPaletteItem from "./dist/ColorPaletteItem.js";
import ColorPalettePopover from "./dist/ColorPalettePopover.js";
import ColorPicker from "./dist/ColorPicker.js";
import ComboBox from "./dist/ComboBox.js";
import DatePicker from "./dist/DatePicker.js";
Expand Down
24 changes: 19 additions & 5 deletions packages/main/src/ColorPalette.hbs
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
<div
class="ui5-cp-root"
class="{{classes.colorPaletteRoot}}"
@click={{_onclick}}
@keyup={{_onkeyup}}
@keydown={{_onkeydown}}
>
{{#if this.showDefaultColor}}
<div class="ui5-cp-default-color-button-wrapper">
<ui5-button
class="ui5-cp-default-color-button"
design="Transparent"
@click={{_onDefaultColorClick}}
@keydown={{_onDefaultColorKeyDown}}>Default color</ui5-button>
<div class="ui5-cp-separator"></div>
</div>
{{/if}}
<div class="ui5-cp-item-container"
role="region"
aria-label="{{colorContainerLabel}}"
@keydown="{{_onColorContainerKeyDown}}"
>
{{#each this.displayedColors}}
<slot
Expand All @@ -23,16 +34,19 @@
design="Transparent"
class="ui5-cp-more-colors"
@click="{{_openMoreColorsDialog}}"
@keydown={{_onMoreColorsKeyDown}}
>{{colorPaleteMoreColorsText}}</ui5-button>
</div>
{{/if}}

{{#if showRecentColors}}
<div class="ui5-cp-separator"></div>
<div class="ui5-cp-recent-colors-wrapper">
{{#each recentColors}}
<ui5-color-palette-item value="{{this}}"></ui5-color-palette-item>
{{/each}}
<div class="ui5-cp-separator"></div>
<div class="ui5-cp-recent-colors-container" @keydown="{{_onRecentColorsContainerKeyDown}}">
{{#each recentColors}}
<ui5-color-palette-item value="{{this}}"></ui5-color-palette-item>
{{/each}}
</div>
</div>
{{/if}}
</div>
215 changes: 208 additions & 7 deletions packages/main/src/ColorPalette.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18
import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js";
import CSSColor from "@ui5/webcomponents-base/dist/types/CSSColor.js";
import ItemNavigationBehavior from "@ui5/webcomponents-base/dist/types/ItemNavigationBehavior.js";
import { isPhone } from "@ui5/webcomponents-base/dist/Device.js";
import {
isSpace,
isEnter,
isDown,
isUp,
isTabNext,
} from "@ui5/webcomponents-base/dist/Keys.js";
import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js";
import ColorPaletteTemplate from "./generated/templates/ColorPaletteTemplate.lit.js";
Expand Down Expand Up @@ -50,6 +54,28 @@ const metadata = {
type: Boolean,
},

/**
* Defines whether the user can choose the default color from a button.
* @type {boolean}
* @defaultvalue false
* @private
* @since 1.0.0-rc.16
*/
showDefaultColor: {
type: Boolean,
},

/**
* Defines the default color of the color palette
* <b>Note:</b> The default color should be a part of the ColorPalette colors</code>
* @type {CSSColor}
* @private
* @since 1.0.0-rc.16
*/
defaultColor: {
type: CSSColor,
},

/**
* Defines the selected color.
* @type {CSSColor}
Expand All @@ -58,6 +84,15 @@ const metadata = {
_selectedColor: {
type: CSSColor,
},

/**
* Defines if the palette is in Popup or Embeded mode.
* @type {CSSColor}
* @private
*/
popupMode: {
type: Boolean,
},
},
slots: /** @lends sap.ui.webcomponents.main.ColorPalette.prototype */ {
/**
Expand Down Expand Up @@ -155,10 +190,16 @@ class ColorPalette extends UI5Element {
this.i18nBundle = getI18nBundle("@ui5/webcomponents");
this._itemNavigation = new ItemNavigation(this, {
getItemsCallback: () => this.displayedColors,
rowSize: 5,
rowSize: this.rowSize,
behavior: ItemNavigationBehavior.Cyclic,
});

this._itemNavigationRecentColors = new ItemNavigation(this, {
getItemsCallback: () => this.recentColorsElements,
rowSize: this.rowSize,
behavior: ItemNavigationBehavior.Static,
});

this._recentColors = [];
}

Expand All @@ -178,6 +219,10 @@ class ColorPalette extends UI5Element {
}

selectColor(item) {
if (!item.value) {
return;
}

item.focus();

if (this.displayedColors.includes(item)) {
Expand Down Expand Up @@ -209,18 +254,122 @@ class ColorPalette extends UI5Element {
}

_onkeyup(event) {
if (isSpace(event)) {
if (isSpace(event) && event.target.localName === "ui5-color-palette-item") {
event.preventDefault();
this.selectColor(event.target);
}
}

_onkeydown(event) {
if (isEnter(event)) {
if (isEnter(event) && event.target.localName === "ui5-color-palette-item") {
this.selectColor(event.target);
}
}

_onDefaultColorKeyDown(event) {
if (isTabNext(event) && this.popupMode) {
event.preventDefault();
this._onDefaultColorClick();
}

if (isDown(event)) {
event.stopPropagation();

this.focusColorElement(this.colorPaletteNavigationElements[1], this._itemNavigation);
} else if (isUp(event)) {
event.stopPropagation();
const lastElementInNavigation = this.colorPaletteNavigationElements[this.colorPaletteNavigationElements.length - 1];

if (this.hasRecentColors) {
this.focusColorElement(lastElementInNavigation, this._itemNavigationRecentColors);
} else if (this.showMoreColors) {
lastElementInNavigation.focus();
} else {
const colorPaletteFocusIndex = (this.displayedColors.length % this.rowSize) * this.rowSize;

this.focusColorElement(this.displayedColors[colorPaletteFocusIndex], this._itemNavigation);
}
}
}

_onMoreColorsKeyDown(event) {
const index = this.colorPaletteNavigationElements.indexOf(event.target);
const colorPaletteFocusIndex = (this.displayedColors.length % this.rowSize) * this.rowSize;

if (isUp(event)) {
event.stopPropagation();

this.focusColorElement(this.displayedColors[colorPaletteFocusIndex], this._itemNavigation);
} else if (isDown(event)) {
event.stopPropagation();

if (this.hasRecentColors) {
this.focusColorElement(this.colorPaletteNavigationElements[index + 1], this._itemNavigationRecentColors);
} else if (this.showDefaultColor) {
this.colorPaletteNavigationElements[0].focus();
} else {
this.focusColorElement(this.displayedColors[0], this._itemNavigation);
}
}
}

_onColorContainerKeyDown(event) {
const lastElementInNavigation = this.colorPaletteNavigationElements[this.colorPaletteNavigationElements.length - 1];
if (isTabNext(event) && this.popupMode) {
event.preventDefault();
this.selectColor(event.target);
}

if (isUp(event) && event.target === this.displayedColors[0] && this.colorPaletteNavigationElements.length > 1) {
event.stopPropagation();
if (this.showDefaultColor) {
this.colorPaletteNavigationElements[0].focus();
} else if (!this.showDefaultColor && this.hasRecentColors) {
this.focusColorElement(lastElementInNavigation, this._itemNavigationRecentColors);
} else if (!this.showDefaultColor && this.showMoreColors) {
lastElementInNavigation.focus();
}
} else if (isDown(event) && event.target === this.displayedColors[this.displayedColors.length - 1] && this.colorPaletteNavigationElements.length > 1) {
event.stopPropagation();
const isRecentColorsNextElement = (this.showDefaultColor && !this.showMoreColors && this.hasRecentColors) || (!this.showDefaultColor && !this.showMoreColors && this.hasRecentColors);

if (this.showDefaultColor && this.showMoreColors) {
this.colorPaletteNavigationElements[2].focus();
} else if (this.showDefaultColor && !this.showMoreColors && (!this.showRecentColors || !this.recentColors[0])) {
this.colorPaletteNavigationElements[0].focus();
} else if (isRecentColorsNextElement) {
this.focusColorElement(lastElementInNavigation, this._itemNavigationRecentColors);
} else if (!this.showDefaultColor && this.showMoreColors) {
this.colorPaletteNavigationElements[1].focus();
}
}
}

_onRecentColorsContainerKeyDown(event) {
if (isUp(event)) {
if (this.showMoreColors) {
this.colorPaletteNavigationElements[1 + this.showDefaultColor].focus();
} else if (!this.showMoreColors && this.colorPaletteNavigationElements.length > 1) {
const colorPaletteFocusIndex = (this.displayedColors.length % this.rowSize) * this.rowSize;
event.stopPropagation();

this.focusColorElement(this.displayedColors[colorPaletteFocusIndex], this._itemNavigation);
}
} else if (isDown(event)) {
if (this.showDefaultColor) {
this.colorPaletteNavigationElements[0].focus();
} else {
event.stopPropagation();
this.focusColorElement(this.displayedColors[0], this._itemNavigation);
}
}
}

focusColorElement(element, itemNavigation) {
itemNavigation.setCurrentItem(element);
itemNavigation._focusCurrentItem();
}

async _chooseCustomColor() {
const colorPicker = await this.getColorPicker();
this._setColor(colorPicker.color);
Expand All @@ -237,6 +386,12 @@ class ColorPalette extends UI5Element {
dialog.show();
}

_onDefaultColorClick() {
if (this.defaultColor) {
this._setColor(this.defaultColor);
}
}

/**
* Returns the selected color.
*/
Expand All @@ -245,7 +400,7 @@ class ColorPalette extends UI5Element {
}

get displayedColors() {
return this.colors.filter(item => item.value).slice(0, 15);
return this.getSlottedNodes("colors").filter(item => item.value).slice(0, 15);
}

get colorContainerLabel() {
Expand All @@ -260,18 +415,64 @@ class ColorPalette extends UI5Element {
return this.showMoreColors && this.moreColorsFeature;
}

get rowSize() {
return 5;
}

get hasRecentColors() {
return this.showRecentColors && this.recentColors[0];
}

get recentColors() {
if (this._recentColors.length > 5) {
this._recentColors = this._recentColors.slice(0, 5);
if (this._recentColors.length > this.rowSize) {
this._recentColors = this._recentColors.slice(0, this.rowSize);
}

while (this._recentColors.length < 5) {
while (this._recentColors.length < this.rowSize) {
this._recentColors.push("");
}

return this._recentColors;
}

get recentColorsElements() {
if (this.getDomRef()) {
return Array.from(this.getDomRef().querySelectorAll(".ui5-cp-recent-colors-wrapper [ui5-color-palette-item]")).filter(x => x.value !== "");
}

return [];
}

get colorPaletteNavigationElements() {
const navigationElements = [];
const rootElement = this.shadowRoot.querySelector(".ui5-cp-root");

if (this.showDefaultColor) {
navigationElements.push(rootElement.querySelector(".ui5-cp-default-color-button"));
}

navigationElements.push(this.displayedColors[0]);

if (this.showMoreColors) {
navigationElements.push(rootElement.querySelector(".ui5-cp-more-colors"));
}

if (this.showRecentColors && !!this.recentColorsElements.length) {
navigationElements.push(this.recentColorsElements[0]);
}

return navigationElements;
}

get classes() {
return {
colorPaletteRoot: {
"ui5-cp-root": true,
"ui5-cp-root-phone": isPhone(),
},
};
}

async _getDialog() {
const staticAreaItem = await this.getStaticAreaItemDomRef();
return staticAreaItem.querySelector("[ui5-dialog]");
Expand Down
11 changes: 11 additions & 0 deletions packages/main/src/ColorPaletteItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js";
import CSSColor from "@ui5/webcomponents-base/dist/types/CSSColor.js";
import { isPhone } from "@ui5/webcomponents-base/dist/Device.js";
import ColorPaletteItemTemplate from "./generated/templates/ColorPaletteItemTemplate.lit.js";
import {
COLORPALETTE_COLOR_LABEL,
Expand Down Expand Up @@ -48,6 +49,15 @@ const metadata = {
type: String,
},

/**
* Defines if the ColorPalette is on phone mode.
* @private
* @type {Boolean}
*/
phone: {
type: Boolean,
},

/**
* @private
* @type {boolean}
Expand Down Expand Up @@ -107,6 +117,7 @@ class ColorPaletteItem extends UI5Element {

onBeforeRendering() {
this._disabled = !this.value;
this.phone = isPhone();
}

get colorLabel() {
Expand Down
Loading

0 comments on commit 894628f

Please sign in to comment.