- ButtonBar block with overflow controller

This commit is contained in:
Benjamin DALSASS
2026-08-26 14:14:47 +02:00
parent c766168d10
commit 4cd0be8ba7
10 changed files with 480 additions and 17 deletions

View File

@@ -5,6 +5,7 @@
@import "alert";
@import "button";
@import "button-bar";
@import "button-separator";
@import "button-group";
@import "breadcrumbs";

View File

@@ -0,0 +1,43 @@
/*
* @copyright Copyright (C) 2010-2024 Combodo SAS
* @license http://opensource.org/licenses/AGPL-3.0
*/
$ibo-button-bar--gap: 2px !default;
$ibo-button-bar--track--gap: 6px !default;
/* button-bar.css */
ibo-button-bar{
display: flex;
flex-wrap: nowrap;
align-items: center;
position: relative;
gap: $ibo-button-bar--gap;
overflow: hidden;
}
/* Keep content visible even if JS initialization is delayed. */
ibo-button-bar .ibo-button-bar--track{
display: flex;
flex: 1 1 auto;
flex-wrap: nowrap;
overflow: hidden;
white-space: nowrap;
gap: $ibo-button-bar--track--gap;
align-items: center;
}
ibo-button-bar .ibo-button-bar--item{
flex: 0 0 auto;
white-space: nowrap;
}
ibo-button-bar .ibo-button-bar--item[hidden]{
display: none !important;
}
ibo-button-bar .ibo-button-bar--extra{
flex: 0 0 auto;
position: relative;
}

View File

