Popover menu: Introduce option to add a visual hint on the menu toggler

This adds a visual hint (caret down) on the toggler to help the user understand that clicking on the toggler won't do something right away, but will open a menu instead
This commit is contained in:
Molkobain
2021-03-19 19:46:36 +01:00
parent 482bf2e523
commit 8334b68285
4 changed files with 115 additions and 29 deletions

View File

@@ -21,9 +21,11 @@ $ibo-popover-menu--background-color: $ibo-color-white-100 !default;
$ibo-popover-menu--border-radius: $ibo-border-radius-300 !default;
$ibo-popover-menu--padding: 0 !default;
$ibo-popover-menu--toggler-visual-hint--margin-left: 0.5rem !default;
$ibo-popover-menu--section-border-radius: $ibo-popover-menu--border-radius !default;
.ibo-popover-menu{
.ibo-popover-menu {
display: none;
padding: $ibo-popover-menu--padding;
background-color: $ibo-popover-menu--background-color;
@@ -38,8 +40,11 @@ $ibo-popover-menu--section-border-radius: $ibo-popover-menu--border-radius !defa
}
}
.ibo-popover-menu--toggler-visual-hint {
margin-left: $ibo-popover-menu--toggler-visual-hint--margin-left;
}
.ibo-popover-menu--section{
.ibo-popover-menu--section {
display: flex;
flex-direction: column;
align-self: flex-start;
@@ -47,10 +52,11 @@ $ibo-popover-menu--section-border-radius: $ibo-popover-menu--border-radius !defa
width: 100%;
white-space: nowrap;
overflow: hidden; /* To avoid first/last entries of the menu to have no border-radius on hover */
&:first-child{
&:first-child {
border-radius: $ibo-popover-menu--section-border-radius $ibo-popover-menu--section-border-radius 0 0;
}
&:last-child {
border-radius: 0 0 $ibo-popover-menu--section-border-radius $ibo-popover-menu--section-border-radius;
}

View File

@@ -33,56 +33,74 @@ $(function()
opened: 'ibo-is-opened',
},
js_selectors:
{
menu: '[data-role="ibo-popover-menu"]',
section: '[data-role="ibo-popover-menu--section"]',
item: '[data-role="ibo-popover-menu--item"]',
},
{
menu: '[data-role="ibo-popover-menu"]',
section: '[data-role="ibo-popover-menu--section"]',
item: '[data-role="ibo-popover-menu--item"]',
},
// the constructor
_create: function()
{
_create: function () {
this._bindEvents();
this._closePopup();
if (true === this.options.add_visual_hint_to_toggler) {
this._addVisualHintToToggler();
}
},
// events bound via _bind are removed automatically
// revert other modifications here
_destroy: function()
{
_destroy: function () {
},
_bindEvents: function()
{
_bindEvents: function () {
const me = this;
const oBodyElem = $('body');
this.element.find(this.js_selectors.item).on('click', function(oEvent){
this.element.find(this.js_selectors.item).on('click', function (oEvent) {
me._closePopup();
});
// Mostly for outside clicks that should close elements
oBodyElem.on('click', function(oEvent){
oBodyElem.on('click', function (oEvent) {
me._onBodyClick(oEvent);
});
},
// Methods
_onBodyClick: function(oEvent)
{
if($(oEvent.target.closest(this.js_selectors.menu)).length === 0 && $(oEvent.target.closest(this.options.toggler)).length === 0)
{
// Events callbacks
_onBodyClick: function (oEvent) {
if ($(oEvent.target.closest(this.js_selectors.menu)).length === 0 && $(oEvent.target.closest(this.options.toggler)).length === 0) {
this._closePopup();
}
},
_openPopup: function()
{
// Methods
/**
* Add a visual hint (caret) on the toggler
*
* @return {boolean}
* @private
*/
_addVisualHintToToggler: function () {
if ('' === this.options.toggler) {
return false;
}
const oTogglerElem = $(this.options.toggler);
if (oTogglerElem.length === 0) {
return false;
}
oTogglerElem.append($(`<span class="ibo-popover-menu--toggler-visual-hint"><span class="fas fa-caret-down"></span></span>`));
return true;
},
_openPopup: function () {
this.element.addClass(this.css_classes.opened);
},
_closePopup: function()
{
_closePopup: function () {
this.element.removeClass(this.css_classes.opened);
},
openPopup: function()
{
openPopup: function () {
this._openPopup();
},
closePopup: function()

View File

@@ -37,10 +37,15 @@ class PopoverMenu extends UIBlock
// Overloaded constants
public const BLOCK_CODE = 'ibo-popover-menu';
public const DEFAULT_HTML_TEMPLATE_REL_PATH = 'base/components/popover-menu/layout';
public const DEFAULT_JS_TEMPLATE_REL_PATH = 'base/components/popover-menu/layout';
public const DEFAULT_JS_FILES_REL_PATH = [
'js/components/popover-menu.js',
];
/** @var string JS selector for the DOM element that should trigger the menu open/close */
protected $sTogglerJSSelector;
/** @var bool Whether the menu should add a visual hint (caret down) on the toggler to help the user understand that clicking on the toggler won't do something right away, but will open a menu instead */
protected $bAddVisualHintToToggler;
/** @var array $aSections */
protected $aSections;
@@ -52,9 +57,62 @@ class PopoverMenu extends UIBlock
public function __construct(?string $sId = null)
{
parent::__construct($sId);
$this->sTogglerJSSelector = '';
$this->bAddVisualHintToToggler = false;
$this->aSections = [];
}
/**
* @param string $sSelector
*
* @return $this
* @uses static::$sTogglerJSSelector
*/
public function SetTogglerJSSelector(string $sSelector)
{
$this->sTogglerJSSelector = $sSelector;
return $this;
}
/**
* @return string
* @uses static::$sTogglerJSSelector
*/
public function GetTogglerJSSelector(): string
{
return $this->sTogglerJSSelector;
}
/**
* @return bool
* @uses static::$sTogglerJSSelector
*/
public function HasToggler(): bool
{
return !empty($this->sTogglerJSSelector);
}
/**
* @return $this
* @uses static::$bAddVisualHintToToggler
*/
public function AddVisualHintToToggler()
{
$this->bAddVisualHintToToggler = true;
return $this;
}
/**
* @return bool
* @uses static::$bAddVisualHintToToggler
*/
public function HasVisualHintToAddToToggler(): bool
{
return $this->bAddVisualHintToToggler;
}
/**
* Add a section $sId if not already existing.
* Important: It does not reset the section.

View File

@@ -0,0 +1,4 @@
$('#{{ oUIBlock.GetId() }}').popover_menu({
toggler: {{ oUIBlock.GetTogglerJSSelector()|json_encode|raw }},
add_visual_hint_to_toggler: {{ oUIBlock.HasVisualHintToAddToToggler()|var_export }}
});