moduleTemplate->getDocHeaderComponent()->getButtonBar(); * $dropDownButton = $this->componentFactory->createDropDownButton() * ->setLabel('Dropdown') * ->setTitle('Save') * ->setIcon($this->iconFactory->getIcon('actions-heart')) * ->setShowLabelText(true) * ->addItem( * $this->componentFactory->createDropDownItem() * ->setLabel('Item') * ->setHref('#') * ); * $buttonBar->addButton($dropDownButton, ButtonBar::BUTTON_POSITION_RIGHT, 2); * } * ``` */ class DropDownButton implements ButtonInterface { protected ?Icon $icon = null; protected string $label = ''; protected ?string $title = null; protected array $items = []; protected bool $showLabelText = false; protected bool $showActiveLabelText = false; protected bool $disabled = false; protected ButtonSize $size = ButtonSize::SMALL; public function getIcon(): ?Icon { return $this->icon; } public function setIcon(?Icon $icon): static { $icon?->setSize(IconSize::SMALL); $this->icon = $icon; return $this; } public function getLabel(): string { return $this->label; } public function setLabel(string $label): static { $this->label = $label; return $this; } public function getTitle(): string { return $this->title ?? $this->label; } public function setTitle(?string $title): static { $this->title = $title; return $this; } public function getShowLabelText(): bool { return $this->showLabelText; } public function setShowLabelText(bool $showLabelText): static { $this->showLabelText = $showLabelText; return $this; } public function getShowActiveLabelText(): bool { return $this->showActiveLabelText; } public function setShowActiveLabelText(bool $showActiveLabelText): static { $this->showActiveLabelText = $showActiveLabelText; return $this; } public function isDisabled(): bool { return $this->disabled; } public function setDisabled(bool $disabled): static { $this->disabled = $disabled; return $this; } public function addItem(DropDownItemInterface $item): static { if (!$item->isValid()) { throw new \InvalidArgumentException( 'Only valid items may be assigned to a DropdownButton. "' . $item->getType() . '" did not pass validation', 1667645426 ); } $this->items[] = clone $item; return $this; } public function getSize(): ButtonSize { return $this->size; } public function setSize(ButtonSize $size): DropDownButton { $this->size = $size; return $this; } /** * @return DropDownItemInterface[] */ public function getItems(): array { return $this->items; } public function isValid(): bool { return !empty($this->getLabel()) && ($this->getShowLabelText() || $this->getIcon()) && !empty($this->getItems()); } public function getType(): string { return static::class; } public function render(): string { $items = $this->getItems(); /** * @var DropDownRadio|null $activeItem */ $activeItem = null; /** * @var DropDownRadio[] $activeItems */ $activeItems = array_filter($items, static function (DropDownItemInterface $item): bool { return $item instanceof DropDownRadio && $item->isActive(); }); if (!empty($activeItems)) { $activeItem = array_shift($activeItems); } $attributes = [ 'type' => 'button', 'class' => 'btn ' . $this->getSize()->value . ' btn-default dropdown-toggle', 'data-bs-toggle' => 'dropdown', 'aria-expanded' => 'false', ]; if ($this->isDisabled()) { $attributes['disabled'] = 'disabled'; } $buttonLabel = ''; if ($this->getShowLabelText()) { if ($activeItem !== null && $this->getShowActiveLabelText()) { // Render label with visually-hidden span for screen readers $buttonLabel = '' . htmlspecialchars($this->getLabel()) . ': ' . htmlspecialchars($activeItem->getLabel()); } else { // No active item or showActiveLabelText is false, just render the label $buttonLabel = htmlspecialchars($this->getLabel()); } } else { // Add aria-label and title for accessibility when label text is not shown // Both serve different purposes: aria-label for screen readers, title for visual tooltip if ($activeItem !== null && $this->getShowActiveLabelText()) { $attributes['aria-label'] = htmlspecialchars($this->getTitle() . ': ' . $activeItem->getLabel()); $attributes['title'] = htmlspecialchars($this->getTitle() . ': ' . $activeItem->getLabel()); } else { $attributes['aria-label'] = $this->getTitle(); $attributes['title'] = $this->getTitle(); } } $icon = $activeItem?->getIcon()?->render() ?? $this->getIcon()?->render() ?? ''; $buttonContent = $icon . ($icon !== '' && $buttonLabel !== '' ? ' ' : '') . $buttonLabel; return sprintf( '
', GeneralUtility::implodeAttributes($attributes, true), $buttonContent, implode('', array_map(static fn(DropDownItemInterface $item) => '
  • ' . $item->render() . '
  • ', $items)) ); } public function __toString(): string { return $this->render(); } }