@@ -61,6 +61,7 @@ $ibo-caselog-entry-form--lock-message--margin-left: 1rem !default;
z-index: 1;
}
.ibo-caselog-entry-form--action-buttons--extra-actions .ibo-button-separator{
vertical-align: center ;
.ibo-caselog-entry-form--action-buttons--extra-actions{
overflow: hidden;
flex-grow: 1;
}

217
js/components/button-bar.js Normal file
View File

@@ -0,0 +1,217 @@
/*
* Copyright (C) 2013-2024 Combodo SAS
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*/
class ButtonBar extends HTMLElement {
constructor() {
super();
// Guard against duplicate setup if the node is re-attached.
this._initialized = false;
// Retry counter for delayed jQuery plugin availability.
this._popoverInitAttempts = 0;
// Recompute distribution on resize.
this._onResize = this.refresh.bind(this);
}
connectedCallback() {
if (this._initialized) {
return;
}
this._initialized = true;
// Core DOM references rendered by the Twig template.
this._track = this.querySelector('[data-role="ibo-button-bar--track"]') || this.querySelector('[data-role="ibo-overflow-line--track"]');
this._extra = this.querySelector('[data-role="ibo-button-bar--extra"]') || this.querySelector('[data-role="ibo-overflow-line--extra"]');
this._popover = this.querySelector('[data-role="ibo-popover-menu"]');
// Toggler id is deterministic: <overflow-id>--toggler.
const sTogglerId = `${this.id}--toggler`;
const oToggler = document.getElementById(sTogglerId);
this._toggler = oToggler && this.contains(oToggler) ? oToggler : null;
if (!this._track || !this._extra || !this._popover || !this._toggler) {
return;
}
this._bindEvents();
if (window.ResizeObserver) {
this._resizeObserver = new ResizeObserver(this._onResize);
this._resizeObserver.observe(this);
this._resizeObserver.observe(this._track);
} else {
window.addEventListener("resize", this._onResize);
}
// Observe both source actions and popover entries (both can be updated dynamically).
this._mutationObserver = new MutationObserver(() => this.refresh());
this._mutationObserver.observe(this._track, { childList: true, subtree: true, characterData: true });
this._mutationObserver.observe(this._popover, { childList: true, subtree: true });
this.refresh();
}
disconnectedCallback() {
this._resizeObserver?.disconnect();
this._mutationObserver?.disconnect();
if (this._popoverInitTimer) {
clearTimeout(this._popoverInitTimer);
}
this._popover?.removeEventListener("click", this._onPopoverClick);
window.removeEventListener("resize", this._onResize);
}
_bindEvents() {
this._onPopoverClick = (event) => {
// Popover entries map to source actions through data-overflow-item-id.
const oMenuItem = event.target.closest('[data-role="ibo-popover-menu--item"][data-overflow-item-id]');
if (!oMenuItem) {
return;
}
event.preventDefault();
const sItemId = oMenuItem.dataset.overflowItemId;
const oSource = this._itemsById[sItemId];
if (!oSource) {
return;
}
// Forward click to the original UI action.
const oClickable = oSource.querySelector('a[href], button, [role="tab"], [data-role="ibo-tab-container--tab-toggler"]');
(oClickable || oSource).click();
};
this._popover.addEventListener("click", this._onPopoverClick);
}
_refreshCollections() {
// Source actions are direct children of the track.
this._items = Array.from(this._track.children).filter((oItem) => Boolean(oItem.dataset.overflowItemId));
this._itemsById = {};
this._items.forEach((oItem) => {
if (oItem.dataset.overflowItemId) {
this._itemsById[oItem.dataset.overflowItemId] = oItem;
}
});
// Popover entries are generated server-side with the same mapping id.
this._menuItems = Array.from(this._popover.querySelectorAll('[data-role="ibo-popover-menu--item"][data-overflow-item-id]'));
this._menuItemsById = {};
this._menuItems.forEach((oItem) => {
this._menuItemsById[oItem.dataset.overflowItemId] = oItem;
});
}
_outerWidth(oElem) {
const oRect = oElem.getBoundingClientRect();
const oStyle = getComputedStyle(oElem);
return oRect.width + (parseFloat(oStyle.marginLeft) || 0) + (parseFloat(oStyle.marginRight) || 0);
}
_flexGap(oElem) {
const oStyle = getComputedStyle(oElem);
const iGap = parseFloat(oStyle.columnGap);
return Number.isFinite(iGap) ? iGap : 0;
}
_closePopoverIfOpen() {
if (window.jQuery && window.jQuery(this._popover).data("itop-popover_menu")) {
window.jQuery(this._popover).popover_menu("closePopup");
}
}
refresh() {
this._refreshCollections();
this.layout();
}
layout() {
if (!this._items || this._items.length === 0) {
this._extra.hidden = true;
return;
}
// 1) Reset visibility before computing overflow.
this._items.forEach((oItem) => {
oItem.hidden = false;
});
this._menuItems.forEach((oItem) => {
oItem.hidden = true;
});
// 2) No mapping => keep source actions visible and hide overflow controls.
if (this._menuItems.length === 0) {
this._extra.hidden = true;
this._closePopoverIfOpen();
return;
}
const iHostWidth = this.clientWidth;
if (iHostWidth <= 0) {
return;
}
const aWidths = this._items.map((oItem) => this._outerWidth(oItem));
const iTrackGap = this._flexGap(this._track);
const iTotalWidth = aWidths.reduce((iSum, iWidth) => iSum + iWidth, 0) + Math.max(0, this._items.length - 1) * iTrackGap;
// 3) Everything fits: hide the overflow button.
if (iTotalWidth <= iHostWidth) {
this._extra.hidden = true;
this._closePopoverIfOpen();
return;
}
this._extra.hidden = false;
// 4) Keep items while there is space, move overflowing ones to popover.
const iHostGap = this._flexGap(this);
const iAvailableWidth = Math.max(0, iHostWidth - this._outerWidth(this._extra) - iHostGap);
let iUsedWidth = 0;
let bHasHiddenItems = false;
let bOverflowStarted = false;
for (let i = 0; i < this._items.length; i++) {
const oItem = this._items[i];
const iWidth = aWidths[i];
const iGapBeforeItem = i > 0 ? iTrackGap : 0;
if (!bOverflowStarted && iUsedWidth + iGapBeforeItem + iWidth <= iAvailableWidth) {
iUsedWidth += iGapBeforeItem + iWidth;
continue;
}
bOverflowStarted = true;
oItem.hidden = true;
const sItemId = oItem.dataset.overflowItemId;
const oMenuItem = sItemId ? this._menuItemsById[sItemId] : null;
if (!oMenuItem) {
continue;
}
oMenuItem.hidden = false;
bHasHiddenItems = true;
}
this._extra.hidden = !bHasHiddenItems;
if (!bHasHiddenItems) {
this._closePopoverIfOpen();
}
}
}
if (!customElements.get("ibo-button-bar")) {
customElements.define("ibo-button-bar", ButtonBar);
}

View File

@@ -165,6 +165,8 @@ return array(
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Badge\\Badge' => $baseDir . '/sources/Application/UI/Base/Component/Badge/Badge.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Badge\\BadgeUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Badge/BadgeUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Breadcrumbs\\Breadcrumbs' => $baseDir . '/sources/Application/UI/Base/Component/Breadcrumbs/Breadcrumbs.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\ButtonBar\\ButtonBar' => $baseDir . '/sources/Application/UI/Base/Component/ButtonBar/ButtonBar.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\ButtonBar\\ButtonBarUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/ButtonBar/ButtonBarUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\ButtonGroup\\ButtonGroup' => $baseDir . '/sources/Application/UI/Base/Component/ButtonGroup/ButtonGroup.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\ButtonGroup\\ButtonGroupUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/ButtonGroup/ButtonGroupUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Button\\Button' => $baseDir . '/sources/Application/UI/Base/Component/Button/Button.php',
@@ -223,6 +225,8 @@ return array(
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\tInputLabel' => $baseDir . '/sources/Application/UI/Base/Component/Input/tInputLabel.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\MedallionIcon\\MedallionIcon' => $baseDir . '/sources/Application/UI/Base/Component/MedallionIcon/MedallionIcon.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Modal\\DoNotShowAgainOptionBlock' => $baseDir . '/sources/Application/UI/Base/Component/Modal/DoNotShowAgainOptionBlock.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\OverflowLine\\OverflowLine' => $baseDir . '/sources/Application/UI/Base/Component/OverflowLine/OverflowLine.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\OverflowLine\\OverflowLineUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/OverflowLine/OverflowLineUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Panel\\Panel' => $baseDir . '/sources/Application/UI/Base/Component/Panel/Panel.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Panel\\PanelUIBlockFactory' => $baseDir . '/sources/Application/UI/Base/Component/Panel/PanelUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Pill\\Pill' => $baseDir . '/sources/Application/UI/Base/Component/Pill/Pill.php',
@@ -4024,5 +4028,5 @@ return array(
'privUITransactionFile' => $baseDir . '/application/transaction.class.inc.php',
'privUITransactionSession' => $baseDir . '/application/transaction.class.inc.php',
'utils' => $baseDir . '/application/utils.inc.php',
'©' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php',
'<EFBFBD>' => $vendorDir . '/symfony/cache/Traits/ValueWrapper.php',
);

View File

@@ -566,6 +566,8 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Badge\\Badge' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Badge/Badge.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Badge\\BadgeUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Badge/BadgeUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Breadcrumbs\\Breadcrumbs' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Breadcrumbs/Breadcrumbs.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\ButtonBar\\ButtonBar' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/ButtonBar/ButtonBar.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\ButtonBar\\ButtonBarUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/ButtonBar/ButtonBarUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\ButtonGroup\\ButtonGroup' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/ButtonGroup/ButtonGroup.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\ButtonGroup\\ButtonGroupUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/ButtonGroup/ButtonGroupUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Button\\Button' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Button/Button.php',
@@ -624,6 +626,8 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Input\\tInputLabel' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Input/tInputLabel.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\MedallionIcon\\MedallionIcon' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/MedallionIcon/MedallionIcon.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Modal\\DoNotShowAgainOptionBlock' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Modal/DoNotShowAgainOptionBlock.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\OverflowLine\\OverflowLine' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/OverflowLine/OverflowLine.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\OverflowLine\\OverflowLineUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/OverflowLine/OverflowLineUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Panel\\Panel' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Panel/Panel.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Panel\\PanelUIBlockFactory' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Panel/PanelUIBlockFactory.php',
'Combodo\\iTop\\Application\\UI\\Base\\Component\\Pill\\Pill' => __DIR__ . '/../..' . '/sources/Application/UI/Base/Component/Pill/Pill.php',
@@ -4425,7 +4429,7 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685
'privUITransactionFile' => __DIR__ . '/../..' . '/application/transaction.class.inc.php',
'privUITransactionSession' => __DIR__ . '/../..' . '/application/transaction.class.inc.php',
'utils' => __DIR__ . '/../..' . '/application/utils.inc.php',
'©' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php',
'<EFBFBD>' => __DIR__ . '/..' . '/symfony/cache/Traits/ValueWrapper.php',
);
public static function getInitializer(ClassLoader $loader)

View File

@@ -21,6 +21,10 @@
namespace Combodo\iTop\Application\UI\Base\Component\PopoverMenu\PopoverMenuItem;
use ApplicationPopupMenuItem;
use Combodo\iTop\Application\UI\Base\Component\Button\Button;
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonJS;
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonSeparator;
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonURL;
use JSPopupMenuItem;
use SeparatorPopupMenuItem;
use URLPopupMenuItem;
@@ -128,6 +132,35 @@ class PopoverMenuItemFactory
return $oPopoverMenuItem;
}
public static function MakeApplicationPopupMenuItemFromButton(Button|ButtonSeparator $oButton, string $sUid): PopoverMenuItem|SeparatorPopupMenuItem
{
if ($oButton instanceof ButtonSeparator) {
$oPopoverMenuItem = PopoverMenuItemFactory::MakeSeparator();
} elseif ($oButton instanceof ButtonURL) {
$oPopoverMenuItem = PopoverMenuItemFactory::MakeFromApplicationPopupMenuItem(
new URLPopupMenuItem($sUid, $oButton->GetLabel(), $oButton->GetURL(), $oButton->GetTarget())
);
} elseif ($oButton instanceof ButtonJS) {
$oPopoverMenuItem = PopoverMenuItemFactory::MakeFromApplicationPopupMenuItem(
new JSPopupMenuItem($sUid, $oButton->GetLabel(), $oButton->GetOnClickJsCode())
);
} else {
$oPopoverMenuItem = PopoverMenuItemFactory::MakeFromApplicationPopupMenuItem(
new URLPopupMenuItem($sUid, $oButton->GetLabel(), '#')
);
}
if ($oButton instanceof Button) {
if ($oButton->GetIconClass() !== '') {
$oPopoverMenuItem->SetIconClass($oButton->GetIconClass());
}
if ($oButton->GetTooltip() !== '') {
$oPopoverMenuItem->SetTooltip($oButton->GetTooltip());
}
}
return $oPopoverMenuItem;
}
/**
* Make a separator item for the popover menu
*

View File

@@ -9,6 +9,9 @@ namespace Combodo\iTop\Application\UI\Base\Layout\ActivityPanel\CaseLogEntryForm
use AttributeCaseLog;
use cmdbAbstractObject;
use Combodo\iTop\Application\UI\Base\Component\Button\Button;
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonSeparator;
use Combodo\iTop\Application\UI\Base\Component\ButtonBar\ButtonBar;
use Combodo\iTop\Application\UI\Base\Component\Input\RichText\RichText;
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlock;
use Combodo\iTop\Application\UI\Base\UIBlock;
@@ -53,8 +56,8 @@ class CaseLogEntryForm extends UIContentBlock
protected $oTextInput;
/** @var array $aMainActionButtons The form main actions (send, cancel, ...) */
protected $aMainActionButtons;
/** @var array $aExtraActionButtons The form extra actions, can be populated through a public API */
protected $aExtraActionButtons;
/** @var ButtonBar $oExtraActionButtonBar Extra actions button bar */
protected ButtonBar $oExtraActionButtonBar;
/**
* CaseLogEntryForm constructor.
@@ -69,8 +72,8 @@ class CaseLogEntryForm extends UIContentBlock
$this->sAttCode = $sAttCode;
$this->sSubmitMode = static::DEFAULT_SUBMIT_MODE;
$this->aMainActionButtons = [];
$this->aExtraActionButtons = [];
$this->InitTextInput();
$this->InitExtraActionButtonBar();
}
/**
@@ -273,12 +276,27 @@ class CaseLogEntryForm extends UIContentBlock
return $this;
}
/**
* @return void
*/
protected function InitExtraActionButtonBar(): void
{
$this->oExtraActionButtonBar = new ButtonBar();
}
/**
* @return ButtonBar
*/
public function GetExtraActionButtonBar(): ButtonBar
{
return $this->oExtraActionButtonBar;
}
/**
* @return \Combodo\iTop\Application\UI\Base\UIBlock[]
*/
public function GetExtraActionButtons(): array
{
return $this->aExtraActionButtons;
return $this->oExtraActionButtonBar->GetButtons();
}
/**
@@ -291,7 +309,7 @@ class CaseLogEntryForm extends UIContentBlock
*/
public function SetExtraActionButtons(array $aExtraActionButtons)
{
$this->aExtraActionButtons = $aExtraActionButtons;
$this->oExtraActionButtonBar->SetButtons($aExtraActionButtons);
return $this;
}
@@ -302,9 +320,12 @@ class CaseLogEntryForm extends UIContentBlock
* @see $aExtraActionButtons
*
*/
public function AddExtraActionButtons(UIBlock $oExtraActionButton)
public function AddExtraActionButtons(UIBlock $oExtraActionButton): self
{
$this->aExtraActionButtons[] = $oExtraActionButton;
if (!($oExtraActionButton instanceof Button) && !($oExtraActionButton instanceof ButtonSeparator)) {
throw new \InvalidArgumentException('Extra action buttons must be either a Button or a ButtonSeparator');
}
$this->oExtraActionButtonBar->AddButton($oExtraActionButton);
return $this;
}
@@ -316,9 +337,7 @@ class CaseLogEntryForm extends UIContentBlock
$aSubBlocks = [];
$aSubBlocks[$this->GetTextInput()->GetId()] = $this->GetTextInput();
foreach ($this->GetExtraActionButtons() as $oExtraActionButton) {
$aSubBlocks[$oExtraActionButton->GetId()] = $oExtraActionButton;
}
$aSubBlocks[$this->GetExtraActionButtonBar()->GetId()] = $this->GetExtraActionButtonBar();
foreach ($this->GetMainActionButtons() as $oMainActionButton) {
$aSubBlocks[$oMainActionButton->GetId()] = $oMainActionButton;

View File

@@ -14,9 +14,7 @@
<div class="ibo-caselog-entry-form--actions">
<div class="ibo-caselog-entry-form--action-buttons--extra-actions"
data-role="ibo-caselog-entry-form--action-buttons--extra-actions">
{% for TextInputActionButton in oUIBlock.GetExtraActionButtons() %}
{{ render_block(TextInputActionButton, {aPage: aPage}) }}
{% endfor %}
{{ render_block(oUIBlock.GetExtraActionButtonBar(), {aPage: aPage}) }}
</div>
<div class="ibo-caselog-entry-form--action-buttons--main-actions" data-role="ibo-caselog-entry-form--action-buttons--main-actions">
{% for FormActionButton in oUIBlock.GetMainActionButtons() %}

View File

@@ -27,7 +27,9 @@ use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Badge\Badge;
use Combodo\iTop\Application\UI\Base\Component\Badge\BadgeUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Button\Button;
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonSeparator;
use Combodo\iTop\Application\UI\Base\Component\Button\ButtonUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\ButtonBar\ButtonBarUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\ButtonGroup\ButtonGroup;
use Combodo\iTop\Application\UI\Base\Component\ButtonGroup\ButtonGroupUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\CollapsibleSection\CollapsibleSection;
@@ -35,6 +37,7 @@ use Combodo\iTop\Application\UI\Base\Component\DataTable\DataTableUIBlockFactory
use Combodo\iTop\Application\UI\Base\Component\Field\FieldUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSet;
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
use Combodo\iTop\Application\UI\Base\Component\Html\HtmlFactory;
use Combodo\iTop\Application\UI\Base\Component\Input\InputUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Input\Set\SetUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Input\Toggler;
@@ -71,6 +74,12 @@ $oPage->add_style(
hr {
background-color: var(--ibo-color-grey-950);
}
.btn-bar-600{
max-width: 600px;
}
.btn-bar-600{
max-width: 800px;
}
CSS
);
@@ -215,6 +224,140 @@ $oPageContentLayout->AddMainBlock(new ButtonGroup(
$oPageContentLayout->AddMainBlock(new Html('<hr/>'));
//////////////
// ButtonBar
//////////////
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('ButtonBar example', 2, 'title-button-bar'));
$oPage->AddUiBlock(HtmlFactory::MakeParagraph('The button bar is a horizontal list of buttons, with an overflow menu for the buttons that do not fit in the available space. The overflow menu is a popover menu that can be opened by clicking on the "..." button. The overflow menu can contain any number of buttons, and can be used to group related actions together.'));
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Full page', 3, 'title-button-bar1'));
$oBtn1 = ButtonUIBlockFactory::MakeNeutral('Action 1');
$oBtn1->SetIconClass('fas fa-thumbs-up');
$oBtn5 = ButtonUIBlockFactory::MakeNeutral('Action 5');
$oBtn5->SetIconClass('fas fa-thumbs-down');
$oBtn11 = ButtonUIBlockFactory::MakeNeutral('Action 11');
$oBtn11->SetIconClass('fas fa-bomb');
$oButtonBar = ButtonBarUIBlockFactory::MakeStandard(
[
$oBtn1,
ButtonUIBlockFactory::MakeNeutral('Action 2'),
ButtonUIBlockFactory::MakeNeutral('Action 3'),
ButtonUIBlockFactory::MakeNeutral('Action 4'),
new ButtonSeparator(),
$oBtn5,
ButtonUIBlockFactory::MakeNeutral('Action 6'),
ButtonUIBlockFactory::MakeNeutral('Action 7'),
ButtonUIBlockFactory::MakeNeutral('Action 8'),
ButtonUIBlockFactory::MakeNeutral('Action 9'),
ButtonUIBlockFactory::MakeNeutral('Action 10'),
new ButtonSeparator(),
$oBtn11,
ButtonUIBlockFactory::MakeNeutral('Action 12'),
ButtonUIBlockFactory::MakeNeutral('Action 13'),
ButtonUIBlockFactory::MakeNeutral('Action 14'),
ButtonUIBlockFactory::MakeNeutral('Action 15'),
ButtonUIBlockFactory::MakeNeutral('Action 16'),
],
'See overflow actions',
'button-bar-test1'
);
$oPageContentLayout->AddMainBlock($oButtonBar);
$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Max width 600px', 3, 'title-button-bar2'));
$oBtn1 = ButtonUIBlockFactory::MakeNeutral('Action 1');
$oBtn1->SetIconClass('fas fa-thumbs-up');
$oBtn5 = ButtonUIBlockFactory::MakeNeutral('Action 5');
$oBtn5->SetIconClass('fas fa-thumbs-down');
$oBtn11 = ButtonUIBlockFactory::MakeNeutral('Action 11');
$oBtn11->SetIconClass('fas fa-bomb');
$oButtonBar = ButtonBarUIBlockFactory::MakeStandard(
[
$oBtn1,
ButtonUIBlockFactory::MakeNeutral('Action 2'),
ButtonUIBlockFactory::MakeNeutral('Action 3'),
ButtonUIBlockFactory::MakeNeutral('Action 4'),
new ButtonSeparator(),
$oBtn5,
ButtonUIBlockFactory::MakeNeutral('Action 6'),
ButtonUIBlockFactory::MakeNeutral('Action 7'),
ButtonUIBlockFactory::MakeNeutral('Action 8'),
ButtonUIBlockFactory::MakeNeutral('Action 9'),
ButtonUIBlockFactory::MakeNeutral('Action 10'),
new ButtonSeparator(),
$oBtn11,
ButtonUIBlockFactory::MakeNeutral('Action 12'),
ButtonUIBlockFactory::MakeNeutral('Action 13'),
ButtonUIBlockFactory::MakeNeutral('Action 14'),
ButtonUIBlockFactory::MakeNeutral('Action 15'),
ButtonUIBlockFactory::MakeNeutral('Action 16'),
],
null,
'button-bar-test2'
);
$oButtonBar->AddCSSClass('btn-bar-600');
$oPageContentLayout->AddMainBlock($oButtonBar);
//$oPage->AddUiBlock(TitleUIBlockFactory::MakeNeutral('Max width 800px', 3, 'title-button-bar3'));
//
//$oBtn1 = ButtonUIBlockFactory::MakeNeutral('Action 1');
//$oBtn1->SetIconClass('fas fa-thumbs-up');
//
//$oBtn5 = ButtonUIBlockFactory::MakeNeutral('Action 5');
//$oBtn5->SetIconClass('fas fa-thumbs-down');
//
//$oBtn11 = ButtonUIBlockFactory::MakeNeutral('Action 11');
//$oBtn11->SetIconClass('fas fa-bomb');
//
//$oButtonBar = ButtonBarUIBlockFactory::MakeStandard(
// [
// $oBtn1,
// ButtonUIBlockFactory::MakeNeutral('Action 2'),
// ButtonUIBlockFactory::MakeNeutral('Action 3'),
// ButtonUIBlockFactory::MakeNeutral('Action 4'),
// ButtonGroupUIBlockFactory::MakeButtonWithOptionsMenu(
// ButtonUIBlockFactory::MakeForPositiveAction('Validation with options'),
// new PopoverMenu()
// ),
// new ButtonSeparator(),
// $oBtn5,
// ButtonUIBlockFactory::MakeNeutral('Action 6'),
// ButtonUIBlockFactory::MakeNeutral('Action 7'),
// ButtonUIBlockFactory::MakeNeutral('Action 8'),
// ButtonUIBlockFactory::MakeNeutral('Action 9'),
// ButtonUIBlockFactory::MakeNeutral('Action 10'),
// ButtonGroupUIBlockFactory::MakeButtonWithOptionsMenu(
// ButtonUIBlockFactory::MakeForPositiveAction('Validation with options'),
// new PopoverMenu()
// ),
// new ButtonSeparator(),
// $oBtn11,
// ButtonUIBlockFactory::MakeNeutral('Action 12'),
// ButtonUIBlockFactory::MakeNeutral('Action 13'),
// ButtonUIBlockFactory::MakeNeutral('Action 14'),
// ButtonUIBlockFactory::MakeNeutral('Action 15'),
// ButtonUIBlockFactory::MakeNeutral('Action 16'),
// ButtonGroupUIBlockFactory::MakeButtonWithOptionsMenu(
// ButtonUIBlockFactory::MakeForPositiveAction('Validation with options'),
// new PopoverMenu()
// ),
// ],
// null,
// 'button-bar-test3'
//);
$oButtonBar->AddCSSClass('btn-bar-800');
$oPageContentLayout->AddMainBlock($oButtonBar);
$oPageContentLayout->AddMainBlock(new Html('<hr/>'));
/////////
// Panels
/////////