diff --git a/src/Accordion.php b/src/Accordion.php
index 53dd283..0b6f540 100644
--- a/src/Accordion.php
+++ b/src/Accordion.php
@@ -150,7 +150,7 @@ class Accordion extends Widget
}
$header = ArrayHelper::remove($item, 'label');
$options = ArrayHelper::getValue($item, 'options', []);
- Html::addCssClass($options, ['panel' => 'card']);
+ Html::addCssClass($options, ['panel' => 'accordion-item']);
$items[] = Html::tag('div', $this->renderItem($header, $item, $index++), $options);
}
@@ -192,18 +192,22 @@ class Accordion extends Widget
$itemToggleOptions = array_merge([
'tag' => 'button',
'type' => 'button',
- 'data-toggle' => 'collapse',
- 'data-target' => '#' . $options['id'],
- 'aria-expanded' => $expand ? 'true' : 'false',
- 'aria-controls' => $options['id'],
+ 'data' => [
+ 'bs-toggle' => 'collapse',
+ 'bs-target' => '#' . $options['id']
+ ],
+ 'aria' => [
+ 'expanded' => $expand ? 'true' : 'false',
+ 'controls' => $options['id']
+ ]
], $this->itemToggleOptions);
$itemToggleTag = ArrayHelper::remove($itemToggleOptions, 'tag', 'button');
if ($itemToggleTag === 'a') {
- ArrayHelper::remove($itemToggleOptions, 'data-target');
+ ArrayHelper::remove($itemToggleOptions, 'data.bs-target');
$headerToggle = Html::a($header, '#' . $id, $itemToggleOptions) . "\n";
} else {
- Html::addCssClass($itemToggleOptions, ['feature' => 'btn-link']);
+ Html::addCssClass($itemToggleOptions, ['widget' => 'accordion-button']);
$headerToggle = Button::widget([
'label' => $header,
'encodeLabel' => false,
@@ -214,7 +218,7 @@ class Accordion extends Widget
$header = Html::tag('h5', $headerToggle, ['class' => 'mb-0']);
if (is_string($item['content']) || is_numeric($item['content']) || is_object($item['content'])) {
- $content = Html::tag('div', $item['content'], ['class' => 'card-body']) . "\n";
+ $content = Html::tag('div', $item['content'], ['class' => 'accordion-body']) . "\n";
} elseif (is_array($item['content'])) {
$content = Html::ul($item['content'], [
'class' => 'list-group',
@@ -232,14 +236,14 @@ class Accordion extends Widget
$group = [];
if ($this->autoCloseItems) {
- $options['data-parent'] = '#' . $this->options['id'];
+ $options['data']['bs-parent'] = '#' . $this->options['id'];
}
- $group[] = Html::tag('div', $header, ['class' => 'card-header', 'id' => $options['id'] . '-heading']);
+ $group[] = Html::tag('div', $header, ['class' => 'accordion-header', 'id' => $options['id'] . '-heading']);
$group[] = Html::beginTag('div', $options);
$group[] = $content;
if (isset($item['footer'])) {
- $group[] = Html::tag('div', $item['footer'], ['class' => 'card-footer']);
+ $group[] = Html::tag('div', $item['footer'], ['class' => 'accordion-footer']);
}
$group[] = Html::endTag('div');
diff --git a/src/ActiveField.php b/src/ActiveField.php
index a71bd1b..673c75a 100644
--- a/src/ActiveField.php
+++ b/src/ActiveField.php
@@ -105,7 +105,7 @@ class ActiveField extends \yii\widgets\ActiveField
/**
* {@inheritdoc}
*/
- public $options = ['class' => ['widget' => 'form-group']];
+ public $options = ['class' => ['widget' => 'mb-3']];
/**
* {@inheritdoc}
*/
@@ -120,9 +120,9 @@ class ActiveField extends \yii\widgets\ActiveField
* @since 2.0.7
*/
public array $checkOptions = [
- 'class' => ['widget' => 'custom-control-input'],
+ 'class' => ['widget' => 'form-check-input'],
'labelOptions' => [
- 'class' => ['widget' => 'custom-control-label'],
+ 'class' => ['widget' => 'form-check-label'],
],
];
/**
@@ -135,9 +135,9 @@ class ActiveField extends \yii\widgets\ActiveField
* @since 2.0.7
*/
public array $radioOptions = [
- 'class' => ['widget' => 'custom-control-input'],
+ 'class' => ['widget' => 'form-check-input'],
'labelOptions' => [
- 'class' => ['widget' => 'custom-control-label'],
+ 'class' => ['widget' => 'form-check-label'],
],
];
/**
@@ -147,7 +147,7 @@ class ActiveField extends \yii\widgets\ActiveField
/**
* {@inheritdoc}
*/
- public $labelOptions = [];
+ public $labelOptions = ['class' => ['widget' => 'form-label']];
/**
* {@inheritdoc}
*/
@@ -164,21 +164,21 @@ class ActiveField extends \yii\widgets\ActiveField
/**
* @var string the template for checkboxes in default layout
*/
- public string $checkTemplate = "
\n{input}\n{label}\n{error}\n{hint}\n
";
+ public string $checkTemplate = "\n{input}\n{label}\n{error}\n{hint}\n
";
/**
* @var string the template for radios in default layout
* @since 2.0.5
*/
- public string $radioTemplate = "\n{input}\n{label}\n{error}\n{hint}\n
";
+ public string $radioTemplate = "\n{input}\n{label}\n{error}\n{hint}\n
";
/**
* @var string the template for checkboxes and radios in horizontal layout
*/
- public string $checkHorizontalTemplate = "{beginWrapper}\n\n{input}\n{label}\n{error}\n{hint}\n
\n{endWrapper}";
+ public string $checkHorizontalTemplate = "{beginWrapper}\n\n{input}\n{label}\n{error}\n{hint}\n
\n{endWrapper}";
/**
* @var string the template for checkboxes and radios in horizontal layout
* @since 2.0.5
*/
- public string $radioHorizontalTemplate = "{beginWrapper}\n\n{input}\n{label}\n{error}\n{hint}\n
\n{endWrapper}";
+ public string $radioHorizontalTemplate = "{beginWrapper}\n\n{input}\n{label}\n{error}\n{hint}\n
\n{endWrapper}";
/**
* @var string the `enclosed by label` template for checkboxes and radios in default layout
*/
@@ -248,9 +248,9 @@ class ActiveField extends \yii\widgets\ActiveField
{
$checkOptions = $this->checkOptions;
$options = ArrayHelper::merge($checkOptions, $options);
- Html::removeCssClass($options, 'form-control');
$labelOptions = ArrayHelper::remove($options, 'labelOptions', []);
$wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', []);
+ Html::removeCssClass($options, 'form-control');
$this->labelOptions = ArrayHelper::merge($this->labelOptions, $labelOptions);
$this->wrapperOptions = ArrayHelper::merge($this->wrapperOptions, $wrapperOptions);
@@ -266,6 +266,7 @@ class ActiveField extends \yii\widgets\ActiveField
Html::removeCssClass($this->labelOptions, $this->horizontalCssClasses['label']);
Html::addCssClass($this->wrapperOptions, $this->horizontalCssClasses['offset']);
}
+ Html::removeCssClass($this->labelOptions, 'form-label');
unset($options['template']);
if ($enclosedByLabel) {
@@ -284,9 +285,9 @@ class ActiveField extends \yii\widgets\ActiveField
{
$checkOptions = $this->radioOptions;
$options = ArrayHelper::merge($checkOptions, $options);
- Html::removeCssClass($options, 'form-control');
$labelOptions = ArrayHelper::remove($options, 'labelOptions', []);
$wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', []);
+ Html::removeCssClass($options, 'form-control');
$this->labelOptions = ArrayHelper::merge($this->labelOptions, $labelOptions);
$this->wrapperOptions = ArrayHelper::merge($this->wrapperOptions, $wrapperOptions);
@@ -302,6 +303,7 @@ class ActiveField extends \yii\widgets\ActiveField
Html::removeCssClass($this->labelOptions, $this->horizontalCssClasses['label']);
Html::addCssClass($this->wrapperOptions, $this->horizontalCssClasses['offset']);
}
+ Html::removeCssClass($this->labelOptions, 'form-label');
unset($options['template']);
if ($enclosedByLabel && isset($options['label'])) {
@@ -332,10 +334,10 @@ class ActiveField extends \yii\widgets\ActiveField
'label' => $encode ? Html::encode($label) : $label,
'value' => $value,
], $itemOptions);
- $wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', ['class' => ['custom-control', 'custom-checkbox']]);
- if ($this->inline) {
- Html::addCssClass($wrapperOptions, 'custom-control-inline');
- }
+ $wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', ['class' => ['form-check']]);
+// if ($this->inline) {
+// Html::addCssClass($wrapperOptions, 'custom-control-inline');
+// }
$html = Html::beginTag('div', $wrapperOptions) . "\n" .
Html::checkbox($name, $checked, $options) . "\n";
@@ -373,10 +375,10 @@ class ActiveField extends \yii\widgets\ActiveField
'label' => $encode ? Html::encode($label) : $label,
'value' => $value,
], $itemOptions);
- $wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', ['class' => ['custom-control', 'custom-radio']]);
- if ($this->inline) {
- Html::addCssClass($wrapperOptions, 'custom-control-inline');
- }
+ $wrapperOptions = ArrayHelper::remove($options, 'wrapperOptions', ['class' => ['form-check']]);
+// if ($this->inline) {
+// Html::addCssClass($wrapperOptions, 'custom-control-inline');
+// }
$html = Html::beginTag('div', $wrapperOptions) . "\n" .
Html::radio($name, $checked, $options) . "\n";
@@ -399,7 +401,7 @@ class ActiveField extends \yii\widgets\ActiveField
public function listBox($items, $options = [])
{
if ($this->form->layout === ActiveForm::LAYOUT_INLINE) {
- Html::removeCssClass($this->labelOptions, 'sr-only');
+ Html::removeCssClass($this->labelOptions, 'visually-hidden');
}
return parent::listBox($items, $options);
@@ -411,7 +413,7 @@ class ActiveField extends \yii\widgets\ActiveField
public function dropdownList($items, $options = [])
{
if ($this->form->layout === ActiveForm::LAYOUT_INLINE) {
- Html::removeCssClass($this->labelOptions, 'sr-only');
+ Html::removeCssClass($this->labelOptions, 'visually-hidden');
}
return parent::dropdownList($items, $options);
@@ -482,7 +484,7 @@ class ActiveField extends \yii\widgets\ActiveField
'class' => 'form-control',
],
'labelOptions' => [
- 'class' => [],
+ 'class' => ['form-label'],
],
];
@@ -499,7 +501,7 @@ class ActiveField extends \yii\widgets\ActiveField
'wrapper' => 'col-sm-10',
'error' => '',
'hint' => '',
- 'field' => 'form-group row',
+ 'field' => 'mb-3 row',
];
if (isset($instanceConfig['horizontalCssClasses'])) {
$cssClasses = ArrayHelper::merge($cssClasses, $instanceConfig['horizontalCssClasses']);
@@ -515,7 +517,7 @@ class ActiveField extends \yii\widgets\ActiveField
$config['inputOptions']['placeholder'] = true;
$config['enableError'] = false;
- Html::addCssClass($config['labelOptions'], ['screenreader' => 'sr-only']);
+ Html::addCssClass($config['labelOptions'], ['screenreader' => 'visually-hidden']);
}
return $config;
@@ -526,7 +528,7 @@ class ActiveField extends \yii\widgets\ActiveField
*/
public function fileInput($options = [])
{
- Html::addCssClass($options, ['widget' => 'form-control-file']);
+ Html::addCssClass($options, ['widget' => 'form-control']);
return parent::fileInput($options);
}
diff --git a/src/ActiveForm.php b/src/ActiveForm.php
index e4dab11..c651241 100644
--- a/src/ActiveForm.php
+++ b/src/ActiveForm.php
@@ -72,6 +72,10 @@ class ActiveForm extends \yii\widgets\ActiveForm
* Inline form layout
*/
const LAYOUT_INLINE = 'inline';
+ /**
+ * Floating labels form layout
+ */
+ const LAYOUT_FLOATING = 'floating';
/**
* @var string the default field class name when calling [[field()]] to create a new field.
@@ -114,7 +118,7 @@ class ActiveForm extends \yii\widgets\ActiveForm
*/
public function init()
{
- if (!in_array($this->layout, [self::LAYOUT_DEFAULT, self::LAYOUT_HORIZONTAL, self::LAYOUT_INLINE])) {
+ if (!in_array($this->layout, [self::LAYOUT_DEFAULT, self::LAYOUT_HORIZONTAL, self::LAYOUT_INLINE, self::LAYOUT_FLOATING])) {
throw new InvalidConfigException('Invalid layout type: ' . $this->layout);
}
@@ -125,9 +129,10 @@ class ActiveForm extends \yii\widgets\ActiveForm
}
/**
- * @inheritdoc
+ * {@inheritDoc}
+ * @return ActiveField|\yii\widgets\ActiveField
*/
- public function field($model, $attribute, $options = []): \yii\widgets\ActiveField
+ public function field($model, $attribute, $options = []): ActiveField
{
return parent::field($model, $attribute, $options);
}
diff --git a/src/Alert.php b/src/Alert.php
index 9549470..442bce6 100644
--- a/src/Alert.php
+++ b/src/Alert.php
@@ -46,7 +46,7 @@ class Alert extends Widget
* the [[begin()]] and [[end()]] calls of the Alert widget will also be treated
* as the body content, and will be rendered before this.
*/
- public $body;
+ public string $body;
/**
* @var array|false the options for rendering the close button tag.
* The close button is displayed in the header of the modal window. Clicking
@@ -55,7 +55,6 @@ class Alert extends Widget
* The following special options are supported:
*
* - tag: string, the tag name of the button. Defaults to 'button'.
- * - label: string, the label of the button. Defaults to '×'.
*
* The rest of the options will be rendered as the HTML attributes of the button tag.
* Please refer to the [Alert documentation](https://getbootstrap.com/docs/5.0/components/alerts/)
@@ -91,7 +90,7 @@ class Alert extends Widget
* Renders the alert body and the close button (if any).
* @return string the rendering result
*/
- protected function renderBodyEnd()
+ protected function renderBodyEnd(): string
{
return $this->body . "\n" . $this->renderCloseButton() . "\n";
}
@@ -104,14 +103,8 @@ class Alert extends Widget
{
if (($closeButton = $this->closeButton) !== false) {
$tag = ArrayHelper::remove($closeButton, 'tag', 'button');
- $label = ArrayHelper::remove($closeButton, 'label', Html::tag('span', '×', [
- 'aria-hidden' => 'true',
- ]));
- if ($tag === 'button' && !isset($closeButton['type'])) {
- $closeButton['type'] = 'button';
- }
- return Html::tag($tag, $label, $closeButton);
+ return Html::tag($tag, '', $closeButton);
} else {
return null;
}
@@ -127,8 +120,10 @@ class Alert extends Widget
if ($this->closeButton !== false) {
$this->closeButton = array_merge([
- 'data-dismiss' => 'alert',
- 'class' => ['widget' => 'close'],
+ 'type' => 'button',
+ 'class' => ['widget' => 'btn-close'],
+ 'data' => ['bs-dismiss' => 'alert'],
+ 'aria' => ['label' => 'Close']
], $this->closeButton);
Html::addCssClass($this->options, ['toggle' => 'alert-dismissible']);
diff --git a/src/BootstrapAsset.php b/src/BootstrapAsset.php
index e2f442c..951ae11 100644
--- a/src/BootstrapAsset.php
+++ b/src/BootstrapAsset.php
@@ -14,7 +14,5 @@ class BootstrapAsset extends AssetBundle
'css/bootstrap.css',
];
- public $js = [
- 'js/bootstrap.bundle.js',
- ];
+ public $js = [];
}
diff --git a/src/BootstrapWidgetTrait.php b/src/BootstrapWidgetTrait.php
index 810cede..777a80c 100644
--- a/src/BootstrapWidgetTrait.php
+++ b/src/BootstrapWidgetTrait.php
@@ -94,6 +94,4 @@ trait BootstrapWidgetTrait
$this->getView()->registerJs(implode("\n", $js));
}
}
-
- abstract function getView();
}
diff --git a/src/Breadcrumbs.php b/src/Breadcrumbs.php
index 50e63c7..c84d5a2 100644
--- a/src/Breadcrumbs.php
+++ b/src/Breadcrumbs.php
@@ -89,6 +89,9 @@ class Breadcrumbs extends Widget
Html::addCssClass($this->options, ['widget' => 'breadcrumb']);
}
+ /**
+ * {@inheritDoc}
+ */
public function run(): string
{
if (!isset($this->options['id'])) {
@@ -98,8 +101,6 @@ class Breadcrumbs extends Widget
/** @psalm-suppress InvalidArgument */
Html::addCssClass($this->options, ['widget' => 'breadcrumb']);
- $this->registerPlugin('breadcrumb');
-
if (empty($this->links)) {
return '';
}
@@ -133,7 +134,7 @@ class Breadcrumbs extends Widget
* @param string $template the template to be used to rendered the link. The token "{link}" will be replaced by the
* link.
*
- * @throws JsonException|RuntimeException if `$link` does not have "label" element.
+ * @throws RuntimeException if `$link` does not have "label" element.
*
* @return string the rendering result
*/
diff --git a/src/Button.php b/src/Button.php
index dda7621..6ddff37 100644
--- a/src/Button.php
+++ b/src/Button.php
@@ -37,6 +37,7 @@ class Button extends Widget
/**
* Initializes the widget.
* If you override this method, make sure you call the parent implementation first.
+ * @throws \yii\base\InvalidConfigException
*/
public function init()
{
@@ -51,8 +52,10 @@ class Button extends Widget
*/
public function run(): string
{
- $this->registerPlugin('button');
- return Html::tag($this->tagName, $this->encodeLabel ? Html::encode($this->label) : $this->label,
- $this->options);
+ return Html::tag(
+ $this->tagName,
+ $this->encodeLabel ? Html::encode($this->label) : $this->label,
+ $this->options
+ );
}
}
diff --git a/src/ButtonDropdown.php b/src/ButtonDropdown.php
index 03c69c4..74dafd3 100644
--- a/src/ButtonDropdown.php
+++ b/src/ButtonDropdown.php
@@ -147,13 +147,12 @@ class ButtonDropdown extends Widget
if ($this->split) {
$buttonOptions = $this->buttonOptions;
- $this->buttonOptions['data-toggle'] = 'dropdown';
- $this->buttonOptions['aria-haspopup'] = 'true';
- $this->buttonOptions['aria-expanded'] = 'false';
+ $this->buttonOptions['data'] = ['bs-toggle' => 'dropdown'];
+ $this->buttonOptions['aria'] = ['expanded' => 'false'];
Html::addCssClass($this->buttonOptions, ['toggle' => 'dropdown-toggle dropdown-toggle-split']);
unset($buttonOptions['id']);
$splitButton = Button::widget([
- 'label' => 'Toggle Dropdown',
+ 'label' => 'Toggle Dropdown',
'encodeLabel' => false,
'options' => $this->buttonOptions,
'view' => $this->getView(),
@@ -161,9 +160,8 @@ class ButtonDropdown extends Widget
} else {
$buttonOptions = $this->buttonOptions;
Html::addCssClass($buttonOptions, ['toggle' => 'dropdown-toggle']);
- $buttonOptions['data-toggle'] = 'dropdown';
- $buttonOptions['aria-haspopup'] = 'true';
- $buttonOptions['aria-expanded'] = 'false';
+ $buttonOptions['data'] = ['bs-toggle' => 'dropdown'];
+ $buttonOptions['aria'] = ['expanded' => 'false'];
$splitButton = '';
}
diff --git a/src/Carousel.php b/src/Carousel.php
index 0085ac4..3495ae8 100644
--- a/src/Carousel.php
+++ b/src/Carousel.php
@@ -76,7 +76,8 @@ class Carousel extends Widget
/**
- * Initializes the widget.
+ * {@inheritDoc}
+ * @throws InvalidConfigException
*/
public function init()
{
@@ -91,9 +92,10 @@ class Carousel extends Widget
* {@inheritdoc}
* @throws InvalidConfigException
*/
- public function run()
+ public function run(): string
{
$this->registerPlugin('carousel');
+
return implode("\n", [
Html::beginTag('div', $this->options),
$this->renderIndicators(),
@@ -107,21 +109,28 @@ class Carousel extends Widget
* Renders carousel indicators.
* @return string the rendering result
*/
- public function renderIndicators()
+ public function renderIndicators(): string
{
if ($this->showIndicators === false) {
return '';
}
$indicators = [];
for ($i = 0, $count = count($this->items); $i < $count; $i++) {
- $options = ['data-target' => '#' . $this->options['id'], 'data-slide-to' => $i];
+ $options = [
+ 'data' => [
+ 'bs-target' => '#' . $this->options['id'],
+ 'bs-slide-to' => $i
+ ],
+ 'type' => 'button'
+ ];
if ($i === 0) {
Html::addCssClass($options, ['activate' => 'active']);
+ $options['aria']['current'] = 'true';
}
- $indicators[] = Html::tag('li', '', $options);
+ $indicators[] = Html::tag('button', '', $options);
}
- return Html::tag('ol', implode("\n", $indicators), ['class' => ['carousel-indicators']]);
+ return Html::tag('div', implode("\n", $indicators), ['class' => ['carousel-indicators']]);
}
/**
@@ -129,7 +138,7 @@ class Carousel extends Widget
* @return string the rendering result
* @throws InvalidConfigException
*/
- public function renderItems()
+ public function renderItems(): string
{
$items = [];
for ($i = 0, $count = count($this->items); $i < $count; $i++) {
@@ -145,8 +154,9 @@ class Carousel extends Widget
* @param int $index the item index as the first item should be set to `active`
* @return string the rendering result
* @throws InvalidConfigException if the item is invalid
+ * @throws \Exception
*/
- public function renderItem($item, $index)
+ public function renderItem($item, int $index): string
{
if (is_string($item)) {
$content = $item;
@@ -181,15 +191,21 @@ class Carousel extends Widget
public function renderControls()
{
if (isset($this->controls[0], $this->controls[1])) {
- return Html::a($this->controls[0], '#' . $this->options['id'], [
+ return Html::button($this->controls[0], [
'class' => 'carousel-control-prev',
- 'data-slide' => 'prev',
- 'role' => 'button',
+ 'data' => [
+ 'bs-target' => '#' . $this->options['id'],
+ 'bs-slide' => 'prev'
+ ],
+ 'type' => 'button',
]) . "\n"
- . Html::a($this->controls[1], '#' . $this->options['id'], [
+ . Html::button($this->controls[1], [
'class' => 'carousel-control-next',
- 'data-slide' => 'next',
- 'role' => 'button',
+ 'data' => [
+ 'bs-target' => '#' . $this->options['id'],
+ 'bs-slide' => 'next'
+ ],
+ 'type' => 'button',
]);
} elseif ($this->controls === false) {
return '';
diff --git a/src/Dropdown.php b/src/Dropdown.php
index 6d3a9c6..f713377 100644
--- a/src/Dropdown.php
+++ b/src/Dropdown.php
@@ -97,7 +97,7 @@ class Dropdown extends Widget
foreach ($items as $item) {
if (is_string($item)) {
$lines[] = ($item === '-')
- ? Html::tag('div', '', ['class' => 'dropdown-divider'])
+ ? Html::tag('hr', '', ['class' => 'dropdown-divider'])
: $item;
continue;
}
@@ -120,6 +120,7 @@ class Dropdown extends Widget
ArrayHelper::setValue($linkOptions, 'aria-disabled', 'true');
Html::addCssClass($linkOptions, ['disable' => 'disabled']);
} elseif ($active) {
+ ArrayHelper::setValue($linkOptions, 'aria-current', 'true');
Html::addCssClass($linkOptions, ['activate' => 'active']);
}
@@ -141,8 +142,7 @@ class Dropdown extends Widget
$lines[] = Html::beginTag('div', array_merge_recursive(['class' => ['dropdown'], 'aria-expanded' => 'false'], $itemOptions));
$lines[] = Html::a($label, $url, array_merge([
- 'data-toggle' => 'dropdown',
- 'aria-haspopup' => 'true',
+ 'data-bs-toggle' => 'dropdown',
'aria-expanded' => 'false',
'role' => 'button',
], $linkOptions));
diff --git a/src/LinkPager.php b/src/LinkPager.php
index 77bad65..ae17a27 100644
--- a/src/LinkPager.php
+++ b/src/LinkPager.php
@@ -102,12 +102,12 @@ class LinkPager extends Widget
* @var string|bool the label for the "next" page button. Note that this will NOT be HTML-encoded.
* If this property is false, the "next" page button will not be displayed.
*/
- public $nextPageLabel = "»\nNext";
+ public $nextPageLabel = '»«\nPrevious";
+ public $prevPageLabel = '«';
/**
* @var string|bool the text label for the "first" page button. Note that this will NOT be HTML-encoded.
* If it's specified as true, page number will be used as label.
@@ -285,6 +285,7 @@ class LinkPager extends Widget
$linkOptions['data-page'] = $page;
if ($active) {
+ $options['aria'] = ['current' => 'true'];
Html::addCssClass($options, $this->activePageCssClass);
}
if ($disabled) {
diff --git a/src/Modal.php b/src/Modal.php
index 0e7c3c9..912b081 100644
--- a/src/Modal.php
+++ b/src/Modal.php
@@ -51,35 +51,35 @@ class Modal extends Widget
/**
* @var string the tile content in the modal window.
*/
- public $title;
+ public string $title;
/**
* @var array additional title options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
- public $titleOptions = [];
+ public array $titleOptions = [];
/**
* @var array additional header options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
- public $headerOptions = [];
+ public array $headerOptions = [];
/**
* @var array body options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
- public $bodyOptions = [];
+ public array $bodyOptions = [];
/**
- * @var string the footer content in the modal window.
+ * @var string|null the footer content in the modal window.
*/
- public $footer;
+ public ?string $footer;
/**
* @var array additional footer options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
*/
- public $footerOptions = [];
+ public array $footerOptions = [];
/**
- * @var string the modal size. Can be [[SIZE_LARGE]] or [[SIZE_SMALL]], or empty for default.
+ * @var string|null the modal size. Can be [[SIZE_LARGE]] or [[SIZE_SMALL]], or empty for default.
*/
- public $size;
+ public ?string $size;
/**
* @var array|false the options for rendering the close button tag.
* The close button is displayed in the header of the modal window. Clicking
@@ -116,24 +116,25 @@ class Modal extends Widget
* When true the modal-dialog-centered class will be added to the modal-dialog
* @since 2.0.9
*/
- public $centerVertical = false;
+ public bool $centerVertical = false;
/**
* @var boolean whether to make the modal body scrollable
*
* When true the modal-dialog-scrollable class will be added to the modal-dialog
* @since 2.0.9
*/
- public $scrollable = false;
+ public bool $scrollable = false;
/**
* @var array modal dialog options
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
* @since 2.0.9
*/
- public $dialogOptions = [];
+ public array $dialogOptions = [];
/**
- * Initializes the widget.
+ * {@inheritDoc}
+ * @throws \yii\base\InvalidConfigException
*/
public function init()
{
@@ -167,10 +168,10 @@ class Modal extends Widget
* Renders the header HTML markup of the modal
* @return string the rendering result
*/
- protected function renderHeader()
+ protected function renderHeader(): string
{
$button = $this->renderCloseButton();
- if ($this->title !== null) {
+ if (isset($this->title)) {
Html::addCssClass($this->titleOptions, ['widget' => 'modal-title']);
$header = Html::tag('h5', $this->title, $this->titleOptions);
} else {
@@ -190,7 +191,7 @@ class Modal extends Widget
* Renders the opening tag of the modal body.
* @return string the rendering result
*/
- protected function renderBodyBegin()
+ protected function renderBodyBegin(): string
{
Html::addCssClass($this->bodyOptions, ['widget' => 'modal-body']);
return Html::beginTag('div', $this->bodyOptions);
@@ -200,7 +201,7 @@ class Modal extends Widget
* Renders the closing tag of the modal body.
* @return string the rendering result
*/
- protected function renderBodyEnd()
+ protected function renderBodyEnd(): string
{
return Html::endTag('div');
}
@@ -209,9 +210,9 @@ class Modal extends Widget
* Renders the HTML markup for the footer of the modal
* @return string the rendering result
*/
- protected function renderFooter()
+ protected function renderFooter(): ?string
{
- if ($this->footer !== null) {
+ if (isset($this->footer)) {
Html::addCssClass($this->footerOptions, ['widget' => 'modal-footer']);
return Html::tag('div', "\n" . $this->footer . "\n", $this->footerOptions);
} else {
@@ -223,7 +224,7 @@ class Modal extends Widget
* Renders the toggle button.
* @return string the rendering result
*/
- protected function renderToggleButton()
+ protected function renderToggleButton(): ?string
{
if (($toggleButton = $this->toggleButton) !== false) {
$tag = ArrayHelper::remove($toggleButton, 'tag', 'button');
@@ -239,15 +240,12 @@ class Modal extends Widget
* Renders the close button.
* @return string the rendering result
*/
- protected function renderCloseButton()
+ protected function renderCloseButton(): ?string
{
if (($closeButton = $this->closeButton) !== false) {
$tag = ArrayHelper::remove($closeButton, 'tag', 'button');
- $label = ArrayHelper::remove($closeButton, 'label', Html::tag('span', '×', [
- 'aria-hidden' => 'true',
- ]));
- return Html::tag($tag, $label, $closeButton);
+ return Html::tag($tag, '', $closeButton);
} else {
return null;
}
@@ -260,47 +258,43 @@ class Modal extends Widget
protected function initOptions()
{
$this->options = array_merge([
- 'class' => 'fade',
- 'role' => 'dialog',
'tabindex' => -1,
'aria-hidden' => 'true',
], $this->options);
- Html::addCssClass($this->options, ['widget' => 'modal']);
+ Html::addCssClass($this->options, ['widget' => 'modal fade']);
- if ($this->clientOptions !== false) {
+ if (!empty($this->clientOptions)) {
$this->clientOptions = array_merge(['show' => false], $this->clientOptions);
}
$this->titleOptions = array_merge([
'id' => $this->options['id'] . '-label',
], $this->titleOptions);
- if (!isset($this->options['aria-label'], $this->options['aria-labelledby']) && $this->title !== null) {
+ if (!isset($this->options['aria-label'], $this->options['aria-labelledby']) && isset($this->title)) {
$this->options['aria-labelledby'] = $this->titleOptions['id'];
}
if ($this->closeButton !== false) {
$this->closeButton = array_merge([
- 'data-dismiss' => 'modal',
- 'class' => 'close',
+ 'data-bs-dismiss' => 'modal',
+ 'class' => 'btn-close',
'type' => 'button',
+ 'aria-label' => 'Close'
], $this->closeButton);
}
if ($this->toggleButton !== false) {
$this->toggleButton = array_merge([
- 'data-toggle' => 'modal',
+ 'data-bs-toggle' => 'modal',
'type' => 'button',
], $this->toggleButton);
- if (!isset($this->toggleButton['data-target']) && !isset($this->toggleButton['href'])) {
- $this->toggleButton['data-target'] = '#' . $this->options['id'];
+ if (!isset($this->toggleButton['data-bs-target']) && !isset($this->toggleButton['href'])) {
+ $this->toggleButton['data-bs-target'] = '#' . $this->options['id'];
}
}
- $this->dialogOptions = array_merge([
- 'role' => 'document',
- ], $this->dialogOptions);
Html::addCssClass($this->dialogOptions, ['widget' => 'modal-dialog']);
- if ($this->size) {
+ if (isset($this->size)) {
Html::addCssClass($this->dialogOptions, ['size' => $this->size]);
}
if ($this->centerVertical) {
diff --git a/src/Nav.php b/src/Nav.php
index f09eead..bd152d7 100644
--- a/src/Nav.php
+++ b/src/Nav.php
@@ -103,7 +103,7 @@ class Nav extends Widget
/**
- * Initializes the widget.
+ * {@inheritDoc}
*/
public function init()
{
@@ -120,7 +120,7 @@ class Nav extends Widget
/**
* Renders the widget.
* @return string
- * @throws InvalidConfigException
+ * @throws InvalidConfigException|\Throwable
*/
public function run(): string
{
@@ -131,7 +131,7 @@ class Nav extends Widget
/**
* Renders widget items.
* @return string
- * @throws InvalidConfigException
+ * @throws InvalidConfigException|\Throwable
*/
public function renderItems(): string
{
@@ -175,7 +175,9 @@ class Nav extends Widget
Html::addCssClass($options, ['widget' => 'nav-item']);
Html::addCssClass($linkOptions, ['widget' => 'nav-link']);
} else {
- $linkOptions['data-toggle'] = 'dropdown';
+ $linkOptions['data-bs-toggle'] = 'dropdown';
+ $linkOptions['role'] = 'button';
+ $linkOptions['aria-expanded'] = 'false';
Html::addCssClass($options, ['widget' => 'dropdown nav-item']);
Html::addCssClass($linkOptions, ['widget' => 'dropdown-toggle nav-link']);
if (is_array($items)) {
@@ -220,7 +222,9 @@ class Nav extends Widget
* Check to see if a child item is active optionally activating the parent.
* @param array $items @see items
* @param bool $active should the parent be active too
- * @return array @see items
+ * @return array
+ * @see items
+ * @throws \Exception
*/
protected function isChildActive(array $items, bool &$active): array
{
@@ -256,6 +260,7 @@ class Nav extends Widget
* be considered active.
* @param array $item the menu item to be checked
* @return bool whether the menu item is active
+ * @throws \Exception
*/
protected function isItemActive(array $item): bool
{
diff --git a/src/NavBar.php b/src/NavBar.php
index 88bf6f1..b2cf1cc 100644
--- a/src/NavBar.php
+++ b/src/NavBar.php
@@ -84,7 +84,7 @@ class NavBar extends Widget
*/
public string $screenReaderToggleText = 'Toggle navigation';
/**
- * @var string the toggle button content. Defaults to bootstrap 4 default ``
+ * @var string the toggle button content. Defaults to bootstrap 5 default ``
*/
public string $togglerContent = '';
/**
@@ -109,7 +109,7 @@ class NavBar extends Widget
/**
- * Initializes the widget.
+ * {@inheritDoc}
*/
public function init()
{
@@ -176,29 +176,6 @@ class NavBar extends Widget
BootstrapPluginAsset::register($this->getView());
}
- /**
- * Renders collapsible toggle button.
- * @return string the rendering toggle button.
- */
- protected function renderToggleButton(): string
- {
- $options = $this->togglerOptions;
- Html::addCssClass($options, ['widget' => 'navbar-toggler']);
- return Html::button(
- $this->togglerContent,
- ArrayHelper::merge($options, [
- 'type' => 'button',
- 'data' => [
- 'toggle' => 'collapse',
- 'target' => '#' . $this->collapseOptions['id'],
- ],
- 'aria-controls' => $this->collapseOptions['id'],
- 'aria-expanded' => 'false',
- 'aria-label' => $this->screenReaderToggleText,
- ])
- );
- }
-
/**
* Container options setter for backwards compatibility
* @param array $collapseOptions
@@ -208,4 +185,30 @@ class NavBar extends Widget
{
$this->collapseOptions = $collapseOptions;
}
+
+ /**
+ * Renders collapsible toggle button.
+ * @return string the rendering toggle button.
+ */
+ protected function renderToggleButton(): string
+ {
+ $options = $this->togglerOptions;
+ Html::addCssClass($options, ['widget' => 'navbar-toggler']);
+
+ return Html::button(
+ $this->togglerContent,
+ ArrayHelper::merge($options, [
+ 'type' => 'button',
+ 'data' => [
+ 'bs-toggle' => 'collapse',
+ 'bs-target' => '#' . $this->collapseOptions['id'],
+ ],
+ 'aria' => [
+ 'controls' => $this->collapseOptions['id'],
+ 'expanded' => 'false',
+ 'label' => $this->screenReaderToggleText,
+ ]
+ ])
+ );
+ }
}
diff --git a/src/Progress.php b/src/Progress.php
index a565588..f1de68d 100644
--- a/src/Progress.php
+++ b/src/Progress.php
@@ -80,17 +80,17 @@ class Progress extends Widget
/**
* @var string the button label. This property will only be considered if [[bars]] is empty
*/
- public $label;
+ public string $label;
/**
* @var int the amount of progress as a percentage. This property will only be considered if [[bars]] is empty
*/
- public $percent = 0;
+ public int $percent = 0;
/**
* @var array the HTML attributes of the bar. This property will only be considered if [[bars]] is empty
* @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
* @since 2.0.6
*/
- public $barOptions = [];
+ public array $barOptions = [];
/**
* @var array a set of bars that are stacked together to form a single progress bar.
* Each bar is an array of the following structure:
@@ -106,7 +106,7 @@ class Progress extends Widget
* ]
* ```
*/
- public $bars;
+ public array $bars;
/**
@@ -123,7 +123,7 @@ class Progress extends Widget
* {@inheritdoc}
* @throws InvalidConfigException
*/
- public function run()
+ public function run(): string
{
BootstrapAsset::register($this->getView());
return $this->renderProgress();
@@ -133,8 +133,9 @@ class Progress extends Widget
* Renders the progress.
* @return string the rendering result.
* @throws InvalidConfigException if the "percent" option is not set in a stacked progress bar.
+ * @throws \Exception
*/
- protected function renderProgress()
+ protected function renderProgress(): string
{
$out = Html::beginTag('div', $this->options) . "\n";
if (empty($this->bars)) {
@@ -164,14 +165,16 @@ class Progress extends Widget
* @param array $options the HTML attributes of the bar
* @return string the rendering result.
*/
- protected function renderBar($percent, $label = '', $options = [])
+ protected function renderBar(int $percent, string $label = '', array $options = []): string
{
$percent = (float)trim(rtrim((string)$percent, '%'));
$options = array_merge($options, [
'role' => 'progressbar',
- 'aria-valuenow' => $percent,
- 'aria-valuemin' => 0,
- 'aria-valuemax' => 100,
+ 'aria' => [
+ 'valuenow' => $percent,
+ 'valuemin' => 0,
+ 'valuemax' => 100,
+ ]
]);
Html::addCssClass($options, ['widget' => 'progress-bar']);
Html::addCssStyle($options, ['width' => $percent . '%'], true);
diff --git a/src/Tabs.php b/src/Tabs.php
index 1bf0a41..8d17c0e 100644
--- a/src/Tabs.php
+++ b/src/Tabs.php
@@ -165,6 +165,7 @@ class Tabs extends Widget
* @param array $items
* @param string $prefix
* @throws InvalidConfigException
+ * @throws \Exception
*/
protected function prepareItems(array &$items, string $prefix = '')
{
@@ -196,9 +197,9 @@ class Tabs extends Widget
ArrayHelper::setValue($items[$n], 'url', '#' . $options['id']);
ArrayHelper::setValue($items[$n], 'linkOptions.data.toggle', 'tab');
ArrayHelper::setValue($items[$n], 'linkOptions.role', 'tab');
- ArrayHelper::setValue($items[$n], 'linkOptions.aria-controls', $options['id']);
+ ArrayHelper::setValue($items[$n], 'linkOptions.aria.controls', $options['id']);
if (!$disabled) {
- ArrayHelper::setValue($items[$n], 'linkOptions.aria-selected', $selected ? 'true' : 'false');
+ ArrayHelper::setValue($items[$n], 'linkOptions.aria.selected', $selected ? 'true' : 'false');
}
} else {
continue;
@@ -236,6 +237,7 @@ class Tabs extends Widget
*
* This method activates the first tab that is visible and
* not explicitly set to inactive (`'active' => false`).
+ * @throws \Exception
*/
protected function activateFirstVisibleTab()
{
diff --git a/src/Toast.php b/src/Toast.php
index f3213d1..03ee188 100644
--- a/src/Toast.php
+++ b/src/Toast.php
@@ -134,7 +134,7 @@ class Toast extends Widget
{
$button = $this->renderCloseButton();
$tag = ArrayHelper::remove($this->titleOptions, 'tag', 'strong');
- Html::addCssClass($this->titleOptions, ['widget' => 'mr-auto']);
+ Html::addCssClass($this->titleOptions, ['widget' => 'me-auto']);
$title = Html::tag($tag, $this->title === null ? '' : $this->title, $this->titleOptions);
if ($this->dateTime !== false) {
@@ -175,11 +175,8 @@ class Toast extends Widget
protected function renderCloseButton(): string
{
$tag = ArrayHelper::remove($this->closeButton, 'tag', 'button');
- $label = ArrayHelper::remove($this->closeButton, 'label', Html::tag('span', '×', [
- 'aria-hidden' => 'true',
- ]));
- return Html::tag($tag, "\n" . $label . "\n", $this->closeButton);
+ return Html::tag($tag, '', $this->closeButton);
}
/**
@@ -192,8 +189,8 @@ class Toast extends Widget
$this->closeButton = array_merge([
'aria' => ['label' => 'Close'],
- 'data' => ['dismiss' => 'toast'],
- 'class' => ['widget' => 'ml-2 mb-1 close'],
+ 'data' => ['bs-dismiss' => 'toast'],
+ 'class' => ['widget' => 'btn-close'],
'type' => 'button',
], $this->closeButton);
diff --git a/src/ToggleButtonGroup.php b/src/ToggleButtonGroup.php
index 0b17bed..6502141 100644
--- a/src/ToggleButtonGroup.php
+++ b/src/ToggleButtonGroup.php
@@ -68,8 +68,8 @@ class ToggleButtonGroup extends InputWidget
{
parent::init();
$this->registerPlugin('button');
- Html::addCssClass($this->options, ['widget' => 'btn-group-toggle']);
- $this->options['data-toggle'] = 'buttons';
+ Html::addCssClass($this->options, ['widget' => 'btn-group']);
+ $this->options['role'] = 'group';
}
/**
diff --git a/tests/AccordionTest.php b/tests/AccordionTest.php
index 6b460cd..036704f 100644
--- a/tests/AccordionTest.php
+++ b/tests/AccordionTest.php
@@ -71,41 +71,41 @@ class AccordionTest extends TestCase
$this->assertEqualsWithoutLE(<<
-